Hacker News new | past | comments | ask | show | jobs | submit login

>By "without it being a package", I mean that I don't have `src/foo`, which has `src/foo/__main__.py`, but e.g. `src/main.py`.

This doesn't matter. What does matter, though, is that [project.scripts] doesn't support passing arguments - the entry point is only specified as path.to.module:function , which is expected not to take any arguments (although of course it can read `sys.argv`, which will be forwarded from the wrapper). (You can, however, specify any callable, not just a function; and it could be a nested attribute of some other object.)

Relevant documentation:

https://packaging.python.org/en/latest/guides/writing-pyproj...

As far as I'm aware, there's no formal name for this syntax, and only indirect documentation of what's supported - via Setuptools, which originated it:

https://setuptools.pypa.io/en/latest/userguide/entry_point.h...

You could fix this by just making functions that hard-code the name (or e.g. use `functools.partial` to get what you want). With that properly set up, any standards-compliant build backend will put the needed metadata into your wheel, and Pip and uv will both read that metadata and create the necessary wrapper when installing. (This is "recommended" behaviour for installers in the wheel standard, but not required IIRC.)

Then for example, on Linux, you end up with a wrapper script in the environment's bin folder, which looks like:

  #!/path/to/.venv/bin/python
  # -*- coding: utf-8 -*-
  import re
  import sys
  from main import run_botch_bot
  if __name__ == '__main__':
      sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
      sys.exit(run_botch_bot())
(On Windows, IIRC you get cookie-cutter compiled executables that read their own filename and use it to do the right thing, perhaps with a Python shim to do the import or something.)

(Perhaps you'd be interested in raising the documentation issue on https://github.com/pypa/packaging.python.org/issues ?)




Thanks for the links. This helped point me in the right direction. I made no-argument callables in my launch script and ran `uvx migrate-to-uv`. I then changed the [tool.hatch...] section to this:

    [tool.hatch.build.targets.wheel]
    force-include = {"src/" = "/"}
With those three things done, I'm in business. Thanks!


Glad it worked. Most build systems attempt automatic package discovery, but they might not assume that you want to include top-level modules. I haven't tried Hatch(ling) so I can't advise. The maintainer posts here (and is active on discuss.python.org), though.




Consider applying for YC's Summer 2025 batch! Applications are open till May 13

Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: