Configuration

This module provides unified configuration management for BUVIS tools with automatic precedence handling across multiple sources.

Overview

The configuration system loads settings from multiple sources with clear precedence rules:

  1. CLI arguments (highest priority)

  2. Environment variables (BUVIS_* prefix)

  3. YAML config files (auto-discovered)

  4. Model defaults (lowest priority)

This means a --debug flag always wins over BUVIS_DEBUG=false in the environment, which wins over debug: false in a YAML file.

Source Mapping

Each Python field maps to CLI, ENV, and YAML sources with consistent naming:

Mapping Example for PhotoSettings

Python Field

CLI Argument

Environment Variable

YAML Path

debug

--debug

BUVIS_PHOTO_DEBUG

photo.debug

log_level

--log-level

BUVIS_PHOTO_LOG_LEVEL

photo.log_level

library_path

(custom option)

BUVIS_PHOTO_LIBRARY_PATH

photo.library_path

db.host (nested)

(custom option)

BUVIS_PHOTO__DB__HOST

photo.db.host

Naming rules:

  • CLI: Built-in options (--debug, --log-level) are added automatically. Custom fields require explicit Click options - see Adding Custom CLI Options below.

  • ENV: Prefix from env_prefix + field name in SCREAMING_SNAKE_CASE. Nested fields use __ delimiter.

  • YAML: Tool name (derived from prefix) as root key, then field names with . for nesting.

Adding Custom CLI Options

The @buvis_options decorator only adds --debug, --log-level, --config-dir, and --config. For custom fields, add your own Click options and pass them to cli_overrides:

import click
from buvis.pybase.configuration import ConfigResolver, GlobalSettings
from pydantic_settings import SettingsConfigDict
from pathlib import Path

class PhotoSettings(GlobalSettings):
    model_config = SettingsConfigDict(env_prefix="BUVIS_PHOTO_")
    library_path: Path = Path.home() / "Pictures"
    quality: int = 85

@click.command()
@click.option("--library", type=click.Path(exists=True), help="Photo library path")
@click.option("--quality", type=int, help="JPEG quality (1-100)")
@click.option("--debug/--no-debug", default=None)
def main(library: str | None, quality: int | None, debug: bool | None) -> None:
    cli_overrides = {
        k: v for k, v in {
            "library_path": Path(library) if library else None,
            "quality": quality,
            "debug": debug,
        }.items() if v is not None
    }

    resolver = ConfigResolver()
    settings = resolver.resolve(PhotoSettings, cli_overrides=cli_overrides)
    click.echo(f"Library: {settings.library_path}")

For nested fields (e.g., db.host), flatten them in cli_overrides:

# Nested settings don't have direct CLI support in cli_overrides.
# Use ENV vars or YAML for nested fields, or restructure as top-level.

Tool-Specific Configuration Files

You can separate tool configuration from global settings using dedicated files. The loader searches for both buvis.yaml AND buvis-{tool}.yaml:

Option 1: Section in global file

# ~/.config/buvis/buvis.yaml
debug: false
log_level: INFO

photo:                    # Tool section (from BUVIS_PHOTO_ prefix)
  library_path: /media/photos
  quality: 90

Option 2: Separate tool file

# ~/.config/buvis/buvis-photo.yaml
library_path: /media/photos
quality: 90

Both are merged. Tool-specific file values override global file values for that tool.

The tool name is derived from env_prefix:

  • BUVIS_PHOTO_ → searches for buvis-photo.yaml and photo: section

  • BUVIS_ (default) → only buvis.yaml, no tool section

Complete example:

from buvis.pybase.configuration import GlobalSettings, ToolSettings
from pydantic_settings import SettingsConfigDict
from pathlib import Path

class DatabaseSettings(ToolSettings):
    host: str = "localhost"
    port: int = 5432

class PhotoSettings(GlobalSettings):
    model_config = SettingsConfigDict(
        env_prefix="BUVIS_PHOTO_",
        env_nested_delimiter="__",
    )
    library_path: Path = Path.home() / "Pictures"
    db: DatabaseSettings = DatabaseSettings()

All equivalent ways to set db.host to "prod.db.local":

# Environment variable (note double underscore for nesting)
export BUVIS_PHOTO__DB__HOST=prod.db.local
# YAML (~/.config/buvis/buvis.yaml)
photo:
  db:
    host: prod.db.local
# Python default
class DatabaseSettings(ToolSettings):
    host: str = "prod.db.local"

