diff --git a/hatch_vcs_footgun_example/__init__.py b/hatch_vcs_footgun_example/__init__.py index 0ce84a2..eb030f0 100644 --- a/hatch_vcs_footgun_example/__init__.py +++ b/hatch_vcs_footgun_example/__init__.py @@ -1,20 +1,9 @@ -# Define the variable '__version__': -try: - # If setuptools_scm is installed (e.g. in a development environment with - # an editable install), then use it to determine the version dynamically. - from setuptools_scm import get_version +"""Project initialization. - # This will fail with LookupError if the package is not installed in - # editable mode or if Git is not installed. - __version__ = get_version(root="..", relative_to=__file__) -except (ImportError, LookupError): - # As a fallback, use the version that is hard-coded in the file. - try: - from hatch_vcs_footgun_example._version import __version__ # noqa: F401 - except ModuleNotFoundError: - # The user is probably trying to run this without having installed - # the package, so complain. - raise RuntimeError( - "Hatch VCS Footgun Example is not correctly installed. " - "Please install it with pip." - ) +It is a popular convention to define `__version__` in the top-level `__init__.py`. +""" + +from hatch_vcs_footgun_example.version import __version__ + + +__all__ = ["__version__"] diff --git a/hatch_vcs_footgun_example/main.py b/hatch_vcs_footgun_example/main.py old mode 100644 new mode 100755 index 4fde653..f2d0842 --- a/hatch_vcs_footgun_example/main.py +++ b/hatch_vcs_footgun_example/main.py @@ -1,6 +1,6 @@ #!/usr/bin/env python3 -from hatch_vcs_footgun_example import __version__ +from hatch_vcs_footgun_example.version import __version__ if __name__ == "__main__": print(f"My version is '{__version__}'.") diff --git a/hatch_vcs_footgun_example/version.py b/hatch_vcs_footgun_example/version.py new file mode 100644 index 0000000..a92717f --- /dev/null +++ b/hatch_vcs_footgun_example/version.py @@ -0,0 +1,45 @@ +"""Compute the version number and store it in the `__version__` variable.""" + + +def _get_hatch_version(): + """Compute the most up-to-date version number in a development environment. + + Returns `None` if Hatchling is not installed, e.g. in a production environment. + + For more details, see . + """ + import os + + try: + from hatchling.metadata.core import ProjectMetadata + from hatchling.plugin.manager import PluginManager + from hatchling.utils.fs import locate_file + except ImportError: + # Hatchling is not installed, so probably we are not in + # a development environment. + return None + + pyproject_toml = locate_file(__file__, "pyproject.toml") + if pyproject_toml is None: + raise RuntimeError("pyproject.toml not found although hatchling is installed") + root = os.path.dirname(pyproject_toml) + metadata = ProjectMetadata(root=root, plugin_manager=PluginManager()) + # Version can be either statically set in pyproject.toml or computed dynamically: + return metadata.core.version or metadata.hatch.version.cached + + +def _get_importlib_metadata_version(): + """Compute the version number using importlib.metadata. + + This is the official Pythonic way to get the version number of an installed + package. However, it is only updated when a package is installed. Thus, if a + package is installed in editable mode, and a different version is checked out, + then the version number will not be updated. + """ + from importlib.metadata import version + + __version__ = version(__package__) + return __version__ + + +__version__ = _get_hatch_version() or _get_importlib_metadata_version()