Skip to content

API Reference

Complete API documentation for YAPFM, including all classes, methods, and their parameters.

📚 Table of Contents

  1. Core Classes
  2. Strategies
  3. Mixins
  4. Registry
  5. Proxy
  6. Exceptions
  7. Helpers

🏗️ Core Classes

YAPFileManager

The main class that combines all functionality through mixins.

from yapfm import YAPFileManager

Constructor

YAPFileManager(
    path: Union[str, Path],
    strategy: Optional[BaseFileStrategy] = None,
    *,
    auto_create: bool = False,
    **kwargs: Any
) -> None

Parameters: - path (Union[str, Path]): Path to the file to manage - strategy (Optional[BaseFileStrategy]): Custom strategy for file handling. If None, auto-detects based on file extension - auto_create (bool): Whether to create the file if it doesn't exist. Default: False - **kwargs (Any): Additional keyword arguments passed to mixins

Example:

# Basic usage
fm = YAPFileManager("config.json")

# With auto-creation
fm = YAPFileManager("config.json", auto_create=True)

# With custom strategy
from yapfm.strategies import JsonStrategy
fm = YAPFileManager("config.json", strategy=JsonStrategy())

Properties

data
@property
data -> Dict[str, Any]

Get or set the file data. Automatically loads the file on first access if not loaded.

Getter: - Returns: Dictionary containing the file data - Note: Automatically loads the file on first access if it hasn't been loaded yet

Setter: - Parameters: value (Dict[str, Any]): Dictionary containing the data to set - Raises: TypeError if value is not a dictionary

Example:

# Get data (auto-loads if needed)
data = fm.data

# Set data
fm.data = {"key": "value"}

Methods

All methods from the mixins are available. See Mixins section for detailed documentation.

FileManagerProxy

Proxy wrapper that adds logging, metrics, and auditing capabilities.

from yapfm import FileManagerProxy

Constructor

FileManagerProxy(
    manager: Any,
    *,
    enable_logging: bool = False,
    enable_metrics: bool = False,
    enable_audit: bool = False,
    logger: Optional[logging.Logger] = None,
    audit_hook: Optional[Callable[[str, tuple, dict, Any], None]] = None
) -> None

Parameters: - manager (Any): The underlying FileManager instance to proxy - enable_logging (bool): Enable debug logging of method calls and results. Default: False - enable_metrics (bool): Enable execution time measurement. Default: False - enable_audit (bool): Enable audit hook execution. Default: False - logger (Optional[logging.Logger]): Custom logger. Defaults to logging.getLogger(__name__) - audit_hook (Optional[Callable]): Custom hook called as audit_hook(method: str, args: tuple, kwargs: dict, result: Any)

Example:

from yapfm import YAPFileManager, FileManagerProxy
import logging

# Create file manager
fm = YAPFileManager("config.json")

# Create proxy with logging and metrics
proxy = FileManagerProxy(
    fm,
    enable_logging=True,
    enable_metrics=True,
    enable_audit=True
)

# Use proxy like the original manager
with proxy:
    proxy.set_key("value", dot_key="key")

🎯 Strategies

BaseFileStrategy

Abstract base protocol for all file handling strategies.

from yapfm.strategies import BaseFileStrategy

Methods

load
def load(self, file_path: Union[Path, str]) -> Any

Load data from a file.

Parameters: - file_path (Union[Path, str]): Path to the file to load

Returns: - Any: The parsed file contents, typically a dictionary or list

Raises: - FileNotFoundError: If the file doesn't exist - ValueError: If the file format is invalid

Example:

strategy = TomlStrategy()
data = strategy.load("config.toml")
print(data["database"]["host"])
save
def save(self, file_path: Union[Path, str], data: Any) -> None

Save data to a file.

Parameters: - file_path (Union[Path, str]): Path where to save the file - data (Any): The data to save, typically a dictionary or list

Raises: - PermissionError: If the file cannot be written due to permissions - ValueError: If the data cannot be serialized to the target format

Example:

strategy = TomlStrategy()
data = {"database": {"host": "localhost", "port": 5432}}
strategy.save("config.toml", data)
def navigate(
    self, 
    document: Any, 
    path: List[str], 
    create: bool = False
) -> Optional[Any]

Navigate through the document structure.

Parameters: - document (Any): The document to navigate through - path (List[str]): List of keys representing the path to traverse - create (bool): Whether to create missing intermediate structures

Returns: - Optional[Any]: The value at the specified path, or None if not found and create is False

Example:

strategy = TomlStrategy()
document = {"database": {"host": "localhost"}}
value = strategy.navigate(document, ["database", "host"])
print(value)  # "localhost"