Quick Start

Add configuration to any Click command:

import click
from buvis.pybase.configuration import buvis_options, get_settings

@click.command()
@buvis_options
@click.pass_context
def main(ctx: click.Context) -> None:
    settings = get_settings(ctx)
    if settings.debug:
        click.echo("Debug mode enabled")
    click.echo(f"Log level: {settings.log_level}")

if __name__ == "__main__":
    main()

This adds --debug, --log-level, --config-dir, and --config options. Values resolve from CLI > ENV > YAML > defaults.

For tool-specific settings, see Downstream Project Integration or Custom Settings Classes.

Downstream Project Integration

Step-by-step guide for projects depending on buvis-pybase.

Step 1: Define Settings

# myproject/settings.py
from buvis.pybase.configuration import GlobalSettings
from pydantic_settings import SettingsConfigDict
from pathlib import Path

class MyProjectSettings(GlobalSettings):
    model_config = SettingsConfigDict(
        env_prefix="MYPROJECT_",
        env_nested_delimiter="__",
    )
    data_dir: Path = Path.home() / ".myproject"
    verbose: bool = False

Step 2: Wire CLI

# myproject/cli.py
import click
from buvis.pybase.configuration import buvis_options, get_settings
from myproject.settings import MyProjectSettings

@click.command()
@buvis_options(settings_class=MyProjectSettings)
@click.pass_context
def main(ctx: click.Context) -> None:
    settings = get_settings(ctx, MyProjectSettings)
    if settings.verbose:
        click.echo(f"Data dir: {settings.data_dir}")

Step 3: Configure (any combination)

CLI: myproject --debug --log-level DEBUG

Environment:

export MYPROJECT_DATA_DIR=/var/data
export MYPROJECT_VERBOSE=true

YAML (~/.config/buvis/buvis.yaml):

myproject:
  data_dir: /var/data
  verbose: true

Example: Abbreviations from Config

Load abbreviation definitions from YAML and pass to StringOperator:

from buvis.pybase.configuration import GlobalSettings, ToolSettings
from buvis.pybase.formatting import StringOperator
from pydantic_settings import SettingsConfigDict

class FormattingSettings(ToolSettings):
    abbreviations: list[dict] = []

class DocSettings(GlobalSettings):
    model_config = SettingsConfigDict(env_prefix="DOC_")
    formatting: FormattingSettings = FormattingSettings()

# In CLI:
settings = get_settings(ctx, DocSettings)
expanded = StringOperator.replace_abbreviations(
    text="Use the API",
    abbreviations=settings.formatting.abbreviations,
    level=1,
)  # -> "Use the Application Programming Interface"

YAML:

doc:
  formatting:
    abbreviations:
      - API: Application Programming Interface
      - CLI: Command Line Interface

YAML Configuration

File Locations

Config files are discovered in order (first found wins):

  1. $BUVIS_CONFIG_DIR/buvis.yaml (if env var set)

  2. $XDG_CONFIG_HOME/buvis/buvis.yaml (or ~/.config/buvis/buvis.yaml)

  3. ~/.buvis/buvis.yaml (legacy)

  4. ./buvis.yaml (current directory)

For tool-specific config, files named buvis-{tool}.yaml are also checked.

File Format

# ~/.config/buvis/buvis.yaml
debug: false
log_level: INFO
output_format: text
ollama_model: llama3.2:3b        # optional, enables LLM features
ollama_url: http://localhost:11434  # default

# Tool-specific sections
photo:
  watermark: true
  default_album: shared
music:
  normalize: true
  bitrate: 320

Environment Variable Substitution

YAML files support environment variable interpolation:

database:
  host: ${DB_HOST}                    # Required - fails if not set
  port: ${DB_PORT:-5432}              # Optional with default
  password: ${DB_PASSWORD}
  connection_string: $${NOT_EXPANDED} # Escaped - becomes literal ${NOT_EXPANDED}

Substitution is applied automatically by ConfigResolver when it loads YAML:

from buvis.pybase.configuration import ConfigResolver
from myapp.settings import PhotoSettings

resolver = ConfigResolver()
settings = resolver.resolve(PhotoSettings)

Environment Variables

The GlobalSettings base class uses the BUVIS_ prefix in SCREAMING_SNAKE_CASE. Override env_prefix on your settings class (as shown in PhotoSettings above) to scope variables per tool:

