[build-system]
requires = ["setuptools>=61", "setuptools-scm[toml]>=6.2"]
build-backend = "setuptools.build_meta"
[project]
name = "moscot"
dynamic = ["version"]
description = "Multi-omic single-cell optimal transport tools"
readme = "README.rst"
requires-python = ">=3.10"
license = {file = "LICENSE"}
classifiers = [
"Development Status :: 4 - Beta",
"Intended Audience :: Developers",
"Intended Audience :: Science/Research",
"Natural Language :: English",
"Operating System :: POSIX :: Linux",
"Operating System :: MacOS :: MacOS X",
"Operating System :: Microsoft :: Windows",
"Typing :: Typed",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Topic :: Scientific/Engineering :: Bio-Informatics",
"Topic :: Scientific/Engineering :: Mathematics"
]
keywords = [
"single-cell",
"bio-informatics",
"optimal transport"
]
authors = [
{name = "Dominik Klein"},
{name = "Giovanni Palla"},
{name = "Michal Klein"},
{name = "Zoe Piran"},
{name = "Marius Lange"},
]
maintainers = [
{name = "Dominik Klein", email = "dominik.klein@helmholtz-muenchen.de"},
{name = "Giovanni Palla", email = "giovanni.palla@helmholtz-muenchen.de"},
{name = "Michal Klein", email = "michal.klein@helmholtz-muenchen.de"}
]
dependencies = [
"numpy>=1.20.0",
"scipy>=1.7.0",
"pandas>=2.0.1",
"networkx>=3.2",
# https://github.com/scverse/scanpy/issues/2411
"matplotlib>=3.5.0",
"anndata>=0.9.1",
"scanpy>=1.9.3",
"wrapt>=1.13.2",
"docrep>=0.3.2",
"ott-jax>=0.5.0",
"cloudpickle>=2.2.0",
"rich>=13.5",
"docstring_inheritance>=2.0.0",
"mudata>=0.2.2"
]
[project.optional-dependencies]
spatial = [
"squidpy>=1.2.3"
]
neural = [
"optax",
"flax",
"diffrax",
"ott-jax[neural]>=0.5.0",
]
dev = [
"pre-commit>=3.0.0",
"tox>=4",
]
test = [
"pytest>=7",
"pytest-xdist>=3",
"pytest-mock>=3.5.0",
"pytest-cov>=4",
"coverage[toml]>=7",
"moscot[neural]"
]
docs = [
"sphinx>=5.1.1",
"sphinx_copybutton>=0.5.0",
"sphinxcontrib-bibtex>=2.3.0",
"sphinxcontrib-spelling>=7.6.2",
"sphinx-autodoc-typehints",
"furo>=2022.09.29",
"sphinx-tippy>=0.4.1",
"myst-nb>=0.17.1",
"ipython>=7.20.0",
"sphinx_design>=0.3.0",
]
[project.urls]
Homepage = "https://github.com/theislab/moscot"
Download = "https://moscot.readthedocs.io/en/latest/installation.html"
"Bug Tracker" = "https://github.com/theislab/moscot/issues"
Documentation = "https://moscot.readthedocs.io"
"Source Code" = "https://github.com/theislab/moscot"
[tool.setuptools]
package-dir = {"" = "src"}
include-package-data = true
[tool.setuptools_scm]
[tool.ruff]
exclude = [
".git",
"__pycache__",
"build",
"docs/_build",
"dist"
]
ignore = [
# Do not assign a lambda expression, use a def -> lambda expression assignments are convenient
"E731",
# allow I, O, l as variable names -> I is the identity matrix, i, j, k, l is reasonable indexing notation
"E741",
# Missing docstring in public package
"D104",
# Missing docstring in public module
"D100",
# Missing docstring in __init__
"D107",
# Missing docstring in magic method
"D105",
# Use `X | Y` for type annotations
"UP007",
]
line-length = 120
select = [
"D", # flake8-docstrings
# TODO(michalk8): enable this in https://github.com/theislab/moscot/issues/483
# "I", # isort
"E", # pycodestyle
"F", # pyflakes
"W", # pycodestyle
"Q", # flake8-quotes
"SIM", # flake8-simplify
"NPY", # NumPy-specific rules
"PT", # flake8-pytest-style
"TID", # flake8-tidy-imports
"B", # flake8-bugbear
"UP", # pyupgrade
"C4", # flake8-comprehensions
"BLE", # flake8-blind-except
"T20", # flake8-print
"RET", # flake8-raise
]
unfixable = ["B", "UP", "C4", "BLE", "T20", "RET"]
target-version = "py38"
[tool.ruff.per-file-ignores]
"tests/*" = ["D"]
"*/__init__.py" = ["F401"]
"docs/*" = ["D"]
"src/moscot/constants.py" = ["D101"]
"src/moscot/utils/subset_policy.py" = ["D101", "D102"]
[tool.ruff.pydocstyle]
convention = "numpy"
[tool.ruff.flake8-tidy-imports]
ban-relative-imports = "all"
[tool.ruff.flake8-quotes]
inline-quotes = "double"
[tool.black]
line-length = 120
target-version = ['py38']
include = '\.pyi?$'
[tool.isort]
profile = "black"
include_trailing_comma = true
multi_line_output = 3
sections = ["FUTURE", "STDLIB", "THIRDPARTY", "GENERIC", "NUMERIC", "PLOTTING", "BIO", "FIRSTPARTY", "LOCALFOLDER"]
# also contains what we import in notebooks
known_generic = ["wrapt", "joblib"]
known_numeric = ["numpy", "scipy", "jax", "ott", "pandas", "sklearn", "networkx", "statsmodels"]
known_bio = ["anndata", "scanpy", "squidpy"]
known_plotting = ["IPython", "matplotlib", "mpl_toolkits", "seaborn"]
[tool.pytest.ini_options]
markers = ["fast: marks tests as fask"]
xfail_strict = true
filterwarnings = [
"ignore:No data for colormapping:UserWarning",
"ignore:The dtype argument will be deprecated in anndata:PendingDeprecationWarning"
]
[tool.coverage.run]
branch = true
parallel = true
source = ["src/"]
omit = [
"*/__init__.py",
"*/_version.py",
]
[tool.coverage.report]
exclude_lines = [
'\#.*pragma:\s*no.?cover',
"^if __name__ == .__main__.:$",
'^\s*raise AssertionError\b',
'^\s*raise NotImplementedError\b',
'^\s*return NotImplemented\b',
]
precision = 2
show_missing = true
skip_empty = true
sort = "Miss"
[tool.rstcheck]
ignore_directives = [
"toctree",
"currentmodule",
"autosummary",
"module",
"automodule",
"autoclass",
"bibliography",
"glossary",
"card",
"grid",
]
ignore_roles = [
"mod",
]
[tool.mypy]
mypy_path = "$MYPY_CONFIG_FILE_DIR/src"
python_version = "3.10"
plugins = "numpy.typing.mypy_plugin"
ignore_errors = false
warn_redundant_casts = true
warn_unused_configs = true
warn_unused_ignores = true
disallow_untyped_calls = false
disallow_untyped_defs = true
disallow_incomplete_defs = true
disallow_any_generics = true
strict_optional = true
strict_equality = true
warn_return_any = false
warn_unreachable = false
check_untyped_defs = true
no_implicit_optional = true
no_implicit_reexport = true
no_warn_no_return = true
show_error_codes = true
show_column_numbers = true
error_summary = true
ignore_missing_imports = true
disable_error_code = ["assignment", "comparison-overlap", "no-untyped-def", "override"]
[tool.doc8]
max_line_length = 120
[tool.tox]
legacy_tox_ini = """
[tox]
min_version = 4.0
env_list = lint-code,py{3.10,3.11,3.12}
skip_missing_interpreters = true
[testenv]
extras = test,neural
commands =
python -m pytest {tty:--color=yes} {posargs: \
--cov={env_site_packages_dir}{/}moscot --cov-config={tox_root}{/}pyproject.toml \
--no-cov-on-fail --cov-report=xml --cov-report=term-missing:skip-covered}
passenv = PYTEST_*,CI
[testenv:lint-code]
description = Lint the code.
deps = pre-commit>=3.0.0
skip_install = true
commands =
pre-commit run --all-files --show-diff-on-failure
[testenv:lint-docs]
description = Lint the documentation.
extras = docs,neural
ignore_errors = true
allowlist_externals = make
pass_env = PYENCHANT_LIBRARY_PATH
set_env = SPHINXOPTS = -W -q --keep-going
changedir = {tox_root}{/}docs
commands =
make linkcheck {posargs}
# TODO(michalk8): uncomment after https://github.com/theislab/moscot/issues/490
# make spelling {posargs}
[testenv:examples-docs]
allowlist_externals = bash
description = Run the notebooks.
use_develop = true
deps =
ipykernel
jupytext
nbconvert
leidenalg
extras = docs,neural
changedir = {tox_root}{/}docs
commands =
python -m ipykernel install --user --name=moscot
bash {tox_root}/.run_notebooks.sh {tox_root}{/}docs/notebooks
[testenv:clean-docs]
description = Remove the documentation.
deps =
skip_install = true
changedir = {tox_root}{/}docs
allowlist_externals = make
commands =
make clean
[testenv:build-docs]
description = Build the documentation.
deps =
extras = docs,neural
allowlist_externals = make
changedir = {tox_root}{/}docs
commands =
make html {posargs}
commands_post =
python -c 'import pathlib; print("Documentation is under:", pathlib.Path("{tox_root}") / "docs" / "_build" / "html" / "index.html")'
[testenv:build-package]
description = Build the package.
deps =
build
twine
allowlist_externals = rm
commands =
rm -rf {tox_root}{/}dist
python -m build --sdist --wheel --outdir {tox_root}{/}dist{/} {posargs:}
python -m twine check {tox_root}{/}dist{/}*
commands_post =
python -c 'import pathlib; print(f"Package is under:", pathlib.Path("{tox_root}") / "dist")'
[testenv:format-references]
description = Format references.bib.
deps =
skip_install = true
allowlist_externals = biber
commands = biber --tool --output_file={tox_root}{/}docs{/}references.bib --nolog \
--output_align --output_indent=2 --output_fieldcase=lower \
--output_legacy_dates --output-field-replace=journaltitle:journal,thesis:phdthesis,institution:school \
{tox_root}{/}docs{/}references.bib
"""