# Create missing path
value = strategy.navigate(document, ["cache", "redis"], create=True)
print(document)  # {"database": {...}, "cache": {"redis": None}}

JsonStrategy

Strategy for handling JSON files.

from yapfm.strategies import JsonStrategy

Features: - Standard JSON with pretty printing - 2-space indentation - UTF-8 encoding support

Example:

strategy = JsonStrategy()
data = strategy.load("config.json")
strategy.save("output.json", data)

TomlStrategy

Strategy for handling TOML files.

from yapfm.strategies import TomlStrategy

Features: - Full TOML specification support - Comment and formatting preservation - Type-safe operations with tomlkit - Support for nested tables and arrays

Example:

strategy = TomlStrategy()
data = strategy.load("config.toml")
strategy.save("output.toml", data)

YamlStrategy

Strategy for handling YAML files.

from yapfm.strategies import YamlStrategy

Features: - YAML 1.2 with safe loading - UTF-8 encoding support - Pretty printing with proper indentation

Example:

strategy = YamlStrategy()
data = strategy.load("config.yaml")
strategy.save("output.yaml", data)

🔧 Mixins

FileOperationsMixin

Provides basic file operations.

Methods

exists
def exists(self) -> bool

Check if the file exists.

Returns: - bool: True if the file exists, False otherwise

Example:

if fm.exists():
    print("File exists")
is_dirty
def is_dirty(self) -> bool

Check if the file is dirty (has unsaved changes).

Returns: - bool: True if the file has unsaved changes, False otherwise

Example:

if fm.is_dirty():
    print("File has unsaved changes")
is_loaded
def is_loaded(self) -> bool

Check if the file is loaded in memory.

Returns: - bool: True if the file is loaded, False otherwise

Example:

if fm.is_loaded():
    print("File is loaded in memory")
load
def load(self) -> None

Load data from the file.

Raises: - FileNotFoundError: If the file doesn't exist and auto_create is False - ValueError: If the file format is invalid or corrupted - LoadFileError: If there's an error during the loading process

Example:

fm.load()  # Loads the file content into memory
save
def save(self) -> None

Save data to the file.

Raises: - PermissionError: If the file cannot be written due to permissions - ValueError: If the data format is invalid for the file type - FileWriteError: If there's an error during the writing process

Example:

fm.save()  # Saves the current data to disk
save_if_dirty
def save_if_dirty(self) -> None

Save the file only if it has been modified.

Example:

fm.save_if_dirty()  # Only saves if there are unsaved changes
reload
def reload(self) -> None

Reload data from the file, discarding any unsaved changes.

Example:

fm.reload()  # Reloads from disk, discards unsaved changes
mark_as_dirty
def mark_as_dirty(self) -> None

Mark the file as dirty (has unsaved changes).

Example:

fm.mark_as_dirty()  # Mark as having unsaved changes
mark_as_clean
def mark_as_clean(self) -> None

Mark the file as clean (no unsaved changes).

Example:

fm.mark_as_clean()  # Mark as clean
mark_as_loaded
def mark_as_loaded(self) -> None

Mark the file as loaded in memory.

Example:

fm.mark_as_loaded()  # Mark as loaded
unload
def unload(self) -> None

Unload the file from memory.

Example:

fm.unload()  # Free memory
create_empty_file
def create_empty_file(self) -> None

Create an empty file.

Example:

fm.create_empty_file()  # Creates empty file
load_if_not_loaded
def load_if_not_loaded(self) -> None

Load the file if it is not loaded.

Example:

fm.load_if_not_loaded()  # Load only if not already loaded

KeyOperationsMixin

Provides key-based data access with dot notation.

Methods

set_key
def set_key(
    self,
    value: Any,
    dot_key: Optional[str] = None,
    *,
    path: Optional[List[str]] = None,
    key_name: Optional[str] = None,
    overwrite: bool = True
) -> None

Set a value in the file using dot notation.

Parameters: - value (Any): The value to set - dot_key (Optional[str]): The dot-separated key - path (Optional[List[str]]): The path to the key - key_name (Optional[str]): The name of the key - overwrite (bool): Whether to overwrite the existing value. Default: True

Example:

# Using dot notation
fm.set_key("localhost", dot_key="database.host")

# Using path and key name
fm.set_key(5432, path=["database"], key_name="port")

# Only set if key doesn't exist
fm.set_key("default", dot_key="database.host", overwrite=False)
get_key
def get_key(
    self,
    dot_key: Optional[str] = None,
    *,
    path: Optional[List[str]] = None,
    key_name: Optional[str] = None,
    default: Any = None
) -> Any