export BUVIS_PHOTO_DEBUG=true
export BUVIS_PHOTO_LOG_LEVEL=DEBUG
export BUVIS_PHOTO_OUTPUT_FORMAT=json

For nested fields, use double underscores:

export BUVIS_PHOTO__MUSIC__NORMALIZE=true
export BUVIS_PHOTO__MUSIC__BITRATE=256

Ollama Integration

GlobalSettings includes optional ollama fields available to all tools:

Setting

Default

Description

ollama_model

None (disabled)

Ollama model name (e.g. llama3.2:3b). When set, enables LLM features such as tag suggestion during bim import.

ollama_url

http://localhost:11434

Ollama API base URL.

Configure via environment variables:

export BUVIS_OLLAMA_MODEL=llama3.2:3b
export BUVIS_OLLAMA_URL=http://localhost:11434  # default, usually not needed

Or YAML:

# ~/.config/buvis/buvis.yaml
ollama_model: llama3.2:3b

If ollama is unreachable when a tool requests it, the call is skipped with a warning.

Custom Settings Classes

GlobalSettings vs ToolSettings

Use the right base class:

  • GlobalSettings (pydantic_settings.BaseSettings) - For your root settings class. Loads from environment variables automatically using the env_prefix.

  • ToolSettings (pydantic.BaseModel) - For nested settings within a root class. Does NOT load from env directly; the parent GlobalSettings handles env resolution for nested fields.

from buvis.pybase.configuration import GlobalSettings, ToolSettings

# ToolSettings for nested - no env loading, just structure
class DatabaseSettings(ToolSettings):
    host: str = "localhost"
    port: int = 5432

# GlobalSettings for root - loads BUVIS_MYAPP_* from env
class MyAppSettings(GlobalSettings):
    model_config = SettingsConfigDict(env_prefix="BUVIS_MYAPP_")
    db: DatabaseSettings = DatabaseSettings()  # Nested

# Environment variable for nested field:
# BUVIS_MYAPP__DB__HOST=prod.db.local  (double underscore!)

Why this matters: If you used GlobalSettings for nested classes, each would try to load from env independently with potentially conflicting prefixes.

Both classes are frozen (immutable) - you cannot modify settings after creation:

settings = get_settings(ctx, MyAppSettings)
settings.db.host = "other"  # Raises: ValidationError (frozen)

Composing Settings

Model tool namespaces with ToolSettings and compose them into your root GlobalSettings subclass:

from typing import Literal
from buvis.pybase.configuration import GlobalSettings, ToolSettings
from pydantic_settings import SettingsConfigDict

class MusicSettings(ToolSettings):
    normalize: bool = True
    bitrate: int = 320

class PhotoSettings(GlobalSettings):
    model_config = SettingsConfigDict(
        env_prefix="BUVIS_PHOTO_",
        env_nested_delimiter="__",
    )
    resolution: Literal["low", "medium", "high"] = "high"
    watermark: bool = False
    music: MusicSettings = MusicSettings()

Nested environment variables map to these namespaces (for example, BUVIS_PHOTO__RESOLUTION=medium or BUVIS_PHOTO__MUSIC__BITRATE=256).

Using ConfigResolver Directly

For non-Click applications or custom resolution:

from buvis.pybase.configuration import ConfigResolver
from myapp.settings import PhotoSettings

resolver = ConfigResolver()
settings = resolver.resolve(
    PhotoSettings,
    cli_overrides={"debug": True},  # Simulate CLI args
)

# Check where each value came from
print(resolver.sources)  # {"debug": ConfigSource.CLI, "log_level": ConfigSource.DEFAULT}

Security Considerations

Sensitive Fields

Fields matching patterns like password, token, api_key, secret are automatically:

  • Masked in __repr__ output (shows ***)

  • Logged at INFO level (vs DEBUG for normal fields)

  • Hidden in validation error messages

from buvis.pybase.configuration import SafeLoggingMixin
from pydantic_settings import BaseSettings

class SecureSettings(SafeLoggingMixin, BaseSettings):
    api_key: str
    password: str

s = SecureSettings(api_key="secret123", password="hunter2")
print(s)  # SecureSettings(api_key='***', password='***')

JSON Size Limits

Environment variables containing JSON are limited to 64KB to prevent DoS:

from buvis.pybase.configuration import SecureSettingsMixin
from pydantic_settings import BaseSettings

class MySettings(SecureSettingsMixin, BaseSettings):
    model_config = {"env_prefix": "MYAPP_"}
    complex_config: dict = {}

