Skip to content

Fs Module ​

Provides file system and path resolution utilities.
Includes fuzzy path resolution, safe file and directory creation, atomic JSON read and write helpers, and common path accessors.

get_cwd() ​

python
def get_cwd() -> Path

The path to the current working directory.

get_home() ​

python
def get_home() -> Path

The path to the user's home directory.

get_script_dir() ​

python
def get_script_dir() -> Path

The path to the directory of the current script.

resolve_path() ​

python
def resolve_path(
    rel_path: Path | str,
    /,
    search_in: Path | str | PathsList | None = None,
    *,
    fuzzy_match: bool = False,
    raise_error: bool = False,
) -> Path | None

Tries to resolve and extend a relative path to an absolute path.


  • rel_path – The relative path to extend.
  • search_in – A directory or a list of directories to search in, in addition to the predefined directories (see exact procedure below).
  • fuzzy_match – If true, it will try to find the closest matching file/folder names in the search_in directories, allowing for typos in rel_path and search_in.
  • raise_error – If true, raises a PathNotFoundError if the path couldn't be found (otherwise it returns None).

If the rel_path couldn't be located in predefined directories, it will be searched in the search_in directory/s.
If the rel_path is still not found, it returns None or raises a PathNotFoundError if raise_error is true.


Example Usage ​

python
import xulbux as xx

# Resolve a relative file with fuzzy matching:
resolved_path = xx.fs.resolve_path("config.json", search_in="./settings", fuzzy_match=True)

resolve_or_create_path() ​

python
def resolve_or_create_path(
    rel_path: Path | str,
    /,
    search_in: Path | str | PathsList | None = None,
    *,
    prefer_script_dir: bool = True,
    fuzzy_match: bool = False,
) -> Path

Tries to locate and extend a relative path to an absolute path, and if the rel_path couldn't be located, it generates a path, as if it was located.


  • rel_path – The relative path to extend or make.
  • search_in – A directory or a list of directories to search in, in addition to the predefined directories (see exact procedure below).
  • prefer_script_dir – If true, the script directory is preferred when making a new path (otherwise the CWD is preferred).
  • fuzzy_match – If true, it will try to find the closest matching file/folder names in the search_in directories, allowing for typos in rel_path and search_in.

If the rel_path couldn't be located in predefined directories, it will be searched in the search_in directory/s.
If the rel_path is still not found, it will makes a path that points to where the rel_path would be in the script directory, even though the rel_path doesn't exist there.
If prefer_script_dir is false, it will instead make a path that points to where the rel_path would be in the CWD.


Example Usage ​

python
import xulbux as xx

# Resolve existing file or compute fallback path in script directory:
target_path = xx.fs.resolve_or_create_path("data/cache.json")

create_file() ​

python
def create_file(file_path: Path | str, content: str = "", /, *, force: bool = False) -> Path

Create a file with or without content.


  • file_path – The path where the file should be created.
  • content – The content to write into the file.
  • force – If true, will overwrite existing files without throwing an error (errors explained below).

The method will throw a FileExistsError if a file with the same name already exists and a SameContentFileExistsError if a file with the same name and same content already exists.


Example Usage ​

python
import xulbux as xx

# Create file safely or force overwrite:
file_path = xx.fs.create_file("output/result.txt", "Generated content", force=True)

rename_file_ext() ​

python
def rename_file_ext(
    file_path: Path | str,
    new_extension: str,
    /,
    *,
    full_extension: bool = False,
    camel_case_filename: bool = False,
) -> Path

Rename the extension of a file.


  • file_path – The path to the file whose extension should be changed.
  • new_extension – The new extension for the file (with or without dot).
  • full_extension – Whether to replace the full extension (e.g., .tar.gz) or just the last part of it (e.g., .gz).
  • camel_case_filename – Whether to convert the filename to CamelCase in addition to changing the files extension.

Example Usage ​

python
import xulbux as xx