Get a value from the file using dot notation.

Parameters: - dot_key (Optional[str]): The dot-separated key - path (Optional[List[str]]): The path to the key - key_name (Optional[str]): The name of the key - default (Any): The default value if the key is not found

Returns: - Any: The value at the specified path or default

Example:

# Using dot notation
host = fm.get_key(dot_key="database.host", default="localhost")

# Using path and key name
port = fm.get_key(path=["database"], key_name="port", default=5432)
has_key
def has_key(
    self,
    dot_key: Optional[str] = None,
    *,
    path: Optional[List[str]] = None,
    key_name: Optional[str] = None
) -> bool

Check if a key exists in the file using dot notation.

Parameters: - dot_key (Optional[str]): The dot-separated key - path (Optional[List[str]]): The path to the key - key_name (Optional[str]): The name of the key

Returns: - bool: True if the key exists, False otherwise

Example:

# Using dot notation
if fm.has_key(dot_key="database.host"):
    print("Database host exists")

# Using path and key name
if fm.has_key(path=["database"], key_name="port"):
    print("Database port exists")
delete_key
def delete_key(
    self,
    dot_key: Optional[str] = None,
    *,
    path: Optional[List[str]] = None,
    key_name: Optional[str] = None
) -> bool

Delete a key from the file using dot notation.

Parameters: - dot_key (Optional[str]): The dot-separated key - path (Optional[List[str]]): The path to the key - key_name (Optional[str]): The name of the key

Returns: - bool: True if the key was deleted, False if it didn't exist

Example:

# Using dot notation
deleted = fm.delete_key(dot_key="database.host")

# Using path and key name
deleted = fm.delete_key(path=["database"], key_name="port")

SectionOperationsMixin

Provides section-based data management.

Methods

set_section
def set_section(
    self,
    section_data: Dict[str, Any],
    dot_key: Optional[str] = None,
    *,
    path: Optional[List[str]] = None,
    section_name: Optional[str] = None,
    overwrite: bool = True
) -> None

Set an entire section in the file.

Parameters: - section_data (Dict[str, Any]): The section data to set - dot_key (Optional[str]): The dot-separated key for the section - path (Optional[List[str]]): The path to the section - section_name (Optional[str]): The name of the section - overwrite (bool): Whether to overwrite the existing section. Default: True

Example:

# Using dot notation
fm.set_section({
    "host": "localhost",
    "port": 5432,
    "ssl": True
}, dot_key="database")

# Using path and section name
fm.set_section({
    "version": "v1",
    "timeout": 30
}, path=["api"], section_name="config")
get_section
def get_section(
    self,
    dot_key: Optional[str] = None,
    *,
    path: Optional[List[str]] = None,
    section_name: Optional[str] = None,
    default: Optional[Dict[str, Any]] = None
) -> Optional[Dict[str, Any]]

Get an entire section from the file.

Parameters: - dot_key (Optional[str]): The dot-separated key for the section - path (Optional[List[str]]): The path to the section - section_name (Optional[str]): The name of the section - default (Optional[Dict[str, Any]]): The default value if the section is not found

Returns: - Optional[Dict[str, Any]]: The section data or default

Example:

# Using dot notation
db_config = fm.get_section(dot_key="database")

# Using path and section name
api_config = fm.get_section(path=["api"], section_name="config")
has_section
def has_section(
    self,
    dot_key: Optional[str] = None,
    *,
    path: Optional[List[str]] = None,
    section_name: Optional[str] = None
) -> bool

Check if a section exists in the file.

Parameters: - dot_key (Optional[str]): The dot-separated key for the section - path (Optional[List[str]]): The path to the section - section_name (Optional[str]): The name of the section

Returns: - bool: True if the section exists, False otherwise

Example:

# Using dot notation
if fm.has_section(dot_key="database"):
    print("Database section exists")

# Using path and section name
if fm.has_section(path=["api"], section_name="config"):
    print("API config section exists")
delete_section
def delete_section(
    self,
    dot_key: Optional[str] = None,
    *,
    path: Optional[List[str]] = None,
    section_name: Optional[str] = None
) -> bool

Delete an entire section from the file.

Parameters: - dot_key (Optional[str]): The dot-separated key for the section - path (Optional[List[str]]): The path to the section - section_name (Optional[str]): The name of the section

Returns: - bool: True if the section was deleted, False if it didn't exist

Example:

# Using dot notation
deleted = fm.delete_section(dot_key="database")

# Using path and section name
deleted = fm.delete_section(path=["api"], section_name="config")

