2

I want to install my single file module together with its py.typed file using setuptools and pyproject.toml.

I'm packaging a Python single-module, and so far I was using a very simple pyproject.toml:

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

[project]
name = "sample"
version = 1.0.0
description = "Sample single-module"

Project repository layout is quite simple:

sample
├── pyproject.toml
└── sample.py

The module is installed at the root of site-packages and I can use it like:

from sample import whatever

The problem is, I want to provide a py.typed for this module, so the new repository layout is this:

sample
├── pyproject.toml
├── py.typed
└── sample.py

and the new pyproject.toml reads like this:

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

[project]
name = "sample"
version = 1.0.0
description = "Sample single-module"

[tool.setuptools]
include-package-data = true
package-data = {"sample" = ["py.typed"]}

Of course, setuptools still installs the module at the root of sitepackages and does not install data file py.typed. I was expecting this, and I did not find a clean solution for this, so I switched to a different repository layout, with a package and a module, like this:

sample
├── __init__.py
├── pyproject.toml
└── sample
    ├── __init__.py
    ├── py.typed
    └── sample.py

This works, but forces me to use the module as import sample.sample or from sample import sample, and I don't want this.

Is there alternative for:

  • Having a direct import, no package namespace.
  • Having package data installed.
  • Avoiding a module subdirectory (not essential).

I know about using __init__.py to import the module, so when I import sample, sample.sample is actually imported, but I'm curious about alternatives.

2
  • Have you considered the src layout: packaging.python.org/en/latest/discussions/… Commented Oct 23 at 6:59
  • Yes, John, but I would like to avoid it because it will complicate development, forcing me to install the package to test it by hand, or use an editable install. It is my last resort. Thanks for the edits, BTW ;) Commented Oct 23 at 8:30

1 Answer 1

3

You are correct that single py-module distributions can not have package data (because there is no package).

However, you can still have package data and have the direct import with a flat namespace. Rename the sample/sample/sample.py to sample/sample/__init__.py. Delete the outer sample/__init__.py, it is not necessary.

The resulting directory structure will look like this:

sample
├── pyproject.toml
└── sample
    ├── __init__.py
    └── py.typed

Your existing pyproject.toml looks OK. Import statements will still look like this:

from sample import whatever

With whatever defined directly in the __init__.py file.

Note: Some people prefer __init__.py files to contain just a simple listing of names, and no library code inside. If you want code and implementation defined in submodules instead of directly in __init__.py, that is fine, you would just import those names from within the __init__.py so that they remain available from the top namespace:

sample
├── pyproject.toml
└── sample
    ├── __init__.py
    ├── lib.py
    └── py.typed

In sample/lib.py:

def whatever():
   ...

In sample/__init__.py (you can use relative imports or absolute here, it doesn't matter):

from .lib import whatever

There is no harm in having implementation written directly in the __init__.py file, though.

To install your package for a development install ("editable") with a py.typed file, this is my recommendation:

pip install --editable . --config-settings editable_mode=strict

More info on that here.

Sign up to request clarification or add additional context in comments.

1 Comment

Thanks a lot for the advice, @wim. That was more or less what I was doing, in fact, except for the bit of the editable install in strict mode (I did not even know about strict editable mode). To be honest, I was switching to a src-layout because it is what I've used in other project and it just works, but I was curious about having a much simpler layout for simpler projects. Using what you suggest was a middle-ground acceptable method, but I thought it was a hack I should not be using. I'll try this before going to src-layout. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.