diff --git a/.gitignore b/.gitignore index 42bccc600e..796472c993 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ # Python build files __pycache__/ +/scanpy/_version.py /dist/ /build/ /scanpy.egg-info/ diff --git a/pyproject.toml b/pyproject.toml index e3a75f9e45..37025079f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,17 +1,12 @@ [build-system] -build-backend = "flit_core.buildapi" -requires = [ - "flit_core >=3.4,<4", - "setuptools_scm", - "tomli", - "importlib_metadata>=0.7; python_version < '3.8'", -] +build-backend = "hatchling.build" +requires = ["hatchling", "hatch-vcs"] [project] name = "scanpy" description = "Single-Cell Analysis in Python." requires-python = ">=3.8" -license = {file = "LICENSE"} +license = "BSD-3-clause" authors = [ {name = "Alex Wolf"}, {name = "Philipp Angerer"}, @@ -31,7 +26,7 @@ maintainers = [ {name = "Philipp Angerer", email = "phil.angerer@gmail.com"}, {name = "Alex Wolf", email = "f.alex.wolf@gmx.de"}, ] -readme = {file = "README.md", content-type="text/markdown"} +readme = "README.md" classifiers = [ "License :: OSI Approved :: BSD License", "Development Status :: 5 - Production/Stable", @@ -135,11 +130,12 @@ scrublet = ["scrublet"] # Doublet detection rapids = ["cudf>=0.9", "cuml>=0.9", "cugraph>=0.9"] # GPU accelerated calculation of neighbors dask = ["dask[array]!=2.17.0"] # Use the Dask parallelization engine -[tool.flit.sdist] -exclude = [ - "scanpy/tests", - "setup.py", -] +[tool.hatch.build] +exclude = ["scanpy/tests"] +[tool.hatch.version] +source = "vcs" +[tool.hatch.build.hooks.vcs] +version-file = "scanpy/_version.py" [tool.pytest.ini_options] addopts = [ diff --git a/scanpy/__init__.py b/scanpy/__init__.py index ad7022c75e..ac997b45b4 100644 --- a/scanpy/__init__.py +++ b/scanpy/__init__.py @@ -1,42 +1,52 @@ """Single-Cell Analysis in Python.""" -from ._metadata import __version__, within_flit - -if not within_flit(): # see function docstring on why this is there - from ._utils import check_versions - - check_versions() - del check_versions, within_flit - - # the actual API - # (start with settings as several tools are using it) - from ._settings import settings, Verbosity - from . import tools as tl - from . import preprocessing as pp - from . import plotting as pl - from . import datasets, logging, queries, external, get, metrics, experimental - - from anndata import AnnData, concat - from anndata import ( - read_h5ad, - read_csv, - read_excel, - read_hdf, - read_loom, - read_mtx, - read_text, - read_umi_tools, - ) - from .readwrite import read, read_10x_h5, read_10x_mtx, write, read_visium - from .neighbors import Neighbors - - set_figure_params = settings.set_figure_params - - # has to be done at the end, after everything has been imported - import sys - - sys.modules.update({f'{__name__}.{m}': globals()[m] for m in ['tl', 'pp', 'pl']}) - from ._utils import annotate_doc_types - - annotate_doc_types(sys.modules[__name__], 'scanpy') - del sys, annotate_doc_types +try: # See https://github.com/maresb/hatch-vcs-footgun-example + from setuptools_scm import get_version + + __version__ = get_version(root="..", relative_to=__file__) + del get_version +except (ImportError, LookupError): + try: + from ._version import __version__ + except ModuleNotFoundError: + raise RuntimeError( + "scanpy is not correctly installed. Please install it, e.g. with pip." + ) + +from ._utils import check_versions + +check_versions() +del check_versions + +# the actual API +# (start with settings as several tools are using it) +from ._settings import settings, Verbosity +from . import tools as tl +from . import preprocessing as pp +from . import plotting as pl +from . import datasets, logging, queries, external, get, metrics, experimental + +from anndata import AnnData, concat +from anndata import ( + read_h5ad, + read_csv, + read_excel, + read_hdf, + read_loom, + read_mtx, + read_text, + read_umi_tools, +) +from .readwrite import read, read_10x_h5, read_10x_mtx, write, read_visium +from .neighbors import Neighbors + +set_figure_params = settings.set_figure_params + +# has to be done at the end, after everything has been imported +import sys + +sys.modules.update({f"{__name__}.{m}": globals()[m] for m in ["tl", "pp", "pl"]}) +from ._utils import annotate_doc_types + +annotate_doc_types(sys.modules[__name__], "scanpy") +del sys, annotate_doc_types diff --git a/scanpy/_metadata.py b/scanpy/_metadata.py deleted file mode 100644 index 188f34835b..0000000000 --- a/scanpy/_metadata.py +++ /dev/null @@ -1,46 +0,0 @@ -import traceback -from pathlib import Path - -here = Path(__file__).parent - - -def refresh_entry_points(): - """\ - Under some circumstances, (e.g. when installing a PEP 517 package via pip), - pkg_resources.working_set.entries is stale. This tries to fix that. - See https://github.com/pypa/setuptools_scm/issues/513 - """ - try: - import sys - import pkg_resources - - ws: pkg_resources.WorkingSet = pkg_resources.working_set - for entry in sys.path: - ws.add_entry(entry) - except Exception: - pass - - -try: - from setuptools_scm import get_version - - refresh_entry_points() - __version__ = get_version(root='..', relative_to=__file__) -except (ImportError, LookupError, FileNotFoundError): - from ._compat import pkg_metadata - - metadata = pkg_metadata(here.name) - __version__ = metadata['Version'] - - -def within_flit(): - """\ - Checks if we are being imported by flit. - This is necessary so flit can import __version__ without all depedencies installed. - There are a few options to make this hack unnecessary, see: - https://github.com/takluyver/flit/issues/253#issuecomment-737870438 - """ - for frame in traceback.extract_stack(): - if frame.name == 'get_docstring_and_version_via_import': - return True - return False