ContextMixin

Provides context manager functionality.

Methods

enter
def __enter__(self) -> Self

Enter the context manager and load the file.

Returns: - Self: The file manager instance

Example:

with YAPFileManager("config.json") as fm:
    # File is automatically loaded
    fm.set_key("value", dot_key="key")
exit
def __exit__(self, exc_type, exc_val, exc_tb) -> None

Exit the context manager and save if dirty.

Parameters: - exc_type: Exception type - exc_val: Exception value - exc_tb: Exception traceback

Example:

with YAPFileManager("config.json") as fm:
    fm.set_key("value", dot_key="key")
    # File is automatically saved when exiting context
lazy_save
@contextmanager
def lazy_save(self, save_on_exit: bool = True) -> Iterator[Self]

Context manager for lazy saving.

Parameters: - save_on_exit (bool): Whether to save when exiting the context. Default: True

Returns: - Iterator[Self]: The file manager instance

Example:

with fm.lazy_save():
    fm.set_key("value1", dot_key="key1")
    fm.set_key("value2", dot_key="key2")
    # Save happens here when exiting lazy_save context
auto_save
@contextmanager
def auto_save(self, save_on_exit: bool = True) -> Iterator[Self]

Context manager for automatic saving.

Parameters: - save_on_exit (bool): Whether to save when exiting the context. Default: True

Returns: - Iterator[Self]: The file manager instance

Example:

with fm.auto_save():
    fm.set_key("value", dot_key="key")
    # Save happens here when exiting auto_save context

📋 Registry

FileStrategyRegistry

Registry for managing file strategies.

from yapfm.registry import FileStrategyRegistry

Class Methods

register_strategy
@classmethod
def register_strategy(
    cls,
    file_exts: Union[str, List[str]],
    strategy_cls: Type[BaseFileStrategy]
) -> None

Register one or multiple extensions for a strategy class.

Parameters: - file_exts (Union[str, List[str]]): File extension(s) to register the strategy for - strategy_cls (Type[BaseFileStrategy]): Strategy class to register

Raises: - TypeError: If the strategy does not inherit from BaseFileStrategy

Example:

from yapfm.strategies import JsonStrategy

# Register single extension
FileStrategyRegistry.register_strategy(".json", JsonStrategy)

# Register multiple extensions
FileStrategyRegistry.register_strategy([".json", ".jsonc"], JsonStrategy)
unregister_strategy
@classmethod
def unregister_strategy(cls, file_ext: str) -> None

Unregister a strategy for a file extension.

Parameters: - file_ext (str): File extension to unregister the strategy for

Example:

FileStrategyRegistry.unregister_strategy(".json")
get_strategy
@classmethod
def get_strategy(cls, file_ext_or_path: str) -> Optional[BaseFileStrategy]

Get a strategy for a file extension or path.

Parameters: - file_ext_or_path (str): File extension or path to get the strategy for

Returns: - Optional[BaseFileStrategy]: The strategy for the file extension or path

Example:

# Get strategy by extension
strategy = FileStrategyRegistry.get_strategy(".json")

# Get strategy by path
strategy = FileStrategyRegistry.get_strategy("config.json")
list_strategies
@classmethod
def list_strategies(cls) -> Dict[str, Type[BaseFileStrategy]]

List all registered strategies.

Returns: - Dict[str, Type[BaseFileStrategy]]: Dictionary mapping extensions to strategy classes

Example:

strategies = FileStrategyRegistry.list_strategies()
print(strategies)  # {'.json': <class 'JsonStrategy'>, '.toml': <class 'TomlStrategy'>}
get_counters
@classmethod
def get_counters(cls) -> Dict[str, int]

Get the counters for all registered strategies.

Returns: - Dict[str, int]: Dictionary mapping extensions to usage counts

Example:

counters = FileStrategyRegistry.get_counters()
print(counters)  # {'.json': 5, '.toml': 3}
get_skipped
@classmethod
def get_skipped(cls) -> Dict[str, List[str]]

Get the skipped files for all registered strategies.

Returns: - Dict[str, List[str]]: Dictionary mapping extensions to lists of skipped files

Example:

skipped = FileStrategyRegistry.get_skipped()
print(skipped)  # {'unknown': ['file.xyz']}
get_supported_formats
@classmethod
def get_supported_formats(cls) -> List[str]

Get the supported formats for all registered strategies.

Returns: - List[str]: List of supported file extensions

Example:

formats = FileStrategyRegistry.get_supported_formats()
print(formats)  # ['.json', '.toml', '.yaml']
is_format_supported
@classmethod
def is_format_supported(cls, file_ext: str) -> bool

