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:
CLI arguments (highest priority)
Environment variables (
BUVIS_*prefix)YAML config files (auto-discovered)
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:
Python Field |
CLI Argument |
Environment Variable |
YAML Path |
|---|---|---|---|
|
|
|
|
|
|
|
|
|
(custom option) |
|
|
|
(custom option) |
|
|
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 forbuvis-photo.yamlandphoto:sectionBUVIS_(default) → onlybuvis.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):
$BUVIS_CONFIG_DIR/buvis.yaml(if env var set)$XDG_CONFIG_HOME/buvis/buvis.yaml(or~/.config/buvis/buvis.yaml)~/.buvis/buvis.yaml(legacy)./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 |
|---|---|---|
|
None (disabled) |
Ollama model name (e.g. |
|
|
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 theenv_prefix.ToolSettings (
pydantic.BaseModel) - For nested settings within a root class. Does NOT load from env directly; the parentGlobalSettingshandles 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):
$BUVIS_CONFIG_DIR/buvis.yaml~/.config/buvis/buvis.yaml~/.buvis/buvis.yaml./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:
BaseSettingsGlobal 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:
BaseModelBase 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:
objectUnified 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):
CLI overrides
Environment variables (BUVIS_* prefix)
YAML config files
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 patternBUVIS_{TOOL}_->"tool"; you no longer passtool_namemanually.- 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
Mixins
SafeLoggingMixin
- class buvis.pybase.configuration.SafeLoggingMixin
Bases:
objectMixin 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:
objectMixin 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--configoptions. 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:
ExceptionConfiguration loading or validation failed.
- exception buvis.pybase.configuration.ConfigurationKeyNotFoundError(message: str = 'Key not found in configuration.')
Bases:
ExceptionKey not found in configuration exception.
- Parameters:
message – Error message describing the missing key.
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_SIZEbytes.
- 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