Ctrl K
ComunidadGuías…

pyproject.toml

Rama main · réplica de lectura del repositorio original.

Archivo original ↗Preguntar a KiBot
[project]
name = "foilstack"
dynamic = ["version"]
description = "Open-source card scanning, inventory and listing export. Self-hostable."
readme = "README.md"
requires-python = ">=3.11"
license = { text = "AGPL-3.0-or-later" }
keywords = ["tcg", "trading-cards", "inventory", "mtg", "pokemon", "self-hosted"]
authors = [{ name = "foilstack contributors" }]
classifiers = [
    "Development Status :: 3 - Alpha",
    "Environment :: Web Environment",
    "Framework :: FastAPI",
    "Intended Audience :: End Users/Desktop",
    "License :: OSI Approved :: GNU Affero General Public License v3 or later (AGPLv3+)",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
    "Topic :: Games/Entertainment",
    "Topic :: Office/Business",
]

dependencies = [
    "fastapi>=0.115",
    "uvicorn[standard]>=0.30",
    "sqlalchemy>=2.0",
    "psycopg[binary]>=3.2",
    "pgvector>=0.3.6",
    # Runtime, not development. `foilstack migrate` is how an installed copy
    # creates its schema, and without this it fails on an ImportError at the
    # one moment a new user has nothing else to try.
    "alembic>=1.13",
    "argon2-cffi>=23.1",
    "itsdangerous>=2.2",
    "jinja2>=3.1",
    "python-multipart>=0.0.9",
    "httpx>=0.27",
    "numpy>=1.26",
    "pillow>=10.0",
    "pydantic>=2.7",
    # Runtime, not development, and declared rather than leaned on: it arrives
    # transitively with uvicorn[standard], and a settings read that silently
    # stops finding `.env` because a transitive dependency moved is the kind of
    # break that points at the wrong thing.
    "python-dotenv>=1.0",
]

[project.urls]
Homepage = "https://foilstack.ai"
Source = "https://github.com/foilstack/foilstack"
Issues = "https://github.com/foilstack/foilstack/issues"

[project.optional-dependencies]
embedder = ["torch>=2.2", "transformers>=4.44"]
# `foilstack enrich` streams a 1.1 GB JSON file. An extra rather than a
# dependency: it is needed by one Magic-only command that most installs will
# run once or never, and the enricher says so by name when it is missing.
mtgjson = ["ijson>=3.2"]
# `ijson` is in here as well as in `mtgjson` because the suite covers the
# enricher, and a test that skips when an extra is absent is a test that
# reports green for code nobody ran.
dev = [
    "pytest>=8.0",
    "pytest-asyncio>=0.23",
    "playwright>=1.48",
    "ruff>=0.14",
    "mypy>=1.13",
    "ijson>=3.2",
]

# Installs a `foilstack` command. Without it the CLI is only reachable as
# `python -m foilstack.cli`, which is not what the README says and not what
# anybody types.
[project.scripts]
foilstack = "foilstack.cli:main"

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

# The version lives in `src/foilstack/__init__.py` and is read from there.
# It is rendered in the page footer and sent as the TCGCSV User-Agent, so a
# second copy here is a copy that goes stale and then misreports both.
[tool.hatch.version]
path = "src/foilstack/__init__.py"

[tool.hatch.build.targets.wheel]
packages = ["src/foilstack"]

[tool.pytest.ini_options]
pythonpath = ["src"]
asyncio_mode = "auto"

[dependency-groups]
dev = [
    "pre-commit>=4.6.2",
]

[tool.ruff]
# Wider than the default 88. The prose comments in this codebase are wrapped
# to about 79 and the code sits comfortably under 100; at 88 the formatter
# explodes several readable tables — the pricing rules, the queue row builder —
# into one item per line for the sake of a few characters.
line-length = 100
target-version = "py311"

[tool.ruff.lint]
select = [
    "E", "W",   # pycodestyle
    "F",        # pyflakes
    "I",        # import sorting
    "UP",       # pyupgrade
    "B",        # bugbear
    "C4",       # comprehensions
    "SIM",      # simplify
    "BLE",      # blind except
    "RUF",
]
ignore = [
    # `assert` in tests is the point of tests.
    "S101",
]

[tool.ruff.lint.flake8-bugbear]
# FastAPI's whole dependency system is function calls in argument defaults —
# `Depends()`, `Query()`, `Form()`, `File()`. B008 exists to catch a mutable
# default evaluated once by accident; these are evaluated once on purpose and
# are the documented way to use the framework. Exempting them by name rather
# than switching B008 off keeps the rule working everywhere else.
extend-immutable-calls = [
    "fastapi.Depends", "fastapi.Query", "fastapi.Form",
    "fastapi.File", "fastapi.Body", "fastapi.Header",
]

[tool.ruff.lint.per-file-ignores]
# Migrations are generated, then annotated by hand. Import order and line
# length in them are alembic's business, not ours.
"src/foilstack/migrations/versions/*" = ["E501", "I001"]
# Sixteen quoted columns is 120 characters. Those fixtures are rows copied
# verbatim out of a real TCGplayer export, and a row reflowed to fit is no
# longer the thing the test claims to be testing against.
"tests/test_tcgplayer_match.py" = ["E501"]

[tool.ruff.format]
docstring-code-format = true

[tool.mypy]
python_version = "3.11"
files = ["src/foilstack"]
# Third-party stubs are patchy across sqlalchemy plugins, transformers and
# torch; chasing them adds noise without finding bugs.
ignore_missing_imports = true
# Deliberately not `strict`. Strict reports 142 errors on this codebase, almost
# all of them "add an annotation here" rather than "this is wrong" — a number
# that large gets a blanket ignore rather than a fix, and then the check is
# decoration. At this setting it found four real things: a mutable class
# attribute shared between plugin instances, a deprecated Pillow constant, a
# dict lookup on a possibly-None key, and a plugin protocol that did not
# describe half of what the application calls on it. Tighten a module at a
# time as annotations arrive.
warn_unused_ignores = true
warn_redundant_casts = true

# numpy ships stubs written with 3.12+ `type` statements, which mypy refuses to
# parse while `python_version` says 3.11 — and 3.11 is what `requires-python`
# promises, so lowering the check to suit a dependency's stubs would be the
# wrong way round. Skip following into it instead; nothing here relies on
# numpy's types beyond "an array of floats goes to the encoder".
[[tool.mypy.overrides]]
module = ["numpy.*"]
follow_imports = "skip"
follow_imports_for_stubs = true