Check if a format is supported.

Parameters: - file_ext (str): File extension to check

Returns: - bool: True if the format is supported, False otherwise

Example:

if FileStrategyRegistry.is_format_supported(".json"):
    print("JSON format is supported")
get_registry_stats
@classmethod
def get_registry_stats(cls) -> Dict[str, Any]

Get registry statistics.

Returns: - Dict[str, Any]: Registry statistics including counters and skipped files

Example:

stats = FileStrategyRegistry.get_registry_stats()
print(stats)  # {'counters': {...}, 'skipped': {...}, 'supported_formats': [...]}
display_summary
@classmethod
def display_summary(cls) -> None

Print a styled summary of counters and skipped files.

Example:

FileStrategyRegistry.display_summary()
# Output:
# 🎯 Registered Strategies & Usage Summary
# ----------------------------------------
# .json      -> JsonStrategy         | Used: 5
# .toml      -> TomlStrategy         | Used: 3

register_file_strategy

Decorator to register a strategy for one or more formats.

from yapfm.registry import register_file_strategy

Usage

@register_file_strategy(".json")
class MyJsonStrategy:
    def load(self, file_path):
        # Implementation
        pass

    def save(self, file_path, data):
        # Implementation
        pass

    def navigate(self, document, path, create=False):
        # Implementation
        pass

Parameters: - file_exts (Union[str, List[str]]): The extensions to register the strategy for - registry (Type[FileStrategyRegistry]): The registry to register the strategy for

Example:

@register_file_strategy([".json", ".jsonc"])
class MyJsonStrategy:
    # Implementation
    pass

⚠️ Exceptions

FileManagerError

Base exception for all file manager errors.

from yapfm.exceptions import FileManagerError

LoadFileError

Raised when there's an error loading a file.

from yapfm.exceptions import LoadFileError

Example:

try:
    fm.load()
except LoadFileError as e:
    print(f"Failed to load file: {e}")

FileWriteError

Raised when there's an error writing to a file.

from yapfm.exceptions import FileWriteError

Example:

try:
    fm.save()
except FileWriteError as e:
    print(f"Failed to save file: {e}")

StrategyError

Raised when there's an error with file strategies.

from yapfm.exceptions import StrategyError

Example:

try:
    fm = YAPFileManager("file.xyz")
except StrategyError as e:
    print(f"Strategy error: {e}")

🛠️ Helpers

split_dot_key

Split a dot-separated key into path and key name.

from yapfm.helpers import split_dot_key

Parameters: - dot_key (str): The dot-separated key

Returns: - Tuple[List[str], str]: The path and key name

Example:

path, key = split_dot_key("database.host")
print(path)  # ['database']
print(key)   # 'host'

Navigate through a dictionary-like structure.

from yapfm.helpers import navigate_dict_like

Parameters: - document (Any): The document to navigate - path (List[str]): The path to traverse - create (bool): Whether to create missing intermediate structures

Returns: - Optional[Any]: The value at the specified path

Example:

document = {"database": {"host": "localhost"}}
value = navigate_dict_like(document, ["database", "host"])
print(value)  # "localhost"

load_file

Load a file using a custom loader function.

from yapfm.helpers import load_file

Parameters: - file_path (Union[Path, str]): Path to the file - loader (Callable): Function to load the file content

Returns: - Any: The loaded file content

Example:

import json
data = load_file("config.json", json.loads)

save_file

Save data to a file using a custom serializer.

from yapfm.helpers import save_file

Parameters: - file_path (Union[Path, str]): Path to save the file - data (Any): Data to save - serializer (Callable): Function to serialize the data

Example:

import json
save_file("config.json", data, lambda x: json.dumps(x, indent=2))

open_file

Open a configuration file with the appropriate strategy.

from yapfm.helpers import open_file

Parameters: - path (Union[str, Path]): Path to the file - format (Optional[str]): Optional format override (e.g. "toml", "json", "yaml"). If provided, will select the strategy based on this format instead of the file extension - auto_create (bool): Whether to create the file if it doesn't exist. Default: False

Returns: - YAPFileManager: File manager instance configured for the specified file

Example:

# Open file with automatic format detection
fm = open_file("config.json")

# Open file with format override
fm = open_file("config.txt", format="toml")

# Open file with auto-creation
fm = open_file("new_config.json", auto_create=True)

# Use the file manager
with fm:
    fm.set_key("value", dot_key="key")

This API reference covers all public methods and classes in YAPFM. For more examples and usage patterns, see the Examples Guide.