# Raises ValueError if MYAPP_COMPLEX_CONFIG exceeds 64KB

Error Handling

from buvis.pybase.configuration import (
    ConfigResolver,
    ConfigurationError,
    MissingEnvVarError,
)
from myapp.settings import PhotoSettings

try:
    resolver = ConfigResolver()
    settings = resolver.resolve(PhotoSettings)
except MissingEnvVarError as e:
    print(f"Missing required env vars: {e.var_names}")
except ConfigurationError as e:
    print(f"Config error: {e}")

Testing

Testing Code That Uses Settings

For unit tests, create settings directly without the resolver:

import pytest
from myapp.settings import MyAppSettings

def test_with_custom_settings():
    # Create settings with test values directly
    settings = MyAppSettings(
        debug=True,
        db={"host": "test-db", "port": 5433},
    )
    assert settings.debug is True
    assert settings.db.host == "test-db"

Mocking get_settings in Click Commands

Use pytest-mock to mock get_settings in CLI tests:

import pytest
from click.testing import CliRunner
from myapp.cli import main
from myapp.settings import MyAppSettings

@pytest.fixture
def mock_settings(mocker):
    settings = MyAppSettings(debug=True)
    mocker.patch("myapp.cli.get_settings", return_value=settings)
    return settings

def test_cli_with_mocked_settings(mock_settings):
    runner = CliRunner()
    result = runner.invoke(main)
    assert result.exit_code == 0

Testing with Environment Variables

Use monkeypatch to set env vars for integration tests:

def test_settings_from_env(monkeypatch):
    monkeypatch.setenv("BUVIS_MYAPP_DEBUG", "true")
    monkeypatch.setenv("BUVIS_MYAPP__DB__HOST", "env-db")

    from buvis.pybase.configuration import ConfigResolver
    from myapp.settings import MyAppSettings

    resolver = ConfigResolver()
    settings = resolver.resolve(MyAppSettings)

    assert settings.debug is True
    assert settings.db.host == "env-db"

Troubleshooting

Missing Environment Variables

If YAML uses ${VAR} without a default, you’ll get MissingEnvVarError:

# buvis.yaml
database:
  password: ${DB_PASSWORD}  # Fails if not set

# Fix: provide default
database:
  password: ${DB_PASSWORD:-}  # Empty string default

YAML Not Loading

Check file locations (in order):

  1. $BUVIS_CONFIG_DIR/buvis.yaml

  2. ~/.config/buvis/buvis.yaml

  3. ~/.buvis/buvis.yaml

  4. ./buvis.yaml

Debug with:

from buvis.pybase.configuration import ConfigResolver

resolver = ConfigResolver()
settings = resolver.resolve(MySettings)
print(resolver.sources)  # Shows where each value came from

Precedence Confusion

CLI always wins, then ENV, then YAML, then defaults.

# This won't work as expected:
export BUVIS_DEBUG=true
myapp --no-debug  # CLI wins -> debug=False

API Reference

Core Classes

GlobalSettings

class buvis.pybase.configuration.GlobalSettings(_case_sensitive: bool | None = None, _nested_model_default_partial_update: bool | None = None, _env_prefix: str | None = None, _env_prefix_target: EnvPrefixTarget | None = None, _env_file: DotenvType | None = PosixPath('.'), _env_file_encoding: str | None = None, _env_ignore_empty: bool | None = None, _env_nested_delimiter: str | None = None, _env_nested_max_split: int | None = None, _env_parse_none_str: str | None = None, _env_parse_enums: bool | None = None, _cli_prog_name: str | None = None, _cli_parse_args: bool | list[str] | tuple[str, ...] | None = None, _cli_settings_source: CliSettingsSource[Any] | None = None, _cli_parse_none_str: str | None = None, _cli_hide_none_type: bool | None = None, _cli_avoid_json: bool | None = None, _cli_enforce_required: bool | None = None, _cli_use_class_docs_for_groups: bool | None = None, _cli_exit_on_error: bool | None = None, _cli_prefix: str | None = None, _cli_flag_prefix_char: str | None = None, _cli_implicit_flags: bool | Literal['dual', 'toggle'] | None = None, _cli_ignore_unknown_args: bool | None = None, _cli_kebab_case: bool | Literal['all', 'no_enums'] | None = None, _cli_shortcuts: Mapping[str, str | list[str]] | None = None, _secrets_dir: PathType | None = None, _build_sources: tuple[tuple[PydanticBaseSettingsSource, ...], dict[str, Any]] | None = None, *, debug: bool = False, log_level: Literal['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL'] = 'INFO', output_format: Literal['text', 'json', 'yaml'] = 'text', ollama_model: str | None = None, ollama_url: str = 'http://localhost:11434', adapters: dict[str, dict[str, Any]] = {})