# Rename single extension:
new_path = xx.fs.rename_file_ext("archive.tar.gz", ".zip")  # archive.tar.zip

# Replace full compound extension and convert to CamelCase:
new_path = xx.fs.rename_file_ext(
    "my_data_file.tar.gz",
    ".zip",
    full_extension=True,
    camel_case_filename=True,
)  # MyDataFile.zip

remove() ​

python
def remove(path: Path | str, /, *, only_content: bool = False) -> None

Removes the directory or the directory's content at the specified path.


  • path – The path to the directory or file to remove.
  • only_content – If true, only the content of the directory is removed and the directory itself is kept.

read_json() ​

python
def read_json(
    json_file: Path | str,
    /,
    *,
    comment_start: str = ">>",
    comment_end: str = "<<",
    return_original: bool = False,
) -> dict[str, Any] | tuple[dict[str, Any], dict[str, Any]]

Read JSON files, ignoring comments.


  • json_file – The path (relative or absolute) to the JSON file to read.
  • comment_start – The string that indicates the start of a comment.
  • comment_end – The string that indicates the end of a comment.
  • return_original – If true, the original JSON data is returned additionally:
    python
    (processed_json, original_json)

For more detailed information about the comment handling, see the _data_module.remove_comments() method documentation.


Example Usage ​

python
import xulbux as xx

# Read JSON and strip comments:
config = xx.fs.read_json("config.json")

# Read both stripped and raw original data with comments:
clean_data, raw_data = xx.fs.read_json("config.json", return_original=True)

create_json() ​

python
def create_json(
    json_file: Path | str,
    data: dict[str, Any],
    /,
    *,
    indent: int = 2,
    compactness: Literal[0, 1, 2] = 1,
    force: bool = False,
) -> Path

Create a nicely formatted JSON file from a dictionary.


  • json_file – The path (relative or absolute) to the JSON file to create.
  • data – The dictionary data to write to the JSON file.
  • indent – The amount of spaces to use for indentation.
  • compactness – Can be 0, 1 or 2 and indicates how compact the data should be formatted (see _data_module.render() for more info).
  • force – If true, will overwrite existing files without throwing an error (errors explained below).

The method will throw a FileExistsError if a file with the same name already exists and a SameContentFileExistsError if a file with the same name and same content already exists.


Example Usage ​

python
import xulbux as xx

data = {
    "app": "my-tool",
    "version": "1.0.0",
    "settings": {"debug": True, "workers": 4},
}

file_path = xx.fs.create_json("config.json", data, indent=2, force=True)

update_json() ​

python
def update_json(
    json_file: Path | str,
    update_values: dict[str, Any],
    /,
    *,
    comment_start: str = ">>",
    comment_end: str = "<<",
    path_sep: str = "->",
) -> None

Update single/multiple values inside JSON files, without needing to know the rest of the data.


  • json_file – The path (relative or absolute) to the JSON file to update.
  • update_values – A dictionary where keys are the paths to the values to update and values are the new values to set. Dictionaries are addressed by key name, and sequences by integer index.
    Missing paths will automatically be created.
  • comment_start – The string that indicates the start of a comment.
  • comment_end – The string that indicates the end of a comment.
  • path_sep – The separator used inside the value-paths in update_values.

For more detailed information about comment handling, see the data.remove_comments() method documentation.


Example Usage ​

python
import xulbux as xx

data = {
    "healthy": {
        "fruits": ["apples", "bananas", "oranges"],
        "vegetables": ["carrots", "broccoli", "celery"],
    },
}
xx.fs.create_json("diet.json", data, force=True)

# Update nested list values by index and dict values by key name:
xx.fs.update_json(
    "diet.json",
    {
        "healthy->fruits->0": "strawberries",
        "healthy->vegetables": ["spinach", "kale"],
    },
)
Updated JSON Data
python
{
    "healthy": {
        "fruits": ["strawberries", "bananas", "oranges"],
        "vegetables": ["spinach", "kale"],
    }
}

Released under the MIT License.