A flexible configuration management library for Python applications
Project description
Confii
A comprehensive, production-ready configuration management library for Python
Installation • Quick Start • Features • Examples • Documentation
Overview
Confii is a modern, feature-rich configuration management library designed for Python applications. It provides a unified interface for loading, merging, validating, and accessing configuration from multiple sources with enterprise-grade features like secret management, schema validation, observability, versioning, and async support.
Why Confii?
- 🎯 Attribute-Style Access -
config.database.hostinstead ofconfig["database"]["host"] - 🔐 Secret Management -
${secret:key}resolved from AWS, Vault (9 auth methods), Azure, GCP - ✅ Type Safety -
Config[T]generics with Pydantic for full IDE autocomplete - 🧩 Config Composition -
_includeand_defaultsdirectives (Hydra-like) - 🔄 Dynamic Reloading - Hot reload with incremental updates and dry-run
- 🪝 Hook System - 4 hook types to transform values on access
- 🧊 Freeze & Override - Immutable configs, scoped overrides with
override()context manager - 📊 Observability - Access metrics, event emission, change callbacks
- 🔍 Introspection -
explain(),layers, source tracking, drift detection - 🏢 Enterprise Ready - Versioning with rollback, 6 merge strategies, async support
Installation
# Basic installation
pip install confii
# With optional dependencies
pip install confii[watch] # File watching for dynamic reloading
pip install confii[cli] # CLI tools (confii command)
pip install confii[validation] # Schema validation (Pydantic, JSON Schema)
pip install confii[cloud] # Cloud storage support (AWS S3, Azure, GCP)
pip install confii[secrets] # Secret store support (AWS, Azure, GCP, Vault)
pip install confii[all] # All features
Requirements: Python 3.9+
📖 See examples/basic_usage.py for getting started
Quick Start
Basic Usage
from confii import Config
from confii.loaders import YamlLoader
# Load from a single file
config = Config(loaders=[YamlLoader("config.yaml")])
# Access configuration values with attribute-style syntax
print(config.database.host)
print(config.database.port)
Multiple Sources
from confii import Config
from confii.loaders import YamlLoader, EnvironmentLoader
# Load from multiple sources (later sources override earlier ones)
config = Config(
env="production",
loaders=[
YamlLoader("config/base.yaml"),
YamlLoader("config/production.yaml"),
EnvironmentLoader("APP"), # APP_* environment variables
]
)
# Access values directly as attributes
print(config.database.host) # from production.yaml (overrides base)
print(config.database.port) # from base.yaml (not overridden)
print(config.app.debug) # False in production
Type-Safe Config (North Star Feature)
from pydantic import BaseModel
from confii import Config
from confii.loaders import YamlLoader
class DatabaseConfig(BaseModel):
host: str
port: int = 5432
ssl: bool = False
class AppConfig(BaseModel):
database: DatabaseConfig
debug: bool = False
# Config[AppConfig] gives you full type safety
config = Config[AppConfig](
loaders=[YamlLoader("config.yaml")],
schema=AppConfig,
validate_on_load=True,
)
# Full IDE autocomplete and mypy/pyright type checking:
config.typed.database.host # IDE knows: str
config.typed.database.port # IDE knows: int
config.typed.database.ssl # IDE knows: bool
config.typed.nonexistent # mypy error at dev time!
Load from any source (YAML, JSON, env vars, SSM, Vault) — access with full type safety.
📖 See examples/typed_config.py
With Secret Stores
from confii import Config
from confii.secret_stores import AWSSecretsManager, SecretResolver
from confii.loaders import YamlLoader
# Initialize secret store
secret_store = AWSSecretsManager(region_name='us-east-1')
# Use with Config
config = Config(
loaders=[YamlLoader("config.yaml")],
secret_resolver=SecretResolver(secret_store)
)
# Secrets in config.yaml like "${secret:db/password}" are automatically resolved
print(config.database.password) # Resolved from AWS Secrets Manager
📖 See examples/basic_usage.py for more examples
Features
🎯 Core Features
Multiple Configuration Sources
- Files: JSON, YAML, TOML, INI, .env
- Cloud Storage: AWS S3, Azure Blob, Google Cloud Storage, IBM COS
- AWS Services: SSM Parameter Store, Secrets Manager
- Remote: HTTP/HTTPS endpoints, Git repositories
- Environment Variables: System environment with prefix support
- Secret Stores: AWS, Azure, GCP, HashiCorp Vault
- Custom Loaders: Extensible loader interface
Schema Validation
from confii import Config
from confii.loaders import YamlLoader
from pydantic import BaseModel
class DatabaseConfig(BaseModel):
host: str
port: int = 5432
config = Config(
loaders=[YamlLoader("config.yaml")],
schema=DatabaseConfig,
validate_on_load=True
)
# Validated — safe to access directly
print(config.database.host) # guaranteed to be str
print(config.database.port) # guaranteed to be int, defaults to 5432
📖 See examples/validation_example.py
Dynamic Reloading
Requires
pip install confii[watch]for file watching.
config = Config(
loaders=[YamlLoader("config.yaml")],
dynamic_reloading=True # Watches files for changes
)
# Config automatically reloads when files change
# Or manually reload with incremental updates (no watchdog needed)
config.reload(incremental=True) # Only reloads changed files
AWS SSM Parameter Store
from confii import Config
from confii.loaders import SSMLoader, YamlLoader
# Load base config from file, override with SSM parameters
config = Config(
env="production",
loaders=[
YamlLoader("config.yaml"),
SSMLoader("/myapp/production/", decrypt=True),
],
)
# /myapp/production/database/host → config.database.host
print(config.database.host) # from SSM (overrides YAML)
print(config.database.port) # from YAML (not in SSM)
SSM loader handles pagination automatically (works beyond 10 parameters), decrypts SecureString values, and auto-converts types ("5432" → 5432).
Environment Variables with Nesting
from confii.loaders import EnvironmentLoader
# APP_DATABASE__HOST=db.example.com → config.database.host
# APP_DATABASE__PORT=5432 → config.database.port (auto-typed to int)
config = Config(loaders=[EnvironmentLoader("APP", separator="__")])
print(config.database.host) # "db.example.com"
print(config.database.port) # 5432 (int, not string)
Smart .env Loading
from confii.loaders import EnvFileLoader
# .env file supports dotted keys, type coercion, inline comments, and escapes
# database.host=localhost → nested: config.database.host
# database.port=5432 → auto-typed: int
# debug=true → auto-typed: bool
# api.key=abc123 # my comment → inline comment stripped
# message="hello\nworld" → escape sequences in double quotes
config = Config(loaders=[EnvFileLoader(".env")])
print(config.database.host) # "localhost"
print(config.database.port) # 5432 (int)
print(config.debug) # True (bool)
Introspection API
# Access values directly — the primary way to use Confii
host = config.database.host # "db.example.com"
port = config.database.port # 5432
debug = config.app.debug # False
# get() is available when you need defaults or dynamic keys
value = config.get("database.host", "localhost")
# Query and explore your configuration
keys = config.keys() # all leaf keys
exists = config.has("database.host") # True
schema = config.schema("database") # type info
info = config.explain("database.host") # source, value, override history
📖 See examples/introspection_api.py
Configuration Overrides
# Programmatic overrides
config.set("database.host", "remote.db.example.com")
config.set("database.port", 3306)
# Access the overridden values directly
print(config.database.host) # "remote.db.example.com"
print(config.database.port) # 3306
# Scoped overrides — automatically restored on exit
with config.override({"database.host": "temp.db.example.com"}):
print(config.database.host) # "temp.db.example.com"
print(config.database.host) # back to "remote.db.example.com"
Configuration Composition
Build complex configurations from reusable pieces — like Hydra, but built-in:
# config/base.yaml
_defaults:
- database: postgres
- cache: redis
_include:
- config/shared.yaml
- config/secrets.yaml
app:
name: MyApp
config = Config(loaders=[YamlLoader("config/base.yaml")])
print(config.app.name) # "MyApp"
print(config.database.host) # from included postgres defaults
print(config.cache.ttl) # from included redis defaults
Circular includes are automatically detected and prevented.
Environment Switching
Switch environments dynamically without code changes:
# Read environment name from an OS variable
config = Config(
env_switcher="APP_ENV", # reads os.environ["APP_ENV"]
loaders=[YamlLoader("config.yaml")],
)
# config.yaml has default:, production:, staging: sections
# The right one is selected automatically based on APP_ENV
print(config.database.host) # from the active environment
APP_ENV=production python app.py # uses production section
APP_ENV=staging python app.py # uses staging section
System Environment Fallback
Missing a config key? Confii can fall back to OS environment variables:
config = Config(
loaders=[YamlLoader("config.yaml")],
sysenv_fallback=True,
env_prefix="MYAPP",
)
# If database.host is not in config.yaml, Confii checks MYAPP_DATABASE_HOST
print(config.database.host) # from file or env var — transparent
Hook System
Transform values on access with 4 types of hooks:
config = Config(loaders=[YamlLoader("config.yaml")])
# Key hook — transform specific keys
config.register_key_hook("database.password", lambda v: decrypt(v))
# Value hook — transform specific values
config.register_value_hook("PLACEHOLDER", lambda v: os.environ.get("REAL_VALUE"))
# Condition hook — transform values matching a condition
config.register_condition_hook(
lambda key, value: key.endswith("_url"),
lambda value: value.rstrip("/")
)
# Global hook — applied to every value
config.register_global_hook(lambda key, value: value.strip() if isinstance(value, str) else value)
# Hooks fire automatically on attribute access
print(config.database.password) # decrypted via key hook
print(config.api.base_url) # trailing slash stripped via condition hook
Freeze for Production Safety
Make your config immutable after loading — no accidental mutations:
config = Config(
loaders=[YamlLoader("config.yaml")],
freeze_on_load=True, # immutable from the start
)
print(config.database.host) # reads work
config.set("database.host", "x") # raises ConfiiError!
config.reload() # raises ConfiiError!
# Or freeze manually after setup
config = Config(loaders=[YamlLoader("config.yaml")])
config.set("debug", True) # mutation allowed
config.freeze() # lock it down
config.set("debug", False) # raises ConfiiError!
Dry-Run Reload
Validate a reload before applying it:
# Test what would change without actually changing anything
config.reload(dry_run=True) # validates — no side effects
# Incremental reload — only re-reads changed files
config.reload(incremental=True) # fast for large configs
Change Callbacks
React when configuration values change:
@config.on_change
def handle_change(old_config, new_config):
if old_config.get("database.host") != new_config.get("database.host"):
reconnect_database()
config.reload() # triggers callback if values changed
Self-Configuration
Configure Confii itself from a file — no code needed for defaults:
# confii.yaml (or .confii.yaml, confii.json, confii.toml)
default_environment: production
default_files:
- config.yaml
- config.local.yaml
dynamic_reloading: false
deep_merge: true
use_type_casting: true
# Or in pyproject.toml
[tool.confii]
default_environment = "production"
deep_merge = true
use_type_casting = true
# Config picks up settings automatically — no kwargs needed
config = Config(loaders=[YamlLoader("config.yaml")])
Generate Documentation
Auto-generate a configuration reference from your live config:
# Markdown documentation of all config keys
docs = config.generate_docs("markdown")
print(docs) # | Key | Value | Type | Source |
# JSON format for tooling
docs = config.generate_docs("json")
🔐 Secret Store Integration
Comprehensive secret management with automatic resolution:
from confii.secret_stores import (
AWSSecretsManager,
HashiCorpVault,
AzureKeyVault,
GCPSecretManager,
SecretResolver
)
# AWS Secrets Manager
store = AWSSecretsManager(region_name='us-east-1')
# HashiCorp Vault with OIDC + Kerberos (SSO)
from confii.secret_stores.vault_auth import OIDCAuth
auth = OIDCAuth(role='myapp-role', use_kerberos=True)
store = HashiCorpVault(url='https://vault.example.com', auth_method=auth)
# Multi-store fallback
from confii.secret_stores import MultiSecretStore, DictSecretStore
store = MultiSecretStore([
DictSecretStore({"local/key": "override"}), # Highest priority
AWSSecretsManager(region_name='us-east-1'), # Production
])
config = Config(
loaders=[YamlLoader("config.yaml")],
secret_resolver=SecretResolver(store)
)
Configuration file with secret placeholders:
database:
host: prod-db.example.com
password: "${secret:prod/database/password}"
api:
key: "${secret:prod/api/key:api_key}" # JSON path extraction
Supported Secret Stores:
- ✅ AWS Secrets Manager - Native AWS secret management
- ✅ HashiCorp Vault - Enterprise secrets with 10+ auth methods
- OIDC with Kerberos (SSO, no browser if
kinitdone) - LDAP with PIN+Token (complex password policies)
- JWT, Kubernetes, AWS, Azure, GCP, AppRole, Token
- OIDC with Kerberos (SSO, no browser if
- ✅ Azure Key Vault - Azure native secret management
- ✅ GCP Secret Manager - Google Cloud secret management
- ✅ Environment Variables - Simple env-based secrets
- ✅ Multi-Store - Combine multiple stores with fallback hierarchy
📖 See examples/secret_store_example.py and docs/SECRET_STORES.md
🚀 Advanced Features
Async/Await Support
from confii.async_config import AsyncConfig, AsyncYamlLoader
async def main():
loader = AsyncYamlLoader("config.yaml")
config = await AsyncConfig.create(loaders=[loader])
value = await config.get_async("database.host")
📖 See examples/async_example.py
Configuration Versioning
# Enable versioning
version_manager = config.enable_versioning()
# Save current configuration as a version
version = config.save_version(metadata={
"author": "user@example.com",
"message": "Updated database config"
})
# Rollback to a previous version
config.rollback_to_version(version.version_id)
# List all versions
versions = version_manager.list_versions(limit=10)
Configuration Diff & Drift Detection
# Compare two configurations
config1 = Config(loaders=[YamlLoader("dev.yaml")])
config2 = Config(loaders=[YamlLoader("prod.yaml")])
diffs = config1.diff(config2)
for diff in diffs:
print(f"{diff.path}: {diff.diff_type.value}")
# Detect configuration drift
intended = Config(loaders=[YamlLoader("intended.yaml")])
actual = Config(loaders=[YamlLoader("actual.yaml")])
drift = actual.detect_drift(intended)
Observability & Metrics
# Enable metrics collection
observer = config.enable_observability()
# Use configuration normally
host = config.database.host
# Get metrics statistics
metrics = config.get_metrics()
print(f"Config accessed {metrics['accessed_keys']} times")
print(f"Reload count: {metrics['reload_count']}")
# Enable event emission
emitter = config.enable_events()
@emitter.on("reload")
def handle_reload(new_config, duration):
print(f"Config reloaded in {duration}s")
# Or register without decorator
emitter.on("change", lambda old, new: print("Config changed"))
Advanced Merging Strategies
from confii.merge_strategies import AdvancedConfigMerger, MergeStrategy
merger = AdvancedConfigMerger(MergeStrategy.MERGE)
merger.set_strategy("database", MergeStrategy.REPLACE) # Replace entire section
merger.set_strategy("app.debug", MergeStrategy.REPLACE) # Replace specific key
result = merger.merge(base_config, override_config)
📖 See examples/advanced_features.py
🛠️ Developer Experience
Debug Mode & Source Tracking
config = Config(debug_mode=True, loaders=[YamlLoader("config.yaml")])
# Use config normally — attribute access works the same
print(config.database.host) # "db.example.com"
print(config.database.port) # 5432
# But now you can also trace where each value came from
info = config.get_source_info("database.port")
print(f"Value: {info.value}") # 5432
print(f"Source: {info.source_file}") # "config.yaml"
print(f"Override count: {info.override_count}") # 0
# Export full debug report
config.export_debug_report("config_debug.json")
IDE Support
# Auto-generates type stubs for IDE autocomplete
config = Config(
loaders=[YamlLoader("config.yaml")],
enable_ide_support=True,
ide_stub_path=".confii/stubs.pyi"
)
# Your IDE now autocompletes attribute access!
config.database.host # IDE suggests: host, port, ssl, password
config.app.debug # IDE knows this exists
ConfigBuilder Pattern
from confii import ConfigBuilder
from confii.loaders import YamlLoader
config = (ConfigBuilder()
.with_env("production")
.add_loader(YamlLoader("config.yaml"))
.enable_deep_merge()
.with_schema(AppConfig, validate_on_load=True)
.build())
# Same attribute-style access
print(config.database.host)
print(config.app.debug)
CLI Tools
Requires
pip install confii[cli]
Confii includes a CLI for common operations:
# Validate configuration
confii validate production --loader yaml:config.yaml
# Lint configuration for best practices
confii lint production --loader yaml:config.yaml
# Export configuration
confii export production --format=json --output=config.json
# Show configuration sources
confii debug production --key=database.host
# Explain how a configuration value was resolved
confii explain production --key=database.host
# Compare two configurations
confii diff development production \
--loader1 yaml:dev.yaml \
--loader2 yaml:prod.yaml
# Migrate from other tools
confii migrate dotenv .env --output config.yaml
confii migrate dynaconf settings.yaml --output config.yaml
confii migrate hydra conf/config.yaml --output config.yaml
# Load with overrides
confii load production \
--loader yaml:config.yaml \
--override "database.host=remote.db.example.com" \
--override "database.port=3306"
Examples
We provide comprehensive, runnable examples for every feature. Each file is self-contained — creates temp files, demonstrates the feature, and cleans up.
Quick Reference
| Feature | What You'll Learn | Example File |
|---|---|---|
| YAML / JSON loading | Load config from YAML and JSON files | basic_usage.py |
| TOML loading | Load config from TOML files with sections | loaders_showcase.py |
| INI loading | Load config from INI files, section→dict mapping | loaders_showcase.py |
| .env file loading | Comments, quotes, dot-notation, type coercion | loaders_showcase.py |
| Environment variables | EnvironmentLoader with prefix and nesting |
loaders_showcase.py |
| HTTP remote loading | HTTPLoader with auth and headers |
loaders_showcase.py |
| AWS SSM Parameter Store | SSMLoader with path prefix and decryption |
loaders_showcase.py |
| Deep merge vs shallow | How multi-source merge preserves/replaces keys | loaders_showcase.py |
| Environment resolution | default + production section merging |
basic_usage.py |
env_prefix auto-override |
Config(env_prefix="MYAPP") env var overrides |
config_management.py |
merge_strategy |
Per-path REPLACE/MERGE/APPEND strategies | config_management.py |
| Config reload | Manual config.reload(), incremental, dry_run |
config_management.py |
on_change callbacks |
React to config changes during reload | config_management.py |
freeze() |
Make config immutable after loading | config_management.py |
| Versioning | Save, list, rollback config versions | config_management.py |
| Config diff | Compare two configs, see added/removed/modified | config_management.py |
| Drift detection | Detect actual vs intended config drift | config_management.py |
config.layers |
Inspect source precedence stack | config_management.py |
| Custom hooks | Global, key-specific, and condition hooks | extensibility.py |
| Custom loaders | Extend Loader base class for custom sources |
extensibility.py |
| Observability / metrics | Access counts, reload stats, performance | extensibility.py |
| Event emission | @emitter.on("reload") decorator pattern |
extensibility.py |
| Composition | _include and _defaults directives |
extensibility.py |
| Export | config.export("json"), YAML, TOML |
extensibility.py |
Standalone validate() |
Post-hoc validation with Pydantic models | extensibility.py |
| Introspection API | keys(), has(), get(), schema(), explain() |
introspection_api.py |
| Pydantic validation | Model-based schema validation | validation_example.py |
| JSON Schema validation | Dictionary schema with defaults | validation_example.py |
| Secret stores | DictSecretStore, EnvSecretStore, MultiSecretStore | secret_store_example.py |
| Vault authentication | OIDC, LDAP, Kerberos, K8s, AWS, JWT, AppRole | vault_auth_examples.py |
| Async config | AsyncConfig, AsyncYamlLoader, async reload |
async_example.py |
| ConfigBuilder | Fluent builder pattern | basic_usage.py |
| Config[T] typed access | Full IDE autocomplete via Pydantic models | typed_config.py |
| End-to-end demo | Complete working application | working_demo.py |
Example Files
| File | Focus Area | Examples |
|---|---|---|
| loaders_showcase.py | All loader types | TOML, INI, .env, env vars, HTTP, SSM, deep/shallow merge |
| config_management.py | Config lifecycle | Reload, freeze, versioning, diff, drift, callbacks, layers |
| extensibility.py | Customization | Hooks, custom loaders, observability, events, composition, export |
| basic_usage.py | Getting started | YAML/JSON, env resolution, ConfigBuilder |
| introspection_api.py | Querying config | keys, has, get, schema, explain, set |
| validation_example.py | Validation | Pydantic models, JSON Schema, defaults |
| secret_store_example.py | Secrets | Multiple providers, fallback chains, caching |
| vault_auth_examples.py | Vault auth | 10+ authentication methods |
| async_example.py | Async support | Async loading, parallel sources, async validation |
| typed_config.py | Type safety | Config[T], nested models, multi-source typed |
| working_demo.py | End-to-end | Complete real-world application |
Run any example:
python examples/loaders_showcase.py # All loader types
python examples/config_management.py # Reload, freeze, versioning, diff
python examples/extensibility.py # Hooks, custom loaders, events
python examples/basic_usage.py # Getting started
Documentation
API Reference
- Config Class - Main configuration class
- Loaders - Configuration loaders
- Secret Stores - Secret management
- Validators - Schema validation
- CLI - Command-line interface
Guides
- Secret Stores Guide - Complete secret store documentation
- Vault Authentication - HashiCorp Vault authentication methods
- Migration Guide - Migrating from other libraries
Feature Comparison
| Feature | Confii | python-dotenv | Dynaconf | Hydra | OmegaConf | pydantic-settings |
|---|---|---|---|---|---|---|
| Multiple file formats | ✅✅ | ❌ | ✅ | ✅ | ✅ | Limited |
| Source tracking | ✅✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Cloud storage | ✅✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Secret stores | ✅✅ | ❌ | ⚠️ | ❌ | ❌ | ❌ |
| Schema validation | ✅ | ❌ | ⚠️ | ✅ | ❌ | ✅✅ |
| Type safety | ✅ | ❌ | ❌ | ✅ | ✅ | ✅✅ |
| Configuration composition | ✅ | ❌ | ❌ | ✅✅ | ❌ | ❌ |
| Override system | ✅✅ | ❌ | ⚠️ | ✅✅ | ✅✅ | ❌ |
| Introspection API | ✅✅ | ❌ | ❌ | ❌ | ✅ | ❌ |
| Incremental reloading | ✅✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Async/await support | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Configuration versioning | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Drift detection | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| Observability/metrics | ✅ | ❌ | ❌ | ❌ | ❌ | ❌ |
| IDE autocomplete | ✅ | ❌ | ❌ | ✅ | ✅ | ✅✅ |
| Hot reload | ✅ | ❌ | ✅ | ❌ | ❌ | ❌ |
| Type casting | ✅ | ❌ | ✅ | ✅ | ✅ | ✅ |
Legend: ✅✅ = Strong/Unique feature, ✅ = Supported, ⚠️ = Partial support, ❌ = Not supported
Testing
import pytest
from confii import Config
from confii.loaders import YamlLoader
@pytest.fixture
def test_config():
return Config(loaders=[
YamlLoader("tests/fixtures/test_config.yaml")
])
def test_database_config(test_config):
assert test_config.database.host == "localhost"
assert test_config.database.port == 5432
Run tests:
# Run all tests
pytest
# Run with coverage
pytest --cov=confii
# Run specific test file
pytest tests/test_config.py
Contributing
We welcome contributions! Please see our Contributing Guide for details.
# Clone repository
git clone https://github.com/confiify/confii-py.git
cd confii-py
# Install development dependencies
make setup
# Run tests
make test
# Run all checks (lint, type check, tests)
make check
License
MIT License. See LICENSE.txt for details.
Links
- 📖 Documentation: GitHub Repository
- 📦 PyPI Package: confii on PyPI
- 🐛 Issue Tracker: GitHub Issues
- 📝 Changelog: CHANGELOG.md
Built with ❤️ by confiify and contributors.
Made for developers who value type safety, observability, and developer experience.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file confii-2026.3.30.4.tar.gz.
File metadata
- Download URL: confii-2026.3.30.4.tar.gz
- Upload date:
- Size: 17.2 MB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
817c51d3d961cacaef52cc6908671970f9b9a7760161824803d1743fea95f63a
|
|
| MD5 |
f250b6fcb4a0aa5547c12460da728a74
|
|
| BLAKE2b-256 |
a7030c4ba170d9f23f190cf19c77a0ed0d3adc11ffbc534594096af3365db35e
|
Provenance
The following attestation bundles were made for confii-2026.3.30.4.tar.gz:
Publisher:
release.yml on confiify/confii-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
confii-2026.3.30.4.tar.gz -
Subject digest:
817c51d3d961cacaef52cc6908671970f9b9a7760161824803d1743fea95f63a - Sigstore transparency entry: 1199733980
- Sigstore integration time:
-
Permalink:
confiify/confii-py@e4e85a0f3cbc7a597999754bf68f8f426b3fca5f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/confiify
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e4e85a0f3cbc7a597999754bf68f8f426b3fca5f -
Trigger Event:
workflow_run
-
Statement type:
File details
Details for the file confii-2026.3.30.4-py3-none-any.whl.
File metadata
- Download URL: confii-2026.3.30.4-py3-none-any.whl
- Upload date:
- Size: 172.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
7cd8b8b0d4196cb04b9034232e6b510e7640d2aaa1475eacb17a936f2a13bdab
|
|
| MD5 |
4125cf9c687620255834b0840c3b2105
|
|
| BLAKE2b-256 |
23e5ffd2d9cc9a7f7d569fd0e043c1bc2786fcb72782ddf015955d54427c46f4
|
Provenance
The following attestation bundles were made for confii-2026.3.30.4-py3-none-any.whl:
Publisher:
release.yml on confiify/confii-py
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
confii-2026.3.30.4-py3-none-any.whl -
Subject digest:
7cd8b8b0d4196cb04b9034232e6b510e7640d2aaa1475eacb17a936f2a13bdab - Sigstore transparency entry: 1199733985
- Sigstore integration time:
-
Permalink:
confiify/confii-py@e4e85a0f3cbc7a597999754bf68f8f426b3fca5f -
Branch / Tag:
refs/heads/main - Owner: https://github.com/confiify
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
release.yml@e4e85a0f3cbc7a597999754bf68f8f426b3fca5f -
Trigger Event:
workflow_run
-
Statement type: