Skip to main content

Acquisition, normalization, versioning, and persistence for Riftbound data.

Project description

riftbound-database

riftbound-database est la librairie d'acquisition, de normalisation, d'historisation et de persistance des données Riftbound.

Le projet suit cette direction de dépendances :

riftbound-core
    ↑ utilisé par
riftbound-database
    ↓ utilise
baobab-database

Le modèle métier canonique appartient à riftbound-core. Ce dépôt ne doit pas redéfinir les cartes, sets, domaines, types, tags, coûts ou textes de carte. L'accès aux moteurs, sessions et transactions SQLAlchemy sera encapsulé derrière un adaptateur local de baobab-database.

Prérequis

  • Python 3.12 ou 3.13 ;
  • PostgreSQL pour l'intégration, SQLite étant réservé aux tests rapides.

Installation de développement

python -m venv .venv
python -m pip install --upgrade pip
python -m pip install -e ".[dev]"

La dépendance riftbound-core est résolue depuis PyPI (>=0.1.1,<0.2).

Configuration

Variable Obligatoire Valeur par défaut Rôle
RIFTBOUND_DATABASE_URL Non au bootstrap aucune URL de connexion ; obligatoire pour les futures opérations de base
RIFTBOUND_STORAGE_PATH Non storage Racine du stockage local
RIFTBOUND_LOG_LEVEL Non INFO Niveau de logs Python
RIFTBOUND_ENVIRONMENT Non development Nom de l'environnement d'exécution

Les secrets éventuellement présents dans RIFTBOUND_DATABASE_URL ne doivent jamais être écrits dans les logs. Les fichiers .env sont ignorés par Git.

Provider de base de données

Les moteurs, sessions et transactions passent exclusivement par riftbound_database.database.BaobabProvider. PostgreSQL utilise baobab-database 2.0.0 avec le driver psycopg; SQLite est limité aux tests sur fichier temporaire.

L'adaptation complète et les options SSL supportées sont documentées dans docs/database-provider.md.

Modèles et migrations

Les modèles SQLAlchemy vivent sous riftbound_database.database.models. Les mappers domaine ↔ persistance sont sous database/mappers. Alembic est configuré via alembic.ini et exécutable avec :

python -m alembic upgrade head

Pour les tests locaux sans PostgreSQL, définir RIFTBOUND_MIGRATION_SQLITE_PATH ou laisser Alembic utiliser la base SQLite par défaut sous .my_cache/.

Repositories

Les écritures applicatives passent par RiftboundUnitOfWork, qui expose les repositories sans créer de session locale. Les retours sont limités aux objets riftbound-core ou aux read models sous database/read_models/.

from riftbound_database.database.baobab_provider import BaobabProvider
from riftbound_database.database.unit_of_work import RiftboundUnitOfWork

provider = BaobabProvider.for_sqlite("test.db")
unit_of_work = RiftboundUnitOfWork(provider)
with unit_of_work.transaction() as repositories:
    card = repositories.cards.find_by_stable_id("card-001")

Ingestion

Les imports passent par BaseImporter, qui orchestre fetch, stockage raw, checksum, batch et persistance via les repositories. SetImporter importe des fichiers JSON locaux de façon idempotente avec normalisation, checksum canonique et stockage sous normalized_data/sets/. CardNormalizer produit des DTO canoniques compatibles avec riftbound-core, calcule un checksum stable et signale les champs ambigus via le statut needs_review. Les importers cartes (LocalFileCardImporter, OfficialApiCardImporter, CardGalleryImporter) normalisent, versionnent et persistent les cartes via les repositories. Les documents normatifs passent par RulesImporter, ErrataImporter et BanlistImporter avec normalisation, checksums stables, historisation (rules_versions, snapshots banlist) et statuts matched / ambiguous / needs_review. Un FakeImporter est disponible pour les tests.

Assets

Les images de cartes sont téléchargées par CardAssetDownloader, validées (MIME, taille minimale, signature binaire) puis stockées sous {RIFTBOUND_STORAGE_PATH}/card_assets/{set_code}/{card_id}/ avec un metadata.json par carte. La persistance relationnelle passe par AssetRepository ; un checksum inchangé évite les écritures inutiles.

from riftbound_database.assets import AssetDownloadRequest, AssetVariant, CardAssetDownloader
from riftbound_database.config.settings import Settings
from riftbound_database.database.baobab_provider import BaobabProvider
from riftbound_database.database.unit_of_work import RiftboundUnitOfWork

settings = Settings()
downloader = CardAssetDownloader()
provider = BaobabProvider.for_sqlite("test.db")
unit_of_work = RiftboundUnitOfWork(provider)
request = AssetDownloadRequest(
    set_code="OGN",
    card_id="card-unit-001",
    variant=AssetVariant.ORIGINAL,
    source_url="https://example.test/card.png",
)
with unit_of_work.transaction() as repositories:
    result = downloader.download(request, settings, repositories.assets)

Synchronisation

Les jobs sous riftbound_database.sync orchestrent les importers via un SyncManifest JSON (ADR-0002) : chemins locaux + liste assets[] avec URLs source explicites. FullSyncJob exécute dans l'ordre sets → cartes → assets → règles → errata → banlists, avec dry_run et SyncReport final.

from riftbound_database.sync import FullSyncJob, SyncContext, SyncManifestLoader

manifest = SyncManifestLoader.load(Path("sync.json"))
context = SyncContext(settings=settings, unit_of_work=unit_of_work, manifest=manifest)
report = FullSyncJob().run(context)

CLI

La CLI Typer est exposée via le script riftbound-database (ou python -m riftbound_database.cli.main). Options globales : --database-url, --sqlite-path, --storage-path, --log-level.

riftbound-database --sqlite-path ./local.db db upgrade
riftbound-database --sqlite-path ./local.db import sets --path ./sets.json
riftbound-database --sqlite-path ./local.db import cards --source local-file --path ./cards.json
riftbound-database --sqlite-path ./local.db import rules --path ./rules.json
riftbound-database --sqlite-path ./local.db import errata --path ./errata.json
riftbound-database --sqlite-path ./local.db import banlist --path ./banlist.json
riftbound-database --sqlite-path ./local.db assets download --manifest ./sync.json
riftbound-database --sqlite-path ./local.db sync full --manifest ./sync.json
riftbound-database checksums verify
riftbound-database export normalized --format json

Les imports supportent --dry-run et --limit. Les commandes retournent un code de sortie non nul en cas d'échec ; les secrets de connexion ne sont jamais loggés.

Qualité

python -m pytest
python -m coverage run -m pytest
python -m coverage report
python -m ruff check .
python -m mypy src tests
python -m bandit -r src

Tests rapides vs intégration

# unitaires (CI par défaut)
python -m pytest -m "not integration and not postgresql"

# migrations SQLite
python -m pytest tests/integration/riftbound_database/database/migrations/

# PostgreSQL (service local requis)
set RIFTBOUND_TEST_POSTGRESQL_URL=postgresql+psycopg://user:pass@localhost:5432/riftbound_test
python -m pytest -m postgresql

Couverture minimale configurée : 85 % (pyproject.toml).

CI GitHub Actions

Le workflow .github/workflows/ci.yml exécute sur chaque push/PR vers main :

  • quality : ruff, mypy, bandit ;
  • unit : pytest + coverage (Python 3.12 et 3.13) ;
  • integration : migrations SQLite + test PostgreSQL via service container.

Les dépendances (riftbound-core, baobab-database) sont installées depuis PyPI ; aucun secret GitHub n'est requis pour la CI si tous les packages restent publics.

Documentation projet

Le cahier des charges et le découpage fonctionnel sont disponibles dans docs/. Le développement suit l'ordre séquentiel des backlogs BL-001 à BL-014.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

riftbound_database-0.1.1.tar.gz (160.9 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

riftbound_database-0.1.1-py3-none-any.whl (138.7 kB view details)

Uploaded Python 3

File details

Details for the file riftbound_database-0.1.1.tar.gz.

File metadata

  • Download URL: riftbound_database-0.1.1.tar.gz
  • Upload date:
  • Size: 160.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for riftbound_database-0.1.1.tar.gz
Algorithm Hash digest
SHA256 c62db2ebcec660164594f6617cb941d9edf0da38076af282cafc99db8024d6a2
MD5 bcbabc743a7881b7e450df6351275312
BLAKE2b-256 39536a58f0cbaff5265154759858edba936774b8c5cf397c5b55e1bdeee18b8c

See more details on using hashes here.

Provenance

The following attestation bundles were made for riftbound_database-0.1.1.tar.gz:

Publisher: release.yml on baobabgit/riftbound-database

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file riftbound_database-0.1.1-py3-none-any.whl.

File metadata

File hashes

Hashes for riftbound_database-0.1.1-py3-none-any.whl
Algorithm Hash digest
SHA256 34199830672dfd15209e26289d20dc7a1287d132165c03312dca378c86a629d3
MD5 1f033ec6cc8f519b93e87fea946c22ef
BLAKE2b-256 4e7c177007d2aa099a1ec4cb809ce320325db5eef962aaa9eac805e5f0020553

See more details on using hashes here.

Provenance

The following attestation bundles were made for riftbound_database-0.1.1-py3-none-any.whl:

Publisher: release.yml on baobabgit/riftbound-database

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page