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: BaseModel

Alpine APK-specific configuration.

architecture: str
branch: str
model_config = {'extra': 'forbid'}

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

repository: str
class chantal.core.config.AptConfig(*, distribution: str, components: list[str] = <factory>, architectures: list[str] = <factory>, include_source_packages: bool = False, include_contents: bool = False, include_translations: bool = False, by_hash: bool = False, origin: str | None = None, label: str | None = None, suite: str | None = None, codename: str | None = None, not_automatic: bool = False, but_automatic_upgrades: bool = False, valid_until_days: int | None = None)[source]

Bases: BaseModel

APT/DEB-specific configuration.

architectures: list[str]
but_automatic_upgrades: bool
by_hash: bool
codename: str | None
components: list[str]
distribution: str
include_contents: bool
include_source_packages: bool
include_translations: bool
label: str | None
model_config = {'extra': 'forbid'}

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

not_automatic: bool
origin: str | None
suite: str | None
valid_until_days: int | None
validate_release_fields() AptConfig[source]

Validate the generated-Release field options.

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)[source]

Bases: BaseModel

Repository authentication configuration.

cert_dir: str | None
cert_file: str | None
headers: dict[str, str] | None
key_file: str | None
model_config = {'extra': 'forbid'}

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

password: str | None
token: str | None
type: str
username: str | None
class chantal.core.config.CacheConfig(*, enabled: bool = False, max_age_hours: int | None = None)[source]

Bases: BaseModel

Metadata cache configuration.

enabled: bool
max_age_hours: int | None
model_config = {'extra': 'forbid'}

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

classmethod validate_max_age(v: int | None) int | None[source]

Validate max_age_hours.

class chantal.core.config.ConfigLoader(config_path: Path)[source]

Bases: object

Configuration file loader with include support.

load() GlobalConfig[source]

Load configuration from YAML file.

Returns:

GlobalConfig instance

Raises:
class chantal.core.config.DatabaseConfig(*, url: str = 'sqlite:///chantal.db', pool_size: int = 5, max_overflow: int = 10, echo: bool = False)[source]

Bases: BaseModel

Database configuration.

echo: bool
max_overflow: int
model_config = {'extra': 'forbid'}

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

pool_size: int
url: str
class chantal.core.config.DebFilterConfig(*, components: ListFilterConfig | None = None, priorities: ListFilterConfig | None = None, sections: ListFilterConfig | None = None)[source]

Bases: BaseModel

DEB/APT-specific filters (future support).

components: ListFilterConfig | None
model_config = {'extra': 'forbid'}

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: BaseModel

Download configuration for file downloads.

backend: str
model_config = {'extra': 'forbid'}

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

parallel: int
retry_attempts: int
timeout: int
classmethod validate_backend(v: str) str[source]

Validate download backend.

classmethod validate_parallel(v: int) int[source]

Validate parallel download count.

classmethod validate_retry_attempts(v: int) int[source]

Validate retry attempts.

classmethod validate_timeout(v: int) int[source]

Validate timeout value.

verify_checksum: bool
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: BaseModel

Package 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
exclude_architectures: list[str] | None
exclude_packages: list[str] | None
include_architectures: list[str] | None
include_packages: list[str] | None
metadata: GenericMetadataFilterConfig | None
model_config = {'extra': 'forbid'}

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, apt, etc.)

Raises:

ValueError – If incompatible filters are specified

classmethod validate_patterns_legacy(v: list[str] | None) list[str] | None[source]

Validate regex patterns (legacy).

class chantal.core.config.GenericMetadataFilterConfig(*, size_bytes: SizeFilterConfig | None = None, build_time: TimeFilterConfig | None = None, architectures: ListFilterConfig | None = None)[source]

Bases: BaseModel

Generic metadata filters (work for all package types).

architectures: ListFilterConfig | None
build_time: TimeFilterConfig | None
model_config = {'extra': 'forbid'}

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>, gpg: GpgConfig | None = None, verify: SignatureVerificationConfig | None = None, repositories: list[RepositoryConfig] = <factory>, views: list[ViewConfig] = <factory>, include: str | None = None)[source]

Bases: BaseModel

Global 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.

gpg: GpgConfig | None
include: str | None
model_config = {'extra': 'forbid'}

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

proxy: ProxyConfig | None
repositories: list[RepositoryConfig]
ssl: SSLConfig | None
storage: StorageConfig
validate_repositories_and_views() GlobalConfig[source]

Normalize/validate repository filters and validate views at load time.

  • Migrate legacy flat filters to the structured form for every repo (previously only the RPM plugin did this, so APT silently ignored legacy include_packages/exclude_packages).

  • Reject plugin-specific filters used with the wrong repository type.

  • Reject views that reference unknown repositories or mix repo types.

verify: SignatureVerificationConfig | None
views: list[ViewConfig]
class chantal.core.config.GpgConfig(*, enabled: bool = True, key_id: str | None = None, key_file: str | None = None, passphrase: str | None = None, passphrase_file: str | None = None, gnupg_home: str | None = None, public_key_file: str | None = None, public_key_name: str = 'key.gpg', generate_key: bool = False, key_name: str | None = None, key_email: str | None = None)[source]

Bases: BaseModel

GPG signing configuration for APT repositories.

Used to sign regenerated metadata (Release) in filtered mode so that clients can verify the repository without [trusted=yes].

The signing key can be provided in three ways (checked in this order):

  1. key_file - import a private (secret) key from an ASCII-armored file.

  2. key_id - use a key already present in the keyring / gnupg_home.

  3. generate_key - generate a new keypair if none of the above is set.

enabled: bool
generate_key: bool
gnupg_home: str | None
key_email: str | None
key_file: str | None
key_id: str | None
key_name: str | None
model_config = {'extra': 'forbid'}

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

passphrase: str | None
passphrase_file: str | None
public_key_file: str | None
public_key_name: str
read_passphrase() str | None[source]

Resolve the passphrase from file or inline value.

Returns:

The passphrase string, or None if no passphrase is configured.

validate_key_source() GpgConfig[source]

Ensure at least one key source is configured when signing is enabled.

class chantal.core.config.ListFilterConfig(*, include: list[str] | None = None, exclude: list[str] | None = None)[source]

Bases: BaseModel

Generic list-based filtering (include/exclude).

exclude: list[str] | None
include: list[str] | None
model_config = {'extra': 'forbid'}

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: BaseModel

Metadata generation configuration (RPM, APT, etc.).

compression: Literal['auto', 'gzip', 'zstandard', 'bzip2', 'none']
model_config = {'extra': 'forbid'}

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

classmethod validate_compression(v: str) str[source]

Validate compression format.

class chantal.core.config.PatternFilterConfig(*, include: list[str] | None = None, exclude: list[str] | None = None)[source]

Bases: BaseModel

Pattern-based filters (regex).

exclude: list[str] | None
include: list[str] | None
model_config = {'extra': 'forbid'}

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

classmethod validate_patterns(v: list[str] | None) list[str] | None[source]

Validate regex patterns.

class chantal.core.config.PostProcessingConfig(*, only_latest_version: bool = False, only_latest_n_versions: int | None = None)[source]

Bases: BaseModel

Post-processing configuration (applied after filtering).

model_config = {'extra': 'forbid'}

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

only_latest_n_versions: int | None
only_latest_version: bool
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: BaseModel

HTTP proxy configuration.

http_proxy: str | None
https_proxy: str | None
model_config = {'extra': 'forbid'}

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

no_proxy: str | None
password: str | None
username: str | None
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>, gpg: GpgConfig | None = None, verify: SignatureVerificationConfig | None = None)[source]

Bases: BaseModel

Repository configuration.

apk: ApkConfig | None
apt: AptConfig | None
auth: AuthConfig | None
cache_enabled: bool | None
property display_name: str

Get display name (use name if set, otherwise id).

enabled: bool
feed: str
filters: FilterConfig | None
gpg: GpgConfig | None
id: str
latest_path: str | None
metadata: MetadataConfig | None
mode: Literal['mirror', 'filtered', 'hosted']
model_config = {'extra': 'forbid'}

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

