pythonpippython-packagingpyproject.tomlhatch

How to distribute a Python package where import name is different than project name using Hatch?


I am trying to package my project in order to upload it in PyPI. I have the following directory structure:

.
├── docs
├── LICENSE
├── pyproject.toml
├── README.md
├── src
│   ├── package_name
│   │   ├── __init__.py
│   │   ├── data.json
│   │   ├── __main__.py
│   │   ├── utils.py
└── tests

My package is in under src named src/package_name.

The pyproject.toml has the following lines:

[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[project]
name = "project_name"
version = "0.0.1"
authors = [{name = "Foo Bar"}]
license = {text = "GPL-3.0-only"}
description = "A small example package"
readme = "README.md"
requires-python = ">=3.10"
classifiers = [
    "Programming Language :: Python :: 3",
    "License :: OSI Approved :: MIT License",
    "Operating System :: POSIX :: Linux",
]

[project.urls]
Homepage = "https://example.com"

I want a user to be able to perform the installation as:

pip install project_name

but use the code as:

>>> from package_name import x

Is there any way to achieve this with Hatch? I have read the Build-instructions but can't find how.

Note

I have tried the following:

python3 -m build
python3 -m twine upload --repository testpypi dist/*
pip install --upgrade -i https://test.pypi.org/simple/ project_name

The problem is when I type:

>>> import package_name
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ModuleNotFoundError: No module named 'package_name'

I searched into path/to/site-packages but only path/to/site-packages/project_name-0.0.1.dist-info is there. Any ideas?

Tried to solve my problem based on this Tutorial.

The reason I used Hatch is because it was presented in the tutorial. Αn alternative solution (using also pyproject.toml with different backend) is also appreciated.

Edit

I have updated the directory structure as proposed in the comments.


Solution

  • I found the solution to my problem by simply switching to setuptools as backend and modifying the pyproject.toml as following:

    [build-system]
    requires = ["setuptools"]
    build-backend = "setuptools.build_meta"
    
    [tool.setuptools.packages.find]
    where = ["src"]
    
    [tool.setuptools.dynamic]
    version = {attr = "package_name.__version__"}
    
    [project]
    name = "package_name"
    dynamic = ["version"]
    
    authors = [{name = "Foo Bar"}]
    license = {text = "GPL-3.0-only"}
    description = "A small example package"
    readme = "README.md"
    requires-python = ">=3.10"
    
    classifiers = [
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
        "Operating System :: POSIX :: Linux",
    ]
    
    [project.urls]
    Homepage = "https://example.com""
    

    My solution is based on the setuptools Documentation.