API Reference
This section contains the API documentation for Chantal’s Python modules.
Note
API documentation is generated from Python docstrings using Sphinx autodoc.
Core Modules
Configuration
- class chantal.core.config.ApkConfig(*, branch: str, repository: str = 'main', architecture: str = 'x86_64')[source]
Bases:
BaseModelAlpine APK-specific configuration.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.AptConfig(*, distribution: str, components: list[str] = <factory>, architectures: list[str] = <factory>, include_source_packages: bool = False)[source]
Bases:
BaseModelAPT/DEB-specific configuration.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.AuthConfig(*, type: str, cert_dir: str | None = None, cert_file: str | None = None, key_file: str | None = None, username: str | None = None, password: str | None = None, token: str | None = None, headers: dict[str, str] | None = None, verify_ssl: bool = True, ca_bundle: str | None = None)[source]
Bases:
BaseModelRepository authentication configuration.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.CacheConfig(*, enabled: bool = False, max_age_hours: int | None = None)[source]
Bases:
BaseModelMetadata cache configuration.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.ConfigLoader(config_path: Path)[source]
Bases:
objectConfiguration file loader with include support.
- load() GlobalConfig[source]
Load configuration from YAML file.
- Returns:
GlobalConfig instance
- Raises:
FileNotFoundError – If config file doesn’t exist
ValueError – If config is invalid
- class chantal.core.config.DatabaseConfig(*, url: str = 'sqlite:///chantal.db', pool_size: int = 5, max_overflow: int = 10, echo: bool = False)[source]
Bases:
BaseModelDatabase configuration.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.DebFilterConfig(*, components: ListFilterConfig | None = None, priorities: ListFilterConfig | None = None, sections: ListFilterConfig | None = None)[source]
Bases:
BaseModelDEB/APT-specific filters (future support).
- components: ListFilterConfig | None
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- priorities: ListFilterConfig | None
- sections: ListFilterConfig | None
- class chantal.core.config.DownloadConfig(*, backend: str = 'requests', parallel: int = 1, timeout: int = 300, retry_attempts: int = 3, verify_checksum: bool = True)[source]
Bases:
BaseModelDownload configuration for file downloads.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.FilterConfig(*, metadata: GenericMetadataFilterConfig | None = None, patterns: PatternFilterConfig | None = None, post_processing: PostProcessingConfig | None = None, rpm: RpmFilterConfig | None = None, deb: DebFilterConfig | None = None, include_packages: list[str] | None = None, exclude_packages: list[str] | None = None, include_architectures: list[str] | None = None, exclude_architectures: list[str] | None = None)[source]
Bases:
BaseModelPackage filtering configuration.
Supports both new structure and legacy flat structure for backward compatibility.
Structure: - metadata: Generic filters (all package types) - rpm/deb/helm: Plugin-specific filters - patterns: Generic regex patterns - post_processing: Applied after all filters
- deb: DebFilterConfig | None
- metadata: GenericMetadataFilterConfig | None
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- normalize() FilterConfig[source]
Normalize legacy config to new structure.
- patterns: PatternFilterConfig | None
- post_processing: PostProcessingConfig | None
- rpm: RpmFilterConfig | None
- validate_for_repo_type(repo_type: str) None[source]
Validate that only appropriate plugin-specific filters are used.
- Parameters:
repo_type – Repository type (rpm, deb, etc.)
- Raises:
ValueError – If incompatible filters are specified
- class chantal.core.config.GenericMetadataFilterConfig(*, size_bytes: SizeFilterConfig | None = None, build_time: TimeFilterConfig | None = None, architectures: ListFilterConfig | None = None)[source]
Bases:
BaseModelGeneric metadata filters (work for all package types).
- architectures: ListFilterConfig | None
- build_time: TimeFilterConfig | None
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- size_bytes: SizeFilterConfig | None
- class chantal.core.config.GlobalConfig(*, database: DatabaseConfig = <factory>, storage: StorageConfig = <factory>, cache: CacheConfig | None = <factory>, proxy: ProxyConfig | None = None, ssl: SSLConfig | None = None, download: DownloadConfig | None = <factory>, repositories: list[RepositoryConfig] = <factory>, views: list[ViewConfig] = <factory>, include: str | None = None)[source]
Bases:
BaseModelGlobal Chantal configuration.
- cache: CacheConfig | None
- database: DatabaseConfig
- download: DownloadConfig | None
- get_enabled_repositories() list[RepositoryConfig][source]
Get all enabled repositories.
- get_repositories_by_type(repo_type: str) list[RepositoryConfig][source]
Get all repositories of a specific type.
- get_repository(repo_id: str) RepositoryConfig | None[source]
Get repository configuration by ID.
- get_view(view_name: str) ViewConfig | None[source]
Get view configuration by name.
- get_views_for_repository(repo_id: str) list[ViewConfig][source]
Get all views that contain a specific repository.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- proxy: ProxyConfig | None
- repositories: list[RepositoryConfig]
- storage: StorageConfig
- views: list[ViewConfig]
- class chantal.core.config.ListFilterConfig(*, include: list[str] | None = None, exclude: list[str] | None = None)[source]
Bases:
BaseModelGeneric list-based filtering (include/exclude).
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.MetadataConfig(*, compression: Literal['auto', 'gzip', 'zstandard', 'bzip2', 'none'] = 'auto')[source]
Bases:
BaseModelMetadata generation configuration (RPM, APT, etc.).
- compression: Literal['auto', 'gzip', 'zstandard', 'bzip2', 'none']
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.PatternFilterConfig(*, include: list[str] | None = None, exclude: list[str] | None = None)[source]
Bases:
BaseModelPattern-based filters (regex).
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.PostProcessingConfig(*, only_latest_version: bool = False, only_latest_n_versions: int | None = None)[source]
Bases:
BaseModelPost-processing configuration (applied after filtering).
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.ProxyConfig(*, http_proxy: str | None = None, https_proxy: str | None = None, no_proxy: str | None = None, username: str | None = None, password: str | None = None)[source]
Bases:
BaseModelHTTP proxy configuration.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.RepositoryConfig(*, id: str, name: str | None = None, type: str, feed: str, enabled: bool = True, mode: Literal['mirror', 'filtered', 'hosted']='filtered', tags: list[str] | None = <factory>, auth: AuthConfig | None = None, latest_path: str | None = None, snapshots_path: str | None = None, retention: RetentionConfig | None = <factory>, schedule: ScheduleConfig | None = <factory>, filters: FilterConfig | None = None, proxy: ProxyConfig | None = None, ssl: SSLConfig | None = None, cache_enabled: bool | None = None, apk: ApkConfig | None = None, apt: AptConfig | None = None, metadata: MetadataConfig | None = <factory>)[source]
Bases:
BaseModelRepository configuration.
- auth: AuthConfig | None
- filters: FilterConfig | None
- metadata: MetadataConfig | None
- mode: Literal['mirror', 'filtered', 'hosted']
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- proxy: ProxyConfig | None
- retention: RetentionConfig | None
- schedule: ScheduleConfig | None
- validate_mode_and_filters() RepositoryConfig[source]
Validate that mirror mode is not used with filters.
- class chantal.core.config.RetentionConfig(*, policy: str = 'mirror', keep_count: int | None = None)[source]
Bases:
BaseModelPackage retention policy configuration.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.RpmFilterConfig(*, exclude_source_rpms: bool = False, groups: ListFilterConfig | None = None, licenses: ListFilterConfig | None = None, vendors: ListFilterConfig | None = None, epochs: ListFilterConfig | None = None)[source]
Bases:
BaseModelRPM-specific filters.
- epochs: ListFilterConfig | None
- groups: ListFilterConfig | None
- licenses: ListFilterConfig | None
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- vendors: ListFilterConfig | None
- class chantal.core.config.SSLConfig(*, ca_bundle: str | None = None, ca_cert: str | None = None, verify: bool = True, client_cert: str | None = None, client_key: str | None = None)[source]
Bases:
BaseModelSSL/TLS configuration for HTTPS connections.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.ScheduleConfig(*, enabled: bool = False, cron: str = '0 2 * * *', create_snapshot: bool = False, snapshot_name_template: str = '{repo_id}-{date}')[source]
Bases:
BaseModelRepository sync schedule configuration.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.SizeFilterConfig(*, min: int | None = None, max: int | None = None)[source]
Bases:
BaseModelSize-based filtering.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.StorageConfig(*, base_path: str = '/var/lib/chantal', pool_path: str | None = None, published_path: str = '/var/www/repos', temp_path: str | None = None, cache_path: str | None = None)[source]
Bases:
BaseModelStorage paths configuration.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.TimeFilterConfig(*, newer_than: str | None = None, older_than: str | None = None, last_n_days: int | None = None)[source]
Bases:
BaseModelTime-based filtering.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- class chantal.core.config.ViewConfig(*, name: str, description: str | None = None, repos: list[str], publish_path: str | None = None)[source]
Bases:
BaseModelView configuration - groups multiple repositories into one virtual repository.
- model_config = {}
Configuration for the model, should be a dictionary conforming to [ConfigDict][pydantic.config.ConfigDict].
- validate_repos(all_repos: list[RepositoryConfig]) None[source]
Validate that all referenced repositories exist and have same type.
- Parameters:
all_repos – List of all repository configurations
- Raises:
ValueError – If repo doesn’t exist or types don’t match
- chantal.core.config.create_example_config(output_path: Path) None[source]
Create an example configuration file.
- Parameters:
output_path – Path to write example config
- chantal.core.config.load_config(config_path: Path | None = None) GlobalConfig[source]
Load configuration from file.
Priority: 1. Explicit config_path parameter (–config CLI flag) 2. CHANTAL_CONFIG environment variable 3. Default locations (/etc/chantal/config.yaml, ~/.config/chantal/config.yaml, ./config.yaml)
- Parameters:
config_path – Path to config file. If None, tries CHANTAL_CONFIG env or default locations.
- Returns:
GlobalConfig instance
- Raises:
FileNotFoundError – If no config file found
Storage
- class chantal.core.storage.StorageManager(config: StorageConfig)[source]
Bases:
objectUniversal content-addressed storage manager.
Uses SHA256 hashing for deduplication. All package types (RPM, DEB, etc.) are stored in a unified pool with a 2-level directory structure:
pool/ab/cd/abc123…def456_filename.rpm
This allows for efficient storage and instant deduplication.
- add_package(source_path: Path, filename: str, verify_checksum: bool = True) tuple[str, str, int][source]
Add package to content-addressed pool.
If package with same SHA256 already exists, it won’t be copied again (instant deduplication).
- Parameters:
source_path – Path to source package file
filename – Original filename (without path)
verify_checksum – If True, verify SHA256 matches after copy
- Returns:
Tuple of (sha256, pool_path, size_bytes)
- Raises:
ValueError – If checksum verification fails
FileNotFoundError – If source file doesn’t exist
- add_repository_file(source_path: Path, filename: str, verify_checksum: bool = True) tuple[str, str, int][source]
Add repository file (metadata/installer) to content-addressed pool.
Similar to add_package() but stores files in pool/files/ subdirectory. If file with same SHA256 already exists, it won’t be copied again (instant deduplication).
- Parameters:
source_path – Path to source file
filename – Original filename (without path)
verify_checksum – If True, verify SHA256 matches after copy
- Returns:
Tuple of (sha256, pool_path, size_bytes)
- Raises:
ValueError – If checksum verification fails
FileNotFoundError – If source file doesn’t exist
- calculate_sha256(file_path: Path) str[source]
Calculate SHA256 hash of a file.
- Parameters:
file_path – Path to file
- Returns:
Hex-encoded SHA256 hash
- cleanup_orphaned_files(session: Session, dry_run: bool = True) tuple[int, int][source]
Remove files from pool that are not referenced in database.
- Parameters:
session – Database session
dry_run – If True, only report what would be deleted
- Returns:
Tuple of (files_removed, bytes_freed)
- create_hardlink(sha256: str, filename: str, target_path: Path) None[source]
Create hardlink from pool to target location.
This is used for publishing - creates zero-copy references to pool files.
- Parameters:
sha256 – SHA256 hash of package
filename – Original filename
target_path – Target path for hardlink
- Raises:
FileNotFoundError – If source file not in pool
- get_absolute_pool_path(sha256: str, filename: str, pool_type: str = 'content') Path[source]
Get absolute pool path for a file.
- Parameters:
sha256 – SHA256 hash
filename – Original filename
pool_type – Pool type - “content” for packages, “files” for metadata/installer
- Returns:
Absolute path in pool
- get_orphaned_files(session: Session) list[Path][source]
Find files in pool that are not referenced in database.
Checks both ContentItem (packages) and RepositoryFile (metadata/installer) tables to find orphaned files in both pool subdirectories.
- Parameters:
session – Database session
- Returns:
List of orphaned file paths
- get_pool_path(sha256: str, filename: str, pool_type: str = 'content') str[source]
Get relative pool path for a file.
Uses 2-level directory structure for better filesystem performance: - Pool type subdirectory (content/ or files/) - First 2 chars of SHA256 - Next 2 chars of SHA256 - Full SHA256 + filename
Example: content/ab/cd/abc123…def456_nginx-1.20.1.rpm Example: files/56/78/5678abc_updateinfo.xml.gz
- Parameters:
sha256 – SHA256 hash (64 hex chars)
filename – Original filename
pool_type – Pool type - “content” for packages, “files” for metadata/installer
- Returns:
Relative pool path (e.g., “content/ab/cd/abc123_file.rpm”)
Database Models
- class chantal.db.models.Base(**kwargs: Any)[source]
Bases:
DeclarativeBaseBase class for all database models.
- class chantal.db.models.ContentItem(**kwargs)[source]
Bases:
BaseGeneric content model for all package types (RPM, Helm, APT, PyPI, etc.).
Uses content-addressed storage - one content item file can be referenced by multiple repositories and snapshots.
Type-specific metadata is stored as JSON in the metadata field.
- property nevra: str | None
Version-Release.Arch).
Returns None for non-RPM content types.
- Type:
Get NEVRA string for RPM packages (Name-Epoch
- repositories: Mapped[list[Repository]]
- class chantal.db.models.Repository(**kwargs)[source]
Bases:
BaseRepository model - represents a configured RPM/APT repository.
- content_items: Mapped[list[ContentItem]]
- repository_files: Mapped[list[RepositoryFile]]
- sync_history: Mapped[list[SyncHistory]]
- class chantal.db.models.RepositoryFile(**kwargs)[source]
Bases:
BaseRepository metadata and installer files.
Stores non-package files like: - Metadata: updateinfo.xml, filelists.xml, comps.xml, modules.yaml, etc. - Signatures: repomd.xml.asc, Release.gpg - Kickstart: vmlinuz, initrd.img, .treeinfo - Debian installer: debian-installer/ - SUSE specific: susedata.xml, patterns.xml, products.xml
Uses content-addressed storage like ContentItem - files can be shared across multiple repositories and snapshots.
- repositories: Mapped[list[Repository]]
- class chantal.db.models.RepositoryMode(*values)[source]
-
Repository operation modes.
MIRROR: Full mirror, no filtering, metadata unchanged
FILTERED: Filtered packages with customized metadata (include/exclude, retention, etc.)
HOSTED: Self-hosted packages (for future use)
- FILTERED = 'filtered'
- HOSTED = 'hosted'
- MIRROR = 'mirror'
- class chantal.db.models.Snapshot(**kwargs)[source]
Bases:
BaseSnapshot model - represents an immutable point-in-time repository state.
A snapshot is a collection of packages. Multiple snapshots can reference the same package (content-addressed storage with reference counting).
- content_items: Mapped[list[ContentItem]]
- repository: Mapped[Repository]
- repository_files: Mapped[list[RepositoryFile]]
- class chantal.db.models.SyncHistory(**kwargs)[source]
Bases:
BaseSync history model - tracks repository synchronization events.
- repository: Mapped[Repository]
- class chantal.db.models.View(**kwargs)[source]
Bases:
BaseView model - groups multiple repositories into a single virtual repository.
A view is a collection of repositories that can be published together as one. Views can be published as “latest” (mutable) or as snapshots (immutable).
- view_repositories: Mapped[list[ViewRepository]]
- view_snapshots: Mapped[list[ViewSnapshot]]
- class chantal.db.models.ViewRepository(**kwargs)[source]
Bases:
BaseJunction table: View -> Repositories (with ordering).
Defines which repositories are part of a view and their precedence order.
- repository: Mapped[Repository]
- class chantal.db.models.ViewSnapshot(**kwargs)[source]
Bases:
BaseView snapshot model - represents an atomic snapshot of all repositories in a view.
When creating a view snapshot, all repositories in the view are snapshotted simultaneously, creating an immutable point-in-time state of the entire view.
Plugins
Base Plugins
RPM Plugin
Note
RPM plugin documentation is available in the RPM Plugin section.
The RPM plugin is implemented in:
chantal.plugins.rpm.sync- RPM repository syncingchantal.plugins.rpm.publisher- RPM metadata generationchantal.plugins.rpm.models- RPM metadata modelschantal.plugins.rpm.parsers- Repomd.xml parsing
APT Plugin
Note
APT plugin documentation is available in the APT Plugin section.
The APT plugin is implemented in:
chantal.plugins.apt.sync- APT repository syncingchantal.plugins.apt.publisher- Debian metadata generationchantal.plugins.apt.models- Debian package modelschantal.plugins.apt.parsers- Release/Packages parsing
Helm Plugin
Note
Helm plugin documentation is available in the Helm Plugin section.
The Helm plugin is implemented in:
chantal.plugins.helm.sync- Helm chart syncingchantal.plugins.helm.publisher- index.yaml generationchantal.plugins.helm.models- Helm chart models
Alpine APK Plugin
Note
Alpine APK plugin documentation is available in the Alpine APK Plugin section.
The APK plugin is implemented in:
chantal.plugins.apk.sync- APK package syncingchantal.plugins.apk.publisher- APKINDEX generationchantal.plugins.apk.models- APK package models
CLI Commands
Note
CLI command documentation is available in the CLI Commands section.
The CLI is implemented as modular command groups in:
chantal.cli.main- Entry point and command registrationchantal.cli.repo_commands- Repository managementchantal.cli.snapshot_commands- Snapshot managementchantal.cli.publish_commands- Publishingchantal.cli.view_commands- View managementchantal.cli.content_commands- Content searchchantal.cli.db_commands- Database managementchantal.cli.pool_commands- Storage pool management