name: str | None
proxy: ProxyConfig | None
retention: RetentionConfig | None
schedule: ScheduleConfig | None
snapshots_path: str | None
ssl: SSLConfig | None
tags: list[str] | None
type: str
validate_mode_and_filters() RepositoryConfig[source]

Validate mode/filters and the feed requirement.

classmethod validate_type(v: str) str[source]

Validate repository type.

verify: SignatureVerificationConfig | None
class chantal.core.config.RetentionConfig(*, policy: str = 'mirror', keep_count: int | None = None)[source]

Bases: BaseModel

Package retention policy configuration.

keep_count: int | None
model_config = {'extra': 'forbid'}

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

policy: str
classmethod validate_policy(v: str) str[source]

Validate retention policy.

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: BaseModel

RPM-specific filters.

epochs: ListFilterConfig | None
exclude_source_rpms: bool
groups: ListFilterConfig | None
licenses: ListFilterConfig | None
model_config = {'extra': 'forbid'}

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: BaseModel

SSL/TLS configuration for HTTPS connections.

ca_bundle: str | None
ca_cert: str | None
client_cert: str | None
client_key: str | None
model_config = {'extra': 'forbid'}

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

verify: bool
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: BaseModel

Repository sync schedule configuration.

create_snapshot: bool
cron: str
enabled: bool
model_config = {'extra': 'forbid'}

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

snapshot_name_template: str
class chantal.core.config.SignatureVerificationConfig(*, enabled: bool = False, repo_gpgcheck: bool = True, gpgcheck: bool = True, key_files: list[str] = <factory>, keys: list[str] = <factory>, trusted_fingerprints: list[str] = <factory>, client_key_name: str = 'RPM-GPG-KEY-{repo_id}', gnupg_home: str | None = None, on_missing_signature: Literal['fail', 'warn', 'skip']='fail', on_invalid_signature: Literal['fail', 'warn', 'skip']='fail')[source]

Bases: BaseModel

Verify the authenticity of an upstream repository via GPG.

This is independent of GpgConfig (which holds the private signing key used to re-sign regenerated metadata). Verification needs public trust anchors - the upstream vendor’s public key(s).

Integrity (SHA256) is always checked during sync; this adds authenticity (the metadata/packages were signed by a trusted key), analogous to dnf’s repo_gpgcheck / gpgcheck and apt’s Release signature check.

client_key_name: str
enabled: bool
gnupg_home: str | None
gpgcheck: bool
key_files: list[str]
keys: list[str]
model_config = {'extra': 'forbid'}

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

on_invalid_signature: Literal['fail', 'warn', 'skip']
on_missing_signature: Literal['fail', 'warn', 'skip']
repo_gpgcheck: bool
trusted_fingerprints: list[str]
validate_config() SignatureVerificationConfig[source]

Validate the verification configuration when enabled.

class chantal.core.config.SizeFilterConfig(*, min: int | None = None, max: int | None = None)[source]

Bases: BaseModel

Size-based filtering.

max: int | None
min: int | None
model_config = {'extra': 'forbid'}

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: BaseModel

Storage paths configuration.

base_path: str
cache_path: str | None
get_cache_path() Path | None[source]

Get cache path (None if caching disabled).

get_pool_path() Path[source]

Get pool path (with default).

get_temp_path() Path[source]

Get temp path (with default).

model_config = {'extra': 'forbid'}

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

pool_path: str | None
published_path: str
temp_path: str | None
class chantal.core.config.TimeFilterConfig(*, newer_than: str | None = None, older_than: str | None = None, last_n_days: int | None = None)[source]

Bases: BaseModel

Time-based filtering.

last_n_days: int | None
model_config = {'extra': 'forbid'}

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

newer_than: str | None
older_than: str | None
class chantal.core.config.ViewConfig(*, name: str, description: str | None = None, repos: list[str], publish_path: str | None = None)[source]

Bases: BaseModel

View configuration - groups multiple repositories into one virtual repository.

description: str | None
model_config = {'extra': 'forbid'}

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

name: str
publish_path: str | None
repos: list[str]
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.generate_json_schema() dict[str, Any][source]

Generate the JSON Schema for the Chantal configuration file.

The schema is derived from the GlobalConfig Pydantic model, so it is always in sync with the actual configuration validation. It can be used by editors (e.g. the VS Code YAML extension) for validation and autocompletion of config.yaml files.

Returns:

A JSON Schema (draft 2020-12) document as a dictionary.

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: object

Universal 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:
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:
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, grace_seconds: float | None = None) 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

  • grace_seconds – Skip files newer than this many seconds (see get_orphaned_files()).

Returns:

Tuple of (files_removed, bytes_freed)

Create hardlink from pool to target location.

This is used for publishing - creates zero-copy references to pool files (falling back to a copy across filesystems).

Parameters:
  • sha256 – SHA256 hash of package

  • filename – Original filename

  • target_path – Target path for hardlink

Raises:

FileNotFoundError – If source file not in pool

ensure_directories() None[source]

Ensure all required storage directories exist.

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, grace_seconds: float | None = None) 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. Files modified within grace_seconds (default _ORPHAN_GRACE_SECONDS) are excluded so a concurrent in-progress sync’s not-yet-committed blobs are not mistaken for orphans.

Parameters:
  • session – Database session

  • grace_seconds – Skip files newer than this many seconds.

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”)

get_pool_statistics(session: Session) dict[str, Any][source]

Get storage pool statistics.

Parameters:

session – Database session

Returns:

Dictionary with statistics

Hardlink source_path to target_path, copying across filesystems.

Publishing uses hardlinks (zero-copy) into the published tree, but the pool and the published tree are often on different filesystems, where os.link raises EXDEV. Fall back to a copy in that case.

package_exists(sha256: str, filename: str) bool[source]

Check if package already exists in pool.

Parameters:
  • sha256 – SHA256 hash

  • filename – Original filename

Returns:

True if package exists in pool

Database Models

class chantal.db.models.Base(**kwargs: Any)[source]

Bases: DeclarativeBase

Base class for all database models.

metadata: ClassVar[MetaData] = MetaData()

Refers to the _schema.MetaData collection that will be used for new _schema.Table objects.

See also

orm_declarative_metadata

registry: ClassVar[registry] = <sqlalchemy.orm.decl_api.registry object>

Refers to the _orm.registry in use where new _orm.Mapper objects will be associated.

class chantal.db.models.ContentItem(**kwargs)[source]

Bases: Base

Generic 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 arch: str | None

Get architecture from content metadata (RPM/DEB-specific).

content_metadata: Mapped[dict]
content_type: Mapped[str]
created_at: Mapped[datetime]
property epoch: str | None

Get epoch from content metadata (RPM-specific).

filename: Mapped[str]
id: Mapped[int]
name: Mapped[str]
property nevra: str | None

Version-Release.Arch).

Returns None for non-RPM content types.

Type:

Get NEVRA string for RPM packages (Name-Epoch

pool_path: Mapped[str]
reference_count: Mapped[int]
property release: str | None

Get release from content metadata (RPM-specific).

repositories: Mapped[list[Repository]]
sha256: Mapped[str]
size_bytes: Mapped[int]
snapshots: Mapped[list[Snapshot]]
version: Mapped[str]
class chantal.db.models.Repository(**kwargs)[source]

Bases: Base

Repository model - represents a configured RPM/APT repository.

content_items: Mapped[list[ContentItem]]
created_at: Mapped[datetime]
enabled: Mapped[bool]
feed: Mapped[str]
id: Mapped[int]
last_sync_at: Mapped[datetime | None]
last_sync_status: Mapped[str | None]
latest_path: Mapped[str | None]
mode: Mapped[str]
name: Mapped[str]
repo_id: Mapped[str]
repository_files: Mapped[list[RepositoryFile]]
snapshots: Mapped[list[Snapshot]]
snapshots_path: Mapped[str | None]
sync_history: Mapped[list[SyncHistory]]
type: Mapped[str]
updated_at: Mapped[datetime]
class chantal.db.models.RepositoryFile(**kwargs)[source]

Bases: Base

Repository 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.

created_at: Mapped[datetime]
file_category: Mapped[str]
file_metadata: Mapped[dict | None]
file_type: Mapped[str]
id: Mapped[int]
original_path: Mapped[str]
pool_path: Mapped[str]
repositories: Mapped[list[Repository]]
sha256: Mapped[str]
size_bytes: Mapped[int]
snapshots: Mapped[list[Snapshot]]
updated_at: Mapped[datetime]
class chantal.db.models.RepositoryMode(*values)[source]

Bases: StrEnum

Repository operation modes.

  • MIRROR: Full mirror, no filtering, metadata unchanged

  • FILTERED: Filtered packages with customized metadata (include/exclude, retention, etc.)

  • HOSTED: Upload-only repository with no upstream feed; packages are added with chantal package upload and sync is a no-op

FILTERED = 'filtered'
HOSTED = 'hosted'
MIRROR = 'mirror'
class chantal.db.models.Snapshot(**kwargs)[source]

Bases: Base

Snapshot 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]]
created_at: Mapped[datetime]
description: Mapped[str | None]
id: Mapped[int]
is_published: Mapped[bool]
name: Mapped[str]
package_count: Mapped[int]
published_path: Mapped[str | None]
repository: Mapped[Repository]
repository_files: Mapped[list[RepositoryFile]]
repository_id: Mapped[int]
total_size_bytes: Mapped[int]
class chantal.db.models.SyncHistory(**kwargs)[source]

Bases: Base

Sync history model - tracks repository synchronization events.

bytes_downloaded: Mapped[int]
completed_at: Mapped[datetime | None]
property duration_seconds: float | None

Calculate sync duration in seconds.

error_message: Mapped[str | None]
id: Mapped[int]
packages_added: Mapped[int]
packages_removed: Mapped[int]
packages_updated: Mapped[int]
repository: Mapped[Repository]
repository_id: Mapped[int]
snapshot: Mapped[Snapshot | None]
snapshot_id: Mapped[int | None]
started_at: Mapped[datetime]
status: Mapped[str]
class chantal.db.models.View(**kwargs)[source]

Bases: Base

View 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).

created_at: Mapped[datetime]
description: Mapped[str | None]
id: Mapped[int]
is_published: Mapped[bool]
name: Mapped[str]
published_at: Mapped[datetime | None]
published_path: Mapped[str | None]
repo_type: Mapped[str]
updated_at: Mapped[datetime]
view_repositories: Mapped[list[ViewRepository]]
view_snapshots: Mapped[list[ViewSnapshot]]
class chantal.db.models.ViewRepository(**kwargs)[source]

Bases: Base

Junction table: View -> Repositories (with ordering).

Defines which repositories are part of a view and their precedence order.

added_at: Mapped[datetime]
id: Mapped[int]
order: Mapped[int]
repository: Mapped[Repository]
repository_id: Mapped[int]
view: Mapped[View]
view_id: Mapped[int]
class chantal.db.models.ViewSnapshot(**kwargs)[source]

Bases: Base

View 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.

created_at: Mapped[datetime]
description: Mapped[str | None]
id: Mapped[int]
is_published: Mapped[bool]
name: Mapped[str]
package_count: Mapped[int]
published_at: Mapped[datetime | None]
published_path: Mapped[str | None]
snapshot_ids: Mapped[list[int]]
total_size_bytes: Mapped[int]
view: Mapped[View]
view_id: Mapped[int]

Plugins

Base Plugins

View Publisher

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 syncing

  • chantal.plugins.rpm.publisher - RPM metadata generation

  • chantal.plugins.rpm.models - RPM metadata models

  • chantal.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 syncing

  • chantal.plugins.apt.publisher - Debian metadata generation

  • chantal.plugins.apt.models - Debian package models

  • chantal.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 syncing

  • chantal.plugins.helm.publisher - index.yaml generation

  • chantal.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 syncing

  • chantal.plugins.apk.publisher - APKINDEX generation

  • chantal.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 registration

  • chantal.cli.repo_commands - Repository management

  • chantal.cli.snapshot_commands - Snapshot management

  • chantal.cli.publish_commands - Publishing

  • chantal.cli.view_commands - View management

  • chantal.cli.content_commands - Content search

  • chantal.cli.db_commands - Database management

  • chantal.cli.pool_commands - Storage pool management