34

I'm trying to add a pyproject.toml to a project that's been using setup.py in order to enable support by pipx. I'd like to specify the command line scripts the project includes in pyproject.toml, but all the guides I can find give instructions for use with poetry, which I am not using.

I also don't want to specify entry points to modules - I already have working command line scripts and just want to specify those.

Is there a proper place in pyproject.toml to specify command line scripts?

Not sure it matters, but the package in question is cutlet.

polm23
  • 14,456
  • 7
  • 35
  • 59
  • Note that in this case throwing out my existing scripts and using entry points ended up being the easiest thing - it was much less involved than I had feared. – polm23 Oct 04 '21 at 11:33

2 Answers2

47

Update July 2022: if your TOML file uses setuptools as its build system, setuptools will happily create and install a command-line script. For example, my pyproject.toml file starts like this:

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

Extend your pyproject.toml file with an entry like this, naming the package, module and entry-point function names:

[project.scripts]
my-client = "my_package.my_module:main_cli"

Then run the install sequence:

pip3 install .

And setuptools will install a shell script named my-client somewhere appropriate, for me in my Py3.9 virtual environment's bin directory (~/.virtualenvs/py39/bin).

I was doing a similar thing, upgrading a package that had a setup.py, altho I had no existing scripts. With the rewrite to using pyproject.toml I dropped the old setup.py file entirely.

FWIW I realize the OP asked for a way to install existing scripts, which I didn't provide. This answer tells setuptools to create and install new scripts.

Update Feb 2023: thanks for all the votes. If you're cutting corners to meet arbitrary management deadlines, just copy-paste this short pyproject.toml file and adjust:

[build-system]
requires = ["setuptools>=61.0"]
build-backend = "setuptools.build_meta"

[project]
name = "my_client"
version = "1.2.3"
authors = [{name="Ubr Programmer", email="ubr@gmailington.com" }]
description = "Client for my awesome system"
readme = "README.md"
dependencies = ["cachetools","requests"]
requires-python = ">=3.9"

[project.scripts]
my-client = "my_package.my_module:main_cli"

[project.urls]
"Homepage" = "https://github.com/your_name_here/something"
"Bug Tracker" = "https://github.com/your_name_here/something/issues"
chrisinmtown
  • 3,571
  • 3
  • 34
  • 43
  • 2
    Reference https://setuptools.pypa.io/en/latest/userguide/pyproject_config.html – zerocog Oct 19 '22 at 09:13
  • 1
    @zerocog that "reference" doesn't describe `project.scripts` except to say that it replaces something deprecated called `script-files`. – blee Oct 30 '22 at 16:54
  • @blee if you search in the site project.scripts , you will find how project.scripts is used as entry points. https://setuptools.pypa.io/en/latest/userguide/quickstart.html#entry-points-and-automatic-script-creation – zerocog Nov 04 '22 at 17:38
  • Can you please specify where is "my-client = "my_package.my_module:main_cli""? If you have one file in `src/foo.py` how to to it? – somenxavier Feb 19 '23 at 15:23
  • 1
    @somenxavier I don't see a package name (subdirectory) in the path `src/` I think you probably have to restructure your project a little bit. For example: https://stackoverflow.com/questions/68476886/what-is-the-correct-folder-structure-to-use-for-a-python-project-using-pytest – chrisinmtown Feb 20 '23 at 12:47
  • @chrisinmtown Ideally, an example of how to do it following the official guide of packaging in python could be ideal. – somenxavier Feb 21 '23 at 19:24
  • @somenxavier If `foo.py` contains this `if __name__ == "__main__": main()` then is would be "intended-script-name = "src.foo:main"" – Michael Aug 25 '23 at 13:10
13

Is there a proper place in pyproject.toml to specify command line scripts?

PEP566 (Metadata 2.1) only defines Core metadata specifications. Thus, the answer depends on your build system (Note: PEP518 defines build system concept).

If you use the existing build tools such as setuptools, poetry, and flit, you only can consider adding such options in pyproject.toml if that tool supports command line scripts (console_scripts) in pyproject.toml. Surely, if you have your own build tool, you need to implement a parser to parse the command line scripts in pyproject.toml.

Lastly, you can check below list to know which major build system supports command line scripts (console_scripts) in pyproject.toml (2020/Oct):

Kir Chou
  • 2,980
  • 1
  • 36
  • 48
  • setuptools now [supports](https://setuptools.pypa.io/en/latest/userguide/entry_point.html#console-scripts) that, so does [hatch](https://hatch.pypa.io/latest/config/metadata/#cli) – sourcream Jul 30 '23 at 00:10