ofek / hatch-vcs

Hatch plugin for versioning with your preferred VCS
MIT License
109 stars 15 forks source link

Recommended way to use the build hook #13

Closed maresb closed 2 years ago

maresb commented 2 years ago

I'm trying to understand this comment recommending against setting __version__ with importlib.metadata.version when startup time is important (e.g. CLI).

Is this the sort of setup you had in mind?

hatch_vcs_example/__init__.py

# Set the value of '__version__'
try:
    # If setuptools_scm is installed (e.g. in a development environment),
    # then use it to determine the version dynamically.
    from setuptools_scm import get_version

    __version__ = get_version(root="..", relative_to=__file__)
except ImportError:
    # If setuptools_scm is not installed (e.g. in a release environment),
    # then use the version that is hard-coded in the file.
    try:
        from hatch_vcs_example._version import __version__  # noqa: F401
    except ModuleNotFoundError:
        raise RuntimeError(
            f"{__name__} is not correctly installed. Please install it with pip."
        )

pyproject.toml

[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"

[project]
name = "hatch-vcs-example"
dynamic = ["version"]

[tool.hatch.version]
source = "vcs"

[tool.hatch.build.hooks.vcs]
version-file = "hatch_vcs_example/_version.py"

.gitignore

hatch_vcs_example/_version.py

Initialization:

git init
git commit --allow-empty -m "Initial commit"
git tag v1.2.3
pip install .

Result:

hatch_vcs_example/_version.py

# coding: utf-8
# file generated by setuptools_scm
# don't change, don't track in version control
__version__ = version = '1.2.3'
__version_tuple__ = version_tuple = (1, 2, 3)

On my computer this saves about 40 ms (63 ms vs 23 ms).

I was thinking it could be useful to add this to the README, but it's a bit long. But in terms of impact, I think adding a minimalist example like

[tool.hatch.build.hooks.vcs]
version-file = "_version.py"

would go a long ways towards making the version-file feature more visible.

ofek commented 2 years ago

Correct, except you only need from hatch_vcs_example._version import __version__ as it will always be in the wheel.

maresb commented 2 years ago

But if I am working with an editable install, then I don't think _version.py will be updated, and it will report the wrong version. (That's why I give setuptools_scm priority.) Or is there some better way?

ofek commented 2 years ago

Well true, but not important enough to warrant that heavy logic, no?

maresb commented 2 years ago

I suppose it depends on the use case. If you only care about distributions then ya. But I spend most of my time developing closed-source Python in editable mode, and there the stale version numbers pose a serious risk of confusion.

maresb commented 2 years ago

I didn't expect the robust solution to end up being so inelegant. We could publish it in a separate repository, but I'm not so sure it's worthwhile.

Let's close this with #14. That makes it easier to notice the functionality while skimming the README. But beyond that, perhaps it's best to leave implementation details to the developer.

RonnyPfannschmidt commented 2 years ago

a key reason why setuptools_scm doesn't have something for this is that its utterly brittle, as a maintainer its not a feature i want to be responsible for

a reasonable solution would need a git hook to be installed and the version file/metadata to "self-update" regular, thats just a footgun for maintainers

maresb commented 2 years ago

I'm happy with #14 and building my own custom high-powered footguns, so closing. Thanks for the feedback!

RonnyPfannschmidt commented 2 years ago

@maresb if you package the footgun with footgun in the package name im happy to mention it in the docs

maresb commented 2 years ago

@RonnyPfannschmidt I threw together hatch-vcs-footgun-example. Does everything look correct?

ofek commented 2 years ago

fyi the wheel builder accepts a dependencies build option that build hooks can set conditionally

maresb commented 2 years ago

@ofek, could you please give me a hint about what I can do based on your last comment? I'm confused.

Are you suggesting a mechanism for automatically installing setuptools_scm when in editable mode? Am I implicitly using the wheel builder when I run pip install --editable? Also, I don't understand what is this Versions section in the docs; there seems to be no context.

ofek commented 2 years ago

I don't understand what is this Versions section in the docs

https://hatch.pypa.io/latest/config/build/#versions

Are you suggesting a mechanism for automatically installing setuptools_scm when in editable mode?

Yes, if you make it a real package you can:

from hatchling.builders.hooks.plugin.interface import BuildHookInterface

class FooBuildHook(BuildHookInterface):
    def initialize(self, version, build_data):
        if self.target_name == 'wheel' and version == 'editable':
            build_data['dependencies'].append('setuptools-scm')
maresb commented 2 years ago

Thanks @ofek for the explanation, that makes sense now.

But for my "example" I don't see how this would be so practical, but maybe you have a further idea?

The issue I see is that these are the current steps in my "Quick summary":

  1. Ensure that Hatch VCS is configured in pyproject.toml.
  2. Copy the contents of __init__.py and adjust to your project.
  3. Add _version.py to your .gitignore file.
  4. Install setuptools-scm as a development dependency.
  5. Enjoy up-to-date version numbers, even in editable mode.

After implementing FooBuildHook, the steps would look something like:

  1. Ensure that Hatch VCS and FooBuildHook are configured in pyproject.toml.
  2. Copy the contents of __init__.py and adjust to your project.
  3. Add _version.py to your .gitignore file.
  4. Enjoy up-to-date version numbers, even in editable mode.

So unless you believe that the only footgunny part is that the user might forget to install setuptools-scm, it doesn't seem to me like we gain much. (In any case I greatly appreciate you explaining the BuildHookInterface.)

maresb commented 2 years ago

I'm still fairly confused about the Hatch docs themselves. :disappointed:

Is there some way I myself could have made the connection between this Versions section on the "Wheel builder" page and the version argument of the initialize function on the "Build hook plugins" page?