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_script_dir()
def get_script_dir() -> PathThe path to the directory of the current script.
resolve_path()
def resolve_path(
rel_path: Path | str,
/,
search_in: Path | str | PathsList | None = None,
*,
fuzzy_match: bool = False,
raise_error: bool = False,
) -> Path | NoneTries 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 thesearch_indirectories, allowing for typos inrel_pathandsearch_in.raise_error– If true, raises aPathNotFoundErrorif the path couldn't be found (otherwise it returnsNone).
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
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()
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,
) -> PathTries 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 thesearch_indirectories, allowing for typos inrel_pathandsearch_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
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()
def create_file(file_path: Path | str, content: str = "", /, *, force: bool = False) -> PathCreate 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
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()
def rename_file_ext(
file_path: Path | str,
new_extension: str,
/,
*,
full_extension: bool = False,
camel_case_filename: bool = False,
) -> PathRename 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
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.zipremove()
def remove(path: Path | str, /, *, only_content: bool = False) -> NoneRemoves 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()
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
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()
def create_json(
json_file: Path | str,
data: dict[str, Any],
/,
*,
indent: int = 2,
compactness: Literal[0, 1, 2] = 1,
force: bool = False,
) -> PathCreate 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 be0,1or2and 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
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()
def update_json(
json_file: Path | str,
update_values: dict[str, Any],
/,
*,
comment_start: str = ">>",
comment_end: str = "<<",
path_sep: str = "->",
) -> NoneUpdate 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 inupdate_values.
For more detailed information about comment handling,
see the data.remove_comments() method documentation.
Example Usage
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"],
},
){
"healthy": {
"fruits": ["strawberries", "bananas", "oranges"],
"vegetables": ["spinach", "kale"],
}
}