mtg-carddb 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- mtg_carddb-0.1.0/.github/workflows/ci.yml +94 -0
- mtg_carddb-0.1.0/.github/workflows/publish.yml +112 -0
- mtg_carddb-0.1.0/.gitignore +220 -0
- mtg_carddb-0.1.0/CHANGELOG.md +33 -0
- mtg_carddb-0.1.0/CONTRIBUTING.md +72 -0
- mtg_carddb-0.1.0/LICENSE +21 -0
- mtg_carddb-0.1.0/PKG-INFO +408 -0
- mtg_carddb-0.1.0/README.md +392 -0
- mtg_carddb-0.1.0/docs/api.md +469 -0
- mtg_carddb-0.1.0/docs/releasing.md +195 -0
- mtg_carddb-0.1.0/docs/schema.md +365 -0
- mtg_carddb-0.1.0/pyproject.toml +35 -0
- mtg_carddb-0.1.0/scripts/audit_drilldown.py +214 -0
- mtg_carddb-0.1.0/scripts/audit_real_data.py +504 -0
- mtg_carddb-0.1.0/scripts/audit_remaining_types.py +153 -0
- mtg_carddb-0.1.0/scripts/audit_staging.py +412 -0
- mtg_carddb-0.1.0/scripts/export_failed_printings.py +50 -0
- mtg_carddb-0.1.0/src/mtg_carddb/__init__.py +84 -0
- mtg_carddb-0.1.0/src/mtg_carddb/__main__.py +7 -0
- mtg_carddb-0.1.0/src/mtg_carddb/acquisition.py +330 -0
- mtg_carddb-0.1.0/src/mtg_carddb/activation.py +363 -0
- mtg_carddb-0.1.0/src/mtg_carddb/builder.py +275 -0
- mtg_carddb-0.1.0/src/mtg_carddb/bulk.py +115 -0
- mtg_carddb-0.1.0/src/mtg_carddb/catalogs.py +515 -0
- mtg_carddb-0.1.0/src/mtg_carddb/cli.py +426 -0
- mtg_carddb-0.1.0/src/mtg_carddb/database.py +636 -0
- mtg_carddb-0.1.0/src/mtg_carddb/freshness.py +199 -0
- mtg_carddb-0.1.0/src/mtg_carddb/import_policy.py +100 -0
- mtg_carddb-0.1.0/src/mtg_carddb/indexes.py +138 -0
- mtg_carddb-0.1.0/src/mtg_carddb/ingestion.py +221 -0
- mtg_carddb-0.1.0/src/mtg_carddb/jsonl_limits.py +73 -0
- mtg_carddb-0.1.0/src/mtg_carddb/lockfiles.py +229 -0
- mtg_carddb-0.1.0/src/mtg_carddb/models.py +373 -0
- mtg_carddb-0.1.0/src/mtg_carddb/network.py +115 -0
- mtg_carddb-0.1.0/src/mtg_carddb/normalization.py +702 -0
- mtg_carddb-0.1.0/src/mtg_carddb/oracle_tags.py +362 -0
- mtg_carddb-0.1.0/src/mtg_carddb/persistence.py +90 -0
- mtg_carddb-0.1.0/src/mtg_carddb/printed_types.py +182 -0
- mtg_carddb-0.1.0/src/mtg_carddb/provenance.py +192 -0
- mtg_carddb-0.1.0/src/mtg_carddb/reference_integration.py +84 -0
- mtg_carddb-0.1.0/src/mtg_carddb/reference_sources.py +575 -0
- mtg_carddb-0.1.0/src/mtg_carddb/representatives.py +273 -0
- mtg_carddb-0.1.0/src/mtg_carddb/schema.py +232 -0
- mtg_carddb-0.1.0/src/mtg_carddb/storage.py +373 -0
- mtg_carddb-0.1.0/src/mtg_carddb/workflow.py +294 -0
- mtg_carddb-0.1.0/tests/test_acquisition.py +523 -0
- mtg_carddb-0.1.0/tests/test_activation.py +522 -0
- mtg_carddb-0.1.0/tests/test_audit_staging.py +164 -0
- mtg_carddb-0.1.0/tests/test_builder.py +371 -0
- mtg_carddb-0.1.0/tests/test_bulk.py +177 -0
- mtg_carddb-0.1.0/tests/test_catalogs.py +508 -0
- mtg_carddb-0.1.0/tests/test_cli.py +544 -0
- mtg_carddb-0.1.0/tests/test_database.py +452 -0
- mtg_carddb-0.1.0/tests/test_freshness.py +262 -0
- mtg_carddb-0.1.0/tests/test_import_policy.py +79 -0
- mtg_carddb-0.1.0/tests/test_indexes.py +184 -0
- mtg_carddb-0.1.0/tests/test_ingestion.py +332 -0
- mtg_carddb-0.1.0/tests/test_jsonl_limits.py +104 -0
- mtg_carddb-0.1.0/tests/test_lockfiles.py +179 -0
- mtg_carddb-0.1.0/tests/test_models.py +301 -0
- mtg_carddb-0.1.0/tests/test_network.py +211 -0
- mtg_carddb-0.1.0/tests/test_normalization.py +583 -0
- mtg_carddb-0.1.0/tests/test_oracle_tags.py +278 -0
- mtg_carddb-0.1.0/tests/test_persistence.py +55 -0
- mtg_carddb-0.1.0/tests/test_printed_types.py +131 -0
- mtg_carddb-0.1.0/tests/test_provenance.py +166 -0
- mtg_carddb-0.1.0/tests/test_public_api.py +148 -0
- mtg_carddb-0.1.0/tests/test_reference_integration.py +189 -0
- mtg_carddb-0.1.0/tests/test_reference_sources.py +390 -0
- mtg_carddb-0.1.0/tests/test_representatives.py +518 -0
- mtg_carddb-0.1.0/tests/test_schema.py +113 -0
- mtg_carddb-0.1.0/tests/test_storage.py +227 -0
- mtg_carddb-0.1.0/tests/test_workflow.py +573 -0
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
pull_request:
|
|
6
|
+
workflow_dispatch:
|
|
7
|
+
|
|
8
|
+
permissions:
|
|
9
|
+
contents: read
|
|
10
|
+
|
|
11
|
+
jobs:
|
|
12
|
+
tests:
|
|
13
|
+
name: Tests (${{ matrix.os }}, Python ${{ matrix.python }})
|
|
14
|
+
runs-on: ${{ matrix.os }}
|
|
15
|
+
timeout-minutes: 20
|
|
16
|
+
|
|
17
|
+
strategy:
|
|
18
|
+
fail-fast: false
|
|
19
|
+
matrix:
|
|
20
|
+
os: [ubuntu-latest, windows-latest, macos-latest]
|
|
21
|
+
python: ["3.11", "3.12", "3.13"]
|
|
22
|
+
|
|
23
|
+
steps:
|
|
24
|
+
- uses: actions/checkout@v7
|
|
25
|
+
with:
|
|
26
|
+
persist-credentials: false
|
|
27
|
+
|
|
28
|
+
- uses: actions/setup-python@v7
|
|
29
|
+
with:
|
|
30
|
+
python-version: ${{ matrix.python }}
|
|
31
|
+
|
|
32
|
+
- name: Install package and development tools
|
|
33
|
+
run: python -m pip install -e ".[dev]"
|
|
34
|
+
|
|
35
|
+
- name: Run tests with network access blocked
|
|
36
|
+
run: python -m pytest -q --disable-socket
|
|
37
|
+
|
|
38
|
+
distributions:
|
|
39
|
+
name: Build and test distributions
|
|
40
|
+
runs-on: ubuntu-latest
|
|
41
|
+
timeout-minutes: 20
|
|
42
|
+
|
|
43
|
+
steps:
|
|
44
|
+
- uses: actions/checkout@v7
|
|
45
|
+
with:
|
|
46
|
+
persist-credentials: false
|
|
47
|
+
|
|
48
|
+
- uses: actions/setup-python@v7
|
|
49
|
+
with:
|
|
50
|
+
python-version: "3.11"
|
|
51
|
+
|
|
52
|
+
- name: Install build tools
|
|
53
|
+
run: python -m pip install "build>=1.2" "twine>=6"
|
|
54
|
+
|
|
55
|
+
- name: Build wheel and source distribution
|
|
56
|
+
run: python -m build
|
|
57
|
+
|
|
58
|
+
- name: Validate distribution metadata
|
|
59
|
+
run: python -m twine check --strict dist/*
|
|
60
|
+
|
|
61
|
+
- name: Smoke-test wheel in isolated environment
|
|
62
|
+
shell: bash
|
|
63
|
+
run: |
|
|
64
|
+
python -m venv "$RUNNER_TEMP/carddb-wheel"
|
|
65
|
+
"$RUNNER_TEMP/carddb-wheel/bin/python" -m pip install --no-index --no-deps dist/*.whl
|
|
66
|
+
|
|
67
|
+
cd "$RUNNER_TEMP"
|
|
68
|
+
|
|
69
|
+
"$RUNNER_TEMP/carddb-wheel/bin/python" -I -c 'from pathlib import Path; import mtg_carddb as m; assert "site-packages" in str(Path(m.__file__).resolve()); assert callable(m.initialize_database); print(m.__file__)'
|
|
70
|
+
|
|
71
|
+
"$RUNNER_TEMP/carddb-wheel/bin/python" -m mtg_carddb --help
|
|
72
|
+
"$RUNNER_TEMP/carddb-wheel/bin/mtg-carddb" --help
|
|
73
|
+
"$RUNNER_TEMP/carddb-wheel/bin/mtg-carddb" locks --database "$RUNNER_TEMP/nonexistent-carddb.sqlite"
|
|
74
|
+
|
|
75
|
+
- name: Smoke-test sdist in isolated environment
|
|
76
|
+
shell: bash
|
|
77
|
+
run: |
|
|
78
|
+
python -m venv "$RUNNER_TEMP/carddb-sdist"
|
|
79
|
+
"$RUNNER_TEMP/carddb-sdist/bin/python" -m pip install --no-deps dist/*.tar.gz
|
|
80
|
+
|
|
81
|
+
cd "$RUNNER_TEMP"
|
|
82
|
+
|
|
83
|
+
"$RUNNER_TEMP/carddb-sdist/bin/python" -I -c 'from pathlib import Path; import mtg_carddb as m; assert "site-packages" in str(Path(m.__file__).resolve()); assert callable(m.update_database); print(m.__file__)'
|
|
84
|
+
|
|
85
|
+
"$RUNNER_TEMP/carddb-sdist/bin/python" -m mtg_carddb --help
|
|
86
|
+
"$RUNNER_TEMP/carddb-sdist/bin/mtg-carddb" --help
|
|
87
|
+
|
|
88
|
+
- name: Preserve validated distributions
|
|
89
|
+
uses: actions/upload-artifact@v7
|
|
90
|
+
with:
|
|
91
|
+
name: mtg-carddb-distributions
|
|
92
|
+
path: dist/*
|
|
93
|
+
if-no-files-found: error
|
|
94
|
+
retention-days: 7
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
# Publishing runs only when the maintainer manually starts this workflow.
|
|
2
|
+
name: Publish to PyPI
|
|
3
|
+
|
|
4
|
+
on:
|
|
5
|
+
workflow_dispatch:
|
|
6
|
+
inputs:
|
|
7
|
+
tag:
|
|
8
|
+
description: "Existing release tag to publish (for example, v0.1.0)"
|
|
9
|
+
required: true
|
|
10
|
+
type: string
|
|
11
|
+
|
|
12
|
+
permissions:
|
|
13
|
+
contents: read
|
|
14
|
+
|
|
15
|
+
concurrency:
|
|
16
|
+
group: pypi-${{ inputs.tag }}
|
|
17
|
+
cancel-in-progress: false
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
build:
|
|
21
|
+
name: Verify and build tagged release
|
|
22
|
+
runs-on: ubuntu-latest
|
|
23
|
+
timeout-minutes: 20
|
|
24
|
+
steps:
|
|
25
|
+
- name: Validate tag input
|
|
26
|
+
shell: bash
|
|
27
|
+
env:
|
|
28
|
+
RELEASE_TAG: ${{ inputs.tag }}
|
|
29
|
+
run: |
|
|
30
|
+
set -euo pipefail
|
|
31
|
+
if [[ ! "$RELEASE_TAG" =~ ^v[0-9]+\.[0-9]+\.[0-9]+$ ]]; then
|
|
32
|
+
echo "Expected a version tag like v0.1.0" >&2
|
|
33
|
+
exit 1
|
|
34
|
+
fi
|
|
35
|
+
|
|
36
|
+
- name: Check out the requested tag
|
|
37
|
+
uses: actions/checkout@v7
|
|
38
|
+
with:
|
|
39
|
+
ref: refs/tags/${{ inputs.tag }}
|
|
40
|
+
persist-credentials: false
|
|
41
|
+
|
|
42
|
+
- name: Set up Python
|
|
43
|
+
uses: actions/setup-python@v7
|
|
44
|
+
with:
|
|
45
|
+
python-version: "3.11"
|
|
46
|
+
|
|
47
|
+
- name: Confirm tag matches package version
|
|
48
|
+
env:
|
|
49
|
+
RELEASE_TAG: ${{ inputs.tag }}
|
|
50
|
+
run: |
|
|
51
|
+
python - <<'PY'
|
|
52
|
+
import os
|
|
53
|
+
from pathlib import Path
|
|
54
|
+
import tomllib
|
|
55
|
+
|
|
56
|
+
project = tomllib.loads(Path("pyproject.toml").read_text(encoding="utf-8"))["project"]
|
|
57
|
+
actual = os.environ["RELEASE_TAG"]
|
|
58
|
+
expected = f"v{project['version']}"
|
|
59
|
+
if actual != expected:
|
|
60
|
+
raise SystemExit(f"Tag {actual!r} does not match package version {expected!r}")
|
|
61
|
+
if project["name"] != "mtg-carddb":
|
|
62
|
+
raise SystemExit("Unexpected distribution name")
|
|
63
|
+
PY
|
|
64
|
+
|
|
65
|
+
- name: Install development dependencies
|
|
66
|
+
run: python -m pip install -e ".[dev]"
|
|
67
|
+
|
|
68
|
+
- name: Run offline tests
|
|
69
|
+
run: python -m pytest -q --disable-socket
|
|
70
|
+
|
|
71
|
+
- name: Build wheel and source distribution
|
|
72
|
+
run: python -m build
|
|
73
|
+
|
|
74
|
+
- name: Check distribution metadata and count
|
|
75
|
+
shell: bash
|
|
76
|
+
run: |
|
|
77
|
+
python -m twine check --strict dist/*
|
|
78
|
+
python - <<'PY'
|
|
79
|
+
from pathlib import Path
|
|
80
|
+
files = list(Path("dist").iterdir())
|
|
81
|
+
wheels = [p for p in files if p.suffix == ".whl"]
|
|
82
|
+
sdists = [p for p in files if p.name.endswith(".tar.gz")]
|
|
83
|
+
if len(files) != 2 or len(wheels) != 1 or len(sdists) != 1:
|
|
84
|
+
raise SystemExit(f"Expected one wheel and one sdist; found: {[p.name for p in files]}")
|
|
85
|
+
PY
|
|
86
|
+
|
|
87
|
+
- name: Save validated distributions
|
|
88
|
+
uses: actions/upload-artifact@v7
|
|
89
|
+
with:
|
|
90
|
+
name: mtg-carddb-release-dists
|
|
91
|
+
path: dist/
|
|
92
|
+
if-no-files-found: error
|
|
93
|
+
retention-days: 7
|
|
94
|
+
|
|
95
|
+
publish:
|
|
96
|
+
name: Publish validated distributions
|
|
97
|
+
needs: build
|
|
98
|
+
runs-on: ubuntu-latest
|
|
99
|
+
environment:
|
|
100
|
+
name: pypi
|
|
101
|
+
url: https://pypi.org/project/mtg-carddb/
|
|
102
|
+
permissions:
|
|
103
|
+
id-token: write
|
|
104
|
+
steps:
|
|
105
|
+
- name: Download validated distributions
|
|
106
|
+
uses: actions/download-artifact@v7
|
|
107
|
+
with:
|
|
108
|
+
name: mtg-carddb-release-dists
|
|
109
|
+
path: dist/
|
|
110
|
+
|
|
111
|
+
- name: Publish to PyPI using Trusted Publishing
|
|
112
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[codz]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# C extensions
|
|
7
|
+
*.so
|
|
8
|
+
|
|
9
|
+
# Distribution / packaging
|
|
10
|
+
.Python
|
|
11
|
+
build/
|
|
12
|
+
develop-eggs/
|
|
13
|
+
dist/
|
|
14
|
+
downloads/
|
|
15
|
+
eggs/
|
|
16
|
+
.eggs/
|
|
17
|
+
lib/
|
|
18
|
+
lib64/
|
|
19
|
+
parts/
|
|
20
|
+
sdist/
|
|
21
|
+
var/
|
|
22
|
+
wheels/
|
|
23
|
+
share/python-wheels/
|
|
24
|
+
*.egg-info/
|
|
25
|
+
.installed.cfg
|
|
26
|
+
*.egg
|
|
27
|
+
MANIFEST
|
|
28
|
+
|
|
29
|
+
# PyInstaller
|
|
30
|
+
# Usually these files are written by a python script from a template
|
|
31
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
32
|
+
*.manifest
|
|
33
|
+
*.spec
|
|
34
|
+
|
|
35
|
+
# Installer logs
|
|
36
|
+
pip-log.txt
|
|
37
|
+
pip-delete-this-directory.txt
|
|
38
|
+
|
|
39
|
+
# Unit test / coverage reports
|
|
40
|
+
htmlcov/
|
|
41
|
+
.tox/
|
|
42
|
+
.nox/
|
|
43
|
+
.coverage
|
|
44
|
+
.coverage.*
|
|
45
|
+
.cache
|
|
46
|
+
nosetests.xml
|
|
47
|
+
coverage.xml
|
|
48
|
+
*.cover
|
|
49
|
+
*.py.cover
|
|
50
|
+
*.lcov
|
|
51
|
+
.hypothesis/
|
|
52
|
+
.pytest_cache/
|
|
53
|
+
cover/
|
|
54
|
+
|
|
55
|
+
# Translations
|
|
56
|
+
*.mo
|
|
57
|
+
*.pot
|
|
58
|
+
|
|
59
|
+
# Django stuff:
|
|
60
|
+
*.log
|
|
61
|
+
local_settings.py
|
|
62
|
+
db.sqlite3
|
|
63
|
+
db.sqlite3-journal
|
|
64
|
+
|
|
65
|
+
# Flask stuff:
|
|
66
|
+
instance/
|
|
67
|
+
.webassets-cache
|
|
68
|
+
|
|
69
|
+
# Scrapy stuff:
|
|
70
|
+
.scrapy
|
|
71
|
+
|
|
72
|
+
# Sphinx documentation
|
|
73
|
+
docs/_build/
|
|
74
|
+
|
|
75
|
+
# PyBuilder
|
|
76
|
+
.pybuilder/
|
|
77
|
+
target/
|
|
78
|
+
|
|
79
|
+
# Jupyter Notebook
|
|
80
|
+
.ipynb_checkpoints
|
|
81
|
+
|
|
82
|
+
# IPython
|
|
83
|
+
profile_default/
|
|
84
|
+
ipython_config.py
|
|
85
|
+
|
|
86
|
+
# pyenv
|
|
87
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
88
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
89
|
+
# .python-version
|
|
90
|
+
|
|
91
|
+
# pipenv
|
|
92
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
93
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
94
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
95
|
+
# install all needed dependencies.
|
|
96
|
+
# Pipfile.lock
|
|
97
|
+
|
|
98
|
+
# uv
|
|
99
|
+
# Similar to Pipfile.lock, it is generally recommended to include uv.lock in version control.
|
|
100
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
101
|
+
# commonly ignored for libraries.
|
|
102
|
+
# uv.lock
|
|
103
|
+
|
|
104
|
+
# poetry
|
|
105
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
106
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
107
|
+
# commonly ignored for libraries.
|
|
108
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
109
|
+
# poetry.lock
|
|
110
|
+
# poetry.toml
|
|
111
|
+
|
|
112
|
+
# pdm
|
|
113
|
+
# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
|
|
114
|
+
# pdm recommends including project-wide configuration in pdm.toml, but excluding .pdm-python.
|
|
115
|
+
# https://pdm-project.org/en/latest/usage/project/#working-with-version-control
|
|
116
|
+
# pdm.lock
|
|
117
|
+
# pdm.toml
|
|
118
|
+
.pdm-python
|
|
119
|
+
.pdm-build/
|
|
120
|
+
|
|
121
|
+
# pixi
|
|
122
|
+
# Similar to Pipfile.lock, it is generally recommended to include pixi.lock in version control.
|
|
123
|
+
# pixi.lock
|
|
124
|
+
# Pixi creates a virtual environment in the .pixi directory, just like venv module creates one
|
|
125
|
+
# in the .venv directory. It is recommended not to include this directory in version control.
|
|
126
|
+
.pixi/*
|
|
127
|
+
!.pixi/config.toml
|
|
128
|
+
|
|
129
|
+
# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
|
|
130
|
+
__pypackages__/
|
|
131
|
+
|
|
132
|
+
# Celery stuff
|
|
133
|
+
celerybeat-schedule*
|
|
134
|
+
celerybeat.pid
|
|
135
|
+
|
|
136
|
+
# Redis
|
|
137
|
+
*.rdb
|
|
138
|
+
*.aof
|
|
139
|
+
*.pid
|
|
140
|
+
|
|
141
|
+
# RabbitMQ
|
|
142
|
+
mnesia/
|
|
143
|
+
rabbitmq/
|
|
144
|
+
rabbitmq-data/
|
|
145
|
+
|
|
146
|
+
# ActiveMQ
|
|
147
|
+
activemq-data/
|
|
148
|
+
|
|
149
|
+
# SageMath parsed files
|
|
150
|
+
*.sage.py
|
|
151
|
+
|
|
152
|
+
# Environments
|
|
153
|
+
.env
|
|
154
|
+
.envrc
|
|
155
|
+
.venv
|
|
156
|
+
env/
|
|
157
|
+
venv/
|
|
158
|
+
ENV/
|
|
159
|
+
env.bak/
|
|
160
|
+
venv.bak/
|
|
161
|
+
|
|
162
|
+
# Spyder project settings
|
|
163
|
+
.spyderproject
|
|
164
|
+
.spyproject
|
|
165
|
+
|
|
166
|
+
# Rope project settings
|
|
167
|
+
.ropeproject
|
|
168
|
+
|
|
169
|
+
# mkdocs/Zensical documentation
|
|
170
|
+
/site
|
|
171
|
+
|
|
172
|
+
# mypy
|
|
173
|
+
.mypy_cache/
|
|
174
|
+
.dmypy.json
|
|
175
|
+
dmypy.json
|
|
176
|
+
|
|
177
|
+
# Pyre type checker
|
|
178
|
+
.pyre/
|
|
179
|
+
|
|
180
|
+
# pytype static type analyzer
|
|
181
|
+
.pytype/
|
|
182
|
+
|
|
183
|
+
# Cython debug symbols
|
|
184
|
+
cython_debug/
|
|
185
|
+
|
|
186
|
+
# PyCharm
|
|
187
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
188
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
189
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
190
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
191
|
+
# .idea/
|
|
192
|
+
|
|
193
|
+
# Abstra
|
|
194
|
+
# Abstra is an AI-powered process automation framework.
|
|
195
|
+
# Ignore directories containing user credentials, local state, and settings.
|
|
196
|
+
# Learn more at https://abstra.io/docs
|
|
197
|
+
.abstra/
|
|
198
|
+
|
|
199
|
+
# Visual Studio Code
|
|
200
|
+
# Visual Studio Code specific template is maintained in a separate VisualStudioCode.gitignore that
|
|
201
|
+
# can be found at https://github.com/github/gitignore/blob/main/Global/VisualStudioCode.gitignore
|
|
202
|
+
# and can be added to the global gitignore or merged into this file. However, if you prefer, you
|
|
203
|
+
# could uncomment the following to ignore the entire vscode folder
|
|
204
|
+
# .vscode/
|
|
205
|
+
# Temporary file for partial code execution
|
|
206
|
+
tempCodeRunnerFile.py
|
|
207
|
+
|
|
208
|
+
# Ruff stuff:
|
|
209
|
+
.ruff_cache/
|
|
210
|
+
|
|
211
|
+
# PyPI configuration file
|
|
212
|
+
.pypirc
|
|
213
|
+
|
|
214
|
+
# Marimo
|
|
215
|
+
marimo/_static/
|
|
216
|
+
marimo/_lsp/
|
|
217
|
+
__marimo__/
|
|
218
|
+
|
|
219
|
+
# Streamlit
|
|
220
|
+
.streamlit/secrets.toml
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Notable user-facing changes to MTG CardDB are recorded here.
|
|
4
|
+
|
|
5
|
+
The project follows a `MAJOR.MINOR.PATCH` version scheme. Releases below 1.0.0 may refine the public API, while SQLite schema compatibility is tracked separately using `PRAGMA user_version`.
|
|
6
|
+
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
No changes recorded yet.
|
|
10
|
+
|
|
11
|
+
## 0.1.0 — Initial release candidate
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- Immutable, composable Oracle-ID search API.
|
|
16
|
+
- Read-only SQLite-backed card records and associated metadata.
|
|
17
|
+
- Color identity, color, type, keyword, mana value, produced-mana, legality, Oracle Tag, and historical set/rarity/game queries.
|
|
18
|
+
- Normalization of multiface and reversible-card records.
|
|
19
|
+
- Deterministic Oracle representative and legality selection.
|
|
20
|
+
- Scryfall Default Cards, Oracle Tags, Sets API, and type-catalog acquisition.
|
|
21
|
+
- Verified provenance and source-freshness reporting.
|
|
22
|
+
- Explicit database initialization, update, information, and lock-inspection CLI commands.
|
|
23
|
+
- Progress reporting during database builds.
|
|
24
|
+
- Validated snapshot activation, guarded updates, and lock diagnostics.
|
|
25
|
+
- Network, download-size, and decompression safeguards.
|
|
26
|
+
- Cross-platform CI and clean distribution-installation checks.
|
|
27
|
+
|
|
28
|
+
### Known limitations
|
|
29
|
+
|
|
30
|
+
- No individual printing inventory, price history, or historical Oracle text revisions.
|
|
31
|
+
- No automatically retained source archive for exact offline reconstruction.
|
|
32
|
+
- No guaranteed atomic compare-and-replace against unrelated external filesystem writers.
|
|
33
|
+
- Public Python API remains pre-1.0.
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Contributing to MTG CardDB
|
|
2
|
+
|
|
3
|
+
Contributions, bug reports, regression tests, and documentation corrections are welcome.
|
|
4
|
+
|
|
5
|
+
MTG CardDB is a local-first Python library. Its central guarantees are immutable Oracle-ID query results, deterministic normalization, read-only database access, and explicit, safe database updates.
|
|
6
|
+
|
|
7
|
+
## Development setup
|
|
8
|
+
|
|
9
|
+
Python 3.11 or newer is required.
|
|
10
|
+
|
|
11
|
+
Clone the repository, create a virtual environment if desired, and install the development dependencies:
|
|
12
|
+
|
|
13
|
+
```powershell
|
|
14
|
+
python -m pip install -e ".[dev]"
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
Run the offline test suite:
|
|
18
|
+
|
|
19
|
+
```powershell
|
|
20
|
+
python -m pytest -q --disable-socket
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
The ordinary test suite must not depend on the availability of Scryfall or any other external service. Use temporary files, synthetic fixtures, and mocked HTTP responses when testing network or import behavior.
|
|
24
|
+
|
|
25
|
+
## Before submitting changes
|
|
26
|
+
|
|
27
|
+
- Add regression tests for corrected bugs and new public behavior.
|
|
28
|
+
- Run the complete offline test suite.
|
|
29
|
+
- Keep imports and database queries free of implicit network requests.
|
|
30
|
+
- Check Windows, Linux, and macOS considerations, especially filesystem replacement, locks, path handling, and timestamps.
|
|
31
|
+
- Update documentation when public behavior changes.
|
|
32
|
+
- Do not commit generated SQLite databases, downloaded Scryfall exports, local credentials, virtual environments, or build artifacts.
|
|
33
|
+
|
|
34
|
+
GitHub Actions tests the supported Python versions on all three operating systems and verifies wheel and source-distribution builds.
|
|
35
|
+
|
|
36
|
+
## Public API and schema
|
|
37
|
+
|
|
38
|
+
The public API is documented in [docs/api.md](docs/api.md). Prefer exposing stable library interfaces through `mtg_carddb.__init__`.
|
|
39
|
+
|
|
40
|
+
Queries should continue to return native `frozenset[str]` Oracle-ID memberships. Do not substitute printing IDs, mutable result collections, or custom query objects without an explicit API review.
|
|
41
|
+
|
|
42
|
+
The persisted schema is documented in [docs/schema.md](docs/schema.md).
|
|
43
|
+
|
|
44
|
+
**The SQL block in `docs/schema.md` must match `SCHEMA_SQL` in `src/mtg_carddb/schema.py`.** This is enforced by `tests/test_schema.py`.
|
|
45
|
+
|
|
46
|
+
Do not change the SQL schema silently. A schema change requires coordinated changes to its documentation, builder, reader compatibility checks, tests, and SQLite schema version policy.
|
|
47
|
+
|
|
48
|
+
The current implementation is pre-1.0. API changes should still be deliberate and documented, even though its interface is not yet declared fully stable.
|
|
49
|
+
|
|
50
|
+
## Scryfall import changes
|
|
51
|
+
|
|
52
|
+
The standard workflow consumes Default Cards, Oracle Tags, the Sets API, and type catalogs.
|
|
53
|
+
|
|
54
|
+
Preserve the distinction between known-empty and missing source fields. Keep historical set, rarity, and game observations coupled. Preserve deterministic Oracle representative selection and the separate legality-selection policy.
|
|
55
|
+
|
|
56
|
+
An unsupported required source shape should produce a diagnostic failure, not fabricated values or a partially activated database.
|
|
57
|
+
|
|
58
|
+
Real Scryfall integration runs are separate from the offline test suite. Perform them explicitly when changing normalization, import logic, source acquisition, or the on-disk schema. Avoid unnecessary API requests; use bulk exports rather than per-card downloads.
|
|
59
|
+
|
|
60
|
+
## Reporting issues
|
|
61
|
+
|
|
62
|
+
When reporting a bug, include the CardDB version, Python version, operating system, the operation attempted, and a minimal reproducible example or traceback.
|
|
63
|
+
|
|
64
|
+
For database build issues, source timestamps, source types, relevant hashes, and sanitized error messages are useful. Do not upload personal files or unrelated database contents without checking what they contain.
|
|
65
|
+
|
|
66
|
+
For security-sensitive reports, avoid posting exploit details publicly before there is an opportunity to investigate.
|
|
67
|
+
|
|
68
|
+
## Releases
|
|
69
|
+
|
|
70
|
+
See [docs/releasing.md](docs/releasing.md) for the release checklist and compatibility expectations.
|
|
71
|
+
|
|
72
|
+
The project is licensed under the [MIT License](LICENSE). Card data supplied by Scryfall is subject to its own terms and attribution requirements.
|
mtg_carddb-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jerrett Martin
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|