Bases: BaseSettings

Global runtime settings for BUVIS tools.

Loads from environment variables with BUVIS_ prefix. Nested delimiter is __ (e.g., BUVIS_PHOTO__LIBRARY_PATH).

adapters: dict[str, dict[str, Any]]
debug: bool
log_level: Literal['DEBUG', 'INFO', 'WARNING', 'ERROR', 'CRITICAL']
model_config = {'arbitrary_types_allowed': True, 'case_sensitive': False, 'cli_avoid_json': False, 'cli_enforce_required': False, 'cli_exit_on_error': True, 'cli_flag_prefix_char': '-', 'cli_hide_none_type': False, 'cli_ignore_unknown_args': False, 'cli_implicit_flags': False, 'cli_kebab_case': False, 'cli_parse_args': None, 'cli_parse_none_str': None, 'cli_prefix': '', 'cli_prog_name': None, 'cli_shortcuts': None, 'cli_use_class_docs_for_groups': False, 'enable_decoding': True, 'env_file': None, 'env_file_encoding': None, 'env_ignore_empty': False, 'env_nested_delimiter': '__', 'env_nested_max_split': None, 'env_parse_enums': None, 'env_parse_none_str': None, 'env_prefix': 'BUVIS_', 'env_prefix_target': 'variable', 'extra': 'forbid', 'frozen': True, 'json_file': None, 'json_file_encoding': None, 'nested_model_default_partial_update': False, 'protected_namespaces': ('model_validate', 'model_dump', 'settings_customise_sources'), 'secrets_dir': None, 'toml_file': None, 'validate_default': True, 'yaml_config_section': None, 'yaml_file': None, 'yaml_file_encoding': None}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

ollama_model: str | None
ollama_url: str
output_format: Literal['text', 'json', 'yaml']

ToolSettings

class buvis.pybase.configuration.ToolSettings(*, enabled: bool = True)

Bases: BaseModel

Base for tool-specific settings.

All tool namespaces inherit from this. Each tool gets enabled: bool = True. Subclasses add tool-specific fields. Uses BaseModel (not BaseSettings) since parent GlobalSettings handles ENV resolution.

enabled: bool
model_config = {'extra': 'forbid', 'frozen': True}

Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].

ConfigResolver

class buvis.pybase.configuration.ConfigResolver

Bases: object

Unified configuration loader with precedence handling.

Orchestrates config loading from multiple sources:

  • YAML files (via ConfigurationLoader discovery)

  • Environment variables (via Pydantic, BUVIS_* prefix)

  • CLI overrides (passed to resolve())

Precedence (highest to lowest):

  1. CLI overrides

  2. Environment variables (BUVIS_* prefix)

  3. YAML config files

  4. Model defaults

Example

Basic usage:

resolver = ConfigResolver()
settings = resolver.resolve(GlobalSettings)

With CLI overrides from Click:

@click.command()
@click.option('--debug', is_flag=True)
def main(debug):
    resolver = ConfigResolver()
    settings = resolver.resolve(
        GlobalSettings,
        cli_overrides={"debug": debug} if debug else None,
    )

Custom config directory:

settings = resolver.resolve(GlobalSettings, config_dir="/etc/buvis")

Note

Settings are immutable after resolve(). Instances are frozen. The tool name is inferred from settings_class.model_config['env_prefix'] following the pattern BUVIS_{TOOL}_ -> "tool"; you no longer pass tool_name manually.

resolve(settings_class: type[T], config_dir: str | None = None, config_path: Path | None = None, cli_overrides: dict[str, Any] | None = None) T

Instantiate a settings class with precedence: CLI > ENV > YAML > Defaults.

property sources: dict[str, ConfigSource]

Get copy of source tracking dict.

ConfigSource

class buvis.pybase.configuration.ConfigSource(*values)

Bases: Enum

Source from which a configuration value was obtained.

CLI = 'cli'
DEFAULT = 'default'
ENV = 'env'
YAML = 'yaml'

Mixins

SafeLoggingMixin

class buvis.pybase.configuration.SafeLoggingMixin

Bases: object

Mixin that sanitizes sensitive values in __repr__.

Masks values for fields whose names match sensitive patterns like ‘api_key’, ‘password’, ‘token’, ‘authorization’, etc.

SecureSettingsMixin

class buvis.pybase.configuration.SecureSettingsMixin

Bases: object

Mixin adding security validations for settings.

Validates JSON env values don’t exceed 64KB.

Example:

class MySettings(SecureSettingsMixin, BaseSettings):
    ...
validate_json_sizes(data: dict[str, Any]) dict[str, Any]

Check env var sizes before parsing.

Click Integration

buvis.pybase.configuration.buvis_options(func: F) F
buvis.pybase.configuration.buvis_options(settings_class_or_func: type[T] | None = None, *, settings_class: type[T] | None = None) Callable[[F], F]

Add standard BUVIS options to a Click command.

Adds --debug/--no-debug, --log-level, --config-dir, and --config options. Resolves settings using ConfigResolver and injects into Click context. Can be applied as @buvis_options, @buvis_options(), or @buvis_options(settings_class=CustomSettings).

Example:

@click.command()
@buvis_options(settings_class=GlobalSettings)
@click.pass_context
def cli(ctx):
    settings = ctx.obj["settings"]
    if settings.debug:
        click.echo("Debug mode enabled")
buvis.pybase.configuration.get_settings(ctx: Context) GlobalSettings
buvis.pybase.configuration.get_settings(ctx: Context, settings_class: type[T]) T

Get settings from Click context.

Parameters:
  • ctx – Click context with settings stored by buvis_options decorator.

  • settings_class – Specific settings class to retrieve from context. Defaults to GlobalSettings for backward compatibility.

Raises:

RuntimeError – If called before buvis_options decorator ran.

Returns:

The requested settings instance from context.

Exceptions

exception buvis.pybase.configuration.ConfigurationError

Bases: Exception

Configuration loading or validation failed.

exception buvis.pybase.configuration.ConfigurationKeyNotFoundError(message: str = 'Key not found in configuration.')

Bases: Exception

Key not found in configuration exception.

Parameters:

message – Error message describing the missing key.

exception buvis.pybase.configuration.MissingEnvVarError(var_names: list[str])

Bases: Exception

Required env var not set.

Parameters:

var_names – List of missing environment variable names.

var_names

The missing variable names.

Validators

buvis.pybase.configuration.validate_nesting_depth(model_class: type[BaseModel]) None

Validate that a model does not exceed the allowed nesting depth.

Parameters:

model_class – The Pydantic model class to validate.

Raises:

ValueError – If the model’s nesting depth exceeds MAX_NESTING_DEPTH.

buvis.pybase.configuration.validate_json_env_size(env_var_name: str) None

Validate that an environment variable’s JSON payload fits within limits.

Parameters:

env_var_name – The name of the environment variable containing JSON data.

Raises:

ValueError – If the variable contains more than MAX_JSON_ENV_SIZE bytes.

buvis.pybase.configuration.get_model_depth(model_class: type[BaseModel], current_depth: int = 0) int

Calculate the maximum nesting depth of a Pydantic model.

The function traverses nested BaseModel fields to find the deepest path and short-circuits once the depth exceeds MAX_NESTING_DEPTH + 1.

Parameters:
  • model_class – The root Pydantic model class to examine.

  • current_depth – The depth of the current model in the recursion tree.

Returns:

The maximum nesting depth encountered relative to the root model.

Return type:

int

buvis.pybase.configuration.is_sensitive_field(field_path: str) bool

Check if field path contains sensitive data indicators.

Parameters:

field_path – Dotted field path (e.g., “database.password”).

Returns:

True if any part matches sensitive patterns.

Constants

buvis.pybase.configuration.MAX_NESTING_DEPTH = 5

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating-point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4

buvis.pybase.configuration.MAX_JSON_ENV_SIZE = 65536

int([x]) -> integer int(x, base=10) -> integer

Convert a number or string to an integer, or return 0 if no arguments are given. If x is a number, return x.__int__(). For floating-point numbers, this truncates towards zero.

If x is not a number or if base is given, then x must be a string, bytes, or bytearray instance representing an integer literal in the given base. The literal can be preceded by ‘+’ or ‘-’ and be surrounded by whitespace. The base defaults to 10. Valid bases are 0 and 2-36. Base 0 means to interpret the base from the string as an integer literal. >>> int(‘0b100’, base=0) 4