Ctrl K
ComunidadGuías…

pyproject.toml

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

Archivo original ↗Preguntar a KiBot
# Packaging Scholion for PyPI.
#
# Two decisions worth explaining, because neither is obvious:
#
# 1. One dependency, and it is deliberate. Reading laboratory PDFs is not a
#    side feature — for most people it is the first thing the tool does with
#    their data, and `pdfplumber` is what does it. Declaring it means `pip
#    install scholion` gives a working application.
#
#    It used to be an extra, and the ingest code compensated by running
#    `pip install pdfplumber` on its own when a PDF turned up — including with
#    `--break-system-packages`. A project that promises nothing happens without
#    the user's command must not install packages into their interpreter behind
#    their back. Declared beats silent.
#
#    `pysam` stays an extra: it needs compilation, it is platform-specific, and
#    the genome path needs external tools (bcftools, samtools) anyway. Without
#    it the built-in tabixlite works — slower, on the standard library.
#
# 2. The version is read from the VERSION file. That file is already the single
#    source of truth for the changelog and for publication — there is no reason
#    to keep a second one. `__version__` in `src/scholion/__init__.py` is not a
#    constant: it comes from the metadata of the installed distribution, or, when
#    running from the sources, from that same VERSION file.

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

[project]
name = "scholion"
dynamic = ["version"]
description = "Local health insights for patients and clinicians: connect lab trends, genetics, prescriptions and wearable data"
readme = "README.md"
requires-python = ">=3.10"

# PEP 639: a licence expression plus the list of files. The code is Apache-2.0,
# but the curated knowledge base inside the package is CC BY 4.0, and both files,
# together with the required source notices, are obliged to travel in the
# distribution.
license = "Apache-2.0"
license-files = ["LICENSE", "LICENSE-DATA", "NOTICE", "ATTRIBUTION.md"]

# The e-mail belongs HERE, in the field the metadata standard has for it, and not
# in `[project.urls]`. PyPI rejects a `mailto:` there — «is not a valid url» — and
# it rejects it at UPLOAD, after the build, after `twine check` has passed, which
# is why two releases reached GitHub and neither reached PyPI.
authors = [{ name = "CrossRead", email = "scholion.dev@proton.me" }]
keywords = [
    "genomics", "pharmacogenomics", "clinvar", "acmg", "cpic",
    "polygenic-score", "laboratory", "wearables", "personal-health",
    "second-opinion", "n-of-1",
]

# A `License ::` classifier is deliberately absent — PEP 639 prescribes the
# `license` field instead.
classifiers = [
    "Development Status :: 4 - Beta",
    "Environment :: Console",
    "Environment :: Web Environment",
    "Intended Audience :: End Users/Desktop",
    "Intended Audience :: Healthcare Industry",
    "Intended Audience :: Science/Research",
    "Natural Language :: English",
    "Natural Language :: Russian",
    "Operating System :: MacOS",
    "Operating System :: POSIX :: Linux",
    # Added with the matrix cell that checks it, not before. Everything
    # this package does by itself runs there; what needs a Unix machine
    # is the OPTIONAL genome preparation in src/ingest — shell scripts
    # driving bwa, samtools and mosdepth — and the tools it looks for
    # are each behind a `which`, so their absence is reported rather
    # than fatal. If the Windows cell goes red, this line comes out.
    "Operating System :: Microsoft :: Windows",
    "Programming Language :: Python :: 3",
    "Programming Language :: Python :: 3.10",
    "Programming Language :: Python :: 3.11",
    "Programming Language :: Python :: 3.12",
    "Programming Language :: Python :: 3.13",
    "Topic :: Scientific/Engineering :: Bio-Informatics",
    "Topic :: Scientific/Engineering :: Medical Science Apps.",
]

# PDF extraction and, on Windows, the IANA database absent from the OS.
dependencies = [
    # Lab PDFs are the first data most people load. See the note at the top.
    "pdfplumber>=0.11",
    "tzdata; sys_platform == 'win32'",
]

[project.optional-dependencies]
# Kept so that `pip install "scholion[pdf]"` from older instructions still works;
# pdfplumber is a plain dependency now, so this extra adds nothing.
pdf = []
# Fast VCF access. Without it the built-in tabixlite is used — slower, but on
# the standard library alone.
genome = ["pysam>=0.22"]
all = ["scholion[pdf,genome]"]

[project.scripts]
scholion = "scholion.cli:main"
# A second entry point over the same core: `crossread` — "read your sources
# against each other". The CLI takes the program name from whatever it was called
# as, so the help text reads correctly either way.
crossread = "scholion.cli:main"

[project.urls]
Homepage = "https://github.com/CrossRead/scholion"
Repository = "https://github.com/CrossRead/scholion"
Changelog = "https://github.com/CrossRead/scholion/blob/main/CHANGELOG.md"
Issues = "https://github.com/CrossRead/scholion/issues"
# Every value under [project.urls] must be a URL, and PyPI means it. The address
# itself now travels in `authors`, where it is metadata rather than a link; this
# points at the section of the README that explains what to write about and, more
# importantly, what NOT to send.
Contact = "https://github.com/CrossRead/scholion#contact"

[tool.hatch.version]
path = "VERSION"
pattern = "(?P<version>[^\\s]+)"

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

# The same canonical readers serve source and installed commands. A wheel cannot
# rely on src/ingest beside the user's personal data directory.
[tool.hatch.build.targets.wheel.force-include]
"src/ingest/ingest_garmin.py" = "scholion/readers/ingest_garmin.py"
"src/ingest/ingest_whoop.py" = "scholion/readers/ingest_whoop.py"

# The sdist carries exactly what is needed for a reproducible build and for
# understanding the legal position. The personal directories (profile/, genome/)
# are not here and cannot be: they never reach git either.
# The tests and the checking tools travel in the sdist deliberately. The release
# gate requires running them INSIDE the unpacked artefact rather than in the
# repository: a green run at the author's end with a red one at the recipient's
# does not mean "verified", it means "the state of the artefact is unknown".
# Without tests/ and run_tests.sh such a run is impossible in principle.
[tool.hatch.build.targets.sdist]
include = [
    "/.gitattributes",
    "/docs",
    "/src/scholion",
    "/src/tools",
    # The data-preparation scripts: the genome build guide points at them, and
    # part of the test suite leans on them too (the n-of-1 maths lives in
    # src/ingest/nof1.py). Without them the sdist builds fine and the run inside
    # it dies on an import — which is what the gate caught on its first run.
    "/src/ingest",
    "/tests",
    "/run_tests.sh",
    "/README.md",
    "/CHANGELOG.md",
    "/CONTRIBUTING.md",
    "/DISCLAIMER.md",
    "/SECURITY.md",
    "/THREAT_MODEL.md",
    "/PRIVACY.md",
    "/CITATION.cff",
    "/ASSISTANT-RULES.md",
    "/VERSION",
]
exclude = [
    "**/__pycache__",
    "**/*.pyc",
    "**/.DS_Store",
]

# Lint — run in CI only (`.github/workflows/tests.yml`, job `lint`); the package
# itself still depends on nothing, and `run_tests.sh` asks nothing of the person
# who unpacked it. Rule set F (pyflakes): names used but never defined, imports
# never used, a name redefined before use. The first of these is the class that
# `set -u` catches in shell only when the branch runs — here it is caught on
# every push, whatever branch the name sits in.
[tool.ruff]
target-version = "py310"

[tool.ruff.lint]
select = ["F"]

[tool.ruff.lint.per-file-ignores]
# The engine package is a facade: it re-exports the names every face calls it by.
"src/scholion/engine/__init__.py" = ["F401"]