pypa / hatch

Modern, extensible Python project management
https://hatch.pypa.io/latest/
MIT License
5.95k stars 301 forks source link

“major.minor.micro” for requires-python gets no compatible Python distribution available #1586

Closed Mathieson closed 2 months ago

Mathieson commented 3 months ago

Hi there! I'm new to Hatch and excited about its potential for my workflows. I work in the video game industry, and a lot of my development time is spent inside DCCs (Maya, Houdini, etc.), where the Python version is already determined and locked.

I see Hatch possibly offering a "1-click" solution to setting up development environments for working with these tools, but I need to specify an exact version in the requires-python property. For example, Maya 2024 requires 3.10.8 exactly.

I've specified requires-python = "==3.10.8" in my pyproject.toml but when calling hatch shell I get the error...

Environment "default" is incompatible: no compatible Python distribution available

Should I be writing the requires-python line differently? Is there any other trick I can do, such as point it to that version if I've already pre-installed it on my machine?

Thanks!

ofek commented 3 months ago

Hey!

Can you please tell me a little bit more about your environment? Are the preinstalled Python distributions on PATH?

Mathieson commented 3 months ago

Certainly! Both cases (Autodesk Maya and SideFX Houdini) are 3D applications with integrated Python environments and additional libraries for running the functionality of each respective application. The preinstalled distributions are not on PATH. We will typically have several versions of Maya or Houdini installed on our machine at a time because we will support different game teams that are determining the versions of the tools for their production. Each version of Maya or Houdini will have a different micro version of Python that we cannot control.

I did find success yesterday with Hatch after I originally posted above. Going through more of the documentation, I discovered the key was pointing directly to the interpreter's path.

[tool.hatch.envs.default]
python = "C:\\Program Files\\Autodesk\\Maya2024\\bin\\mayapy.exe"
pre-install-commands = [
  "if not exist \"C:\\Program Files\\Autodesk\\Maya2024\\bin\\python.exe\" (mklink \"C:\\Program Files\\Autodesk\\Maya2024\\bin\\python.exe\" \"C:\\Program Files\\Autodesk\\Maya2024\\bin\\mayapy.exe\")"
]

[tool.hatch.envs.default.env-vars]
PYTHONPATH = "C:\\Program Files\\Autodesk\\Maya2024\\Python\\Lib\\site-packages"

The mklink call in the pre-install-commands is necessary for the virtual environment creation. As you can see, the interpreter is actually named mayapy.exe instead of python.exe.

The above works well, but the symlink need and repeated absolute (Windows) paths are unfortunate. I haven't been able to find a way to utilize environment variables to reuse the root path.

There is an alternative approach for setting up Maya for development. You can get a vanilla Python distro of the same version. (in the case of Maya 2024 it is Python 3.10.8) and then set up environment variables to add Maya's functionality. It would look something like this.

[project]
requires-python = "==3.10.8"

[tool.hatch.envs.default.env-vars]
MAYA_LOCATION = "C:\\Program Files\\Autodesk\\Maya2024"
PATH = "{env:PATH};{env:MAYA_LOCATION}\\bin"
PYTHONPATH = "{env:MAYA_LOCATION}\\Python\\Lib\\site-packages;{env:PYTHONPATH}"

Doing this, with an os.add_dll_directory call once Python is initialized, gives the same result as the first example. This setup process feels more direct and clean. But we need to have the exact same version of Python as what the DCC is using and the requires-python line, as written above, doesn't work.

Reading the docs further yesterday, it seems like Hatch is pulling Python distros from another project. I think I saw something about being able to specify python-sources under [tool.hatch.envs.default] but I didn't quite understand. Something about internal and external. Can you offer any more insight here?

Also, my env-vars section above doesn't work with the {env:MAYA_LOCATION} usages. Is there any way to do something like this so we don't need to repeat the absolute path everywhere?

ofek commented 3 months ago

Thanks for that detailed response!

  1. When you say doesn't work, what do you mean exactly? Can you please show the error?
  2. External source is essentially whatever is on PATH while internal is what is downloaded when nothing can be found on the machine.
  3. That doesn't work because the context is applied before the environment variable section starts rather than after each is parsed; I suppose I could add that feature however so feel free to open a request. You have a few workarounds:
    1. https://github.com/pypa/hatch/discussions/1554#discussioncomment-9693320
    2. https://github.com/pypa/hatch/issues/1556#issuecomment-2156797604
Mathieson commented 3 months ago

But we need to have the exact same version of Python as what the DCC is using and the requires-python line, as written above, doesn't work.

I meant here that there is an error with the feedback of no compatible Python distribution available. Continuing to read the docs, I think this is because the releases here for Python standalone don't include all micro-releases.

Thank you for linking to that plugin example! It just opened a bunch of new doors for me. I printed out the contents of the config dict and had an exciting realization. I can actually hide away a lot of this setup into a plugin like this, and then for the python option key, I can just give it maya2024 instead of the absolute path and resolve it to the absolute path inside. I'm really stoked about that, and I'm excited to try it out.

[tool.hatch.envs.default]
python = "maya2024"

If I create a plugin, what is the best way to deploy it within an organization? We have a custom PyPI server hosted on GitLab. We're currently using it for package distribution. Hatch allows us to use the PIP_EXTRA_INDEX_URL variable, so if we were to deploy our Hatch plugins to that custom PyPI, would the requires statement in [tool.hatch.env] respect the PIP_EXTRA_INDEX_URL and grab it from our custom PyPI? I couldn't conclude this from the docs.

[tool.hatch.env]
requires = [
  "hatch-maya",
]
ofek commented 3 months ago

In order to fetch plugins from a private index you would have to set that variable globally or install the plugin manually in the same environment as Hatch, for example if you are using the binary installation method you could run hatch self pip install ...