Skip to content

Commit

Permalink
feat: migrate from setuptools to hatch
Browse files Browse the repository at this point in the history
The official Python packaging guide recommends hatch over setuptools.
Beyond that official recommendation, getting rid of setuptools allows us
to resolve issue #956 on mypy-checking of plugins in editable mode.

Close #956.
  • Loading branch information
regisb committed Nov 22, 2024
1 parent 1a7c096 commit a071906
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 86 deletions.
7 changes: 2 additions & 5 deletions .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,8 @@ jobs:
python-version: 3.9
cache: 'pip'
cache-dependency-path: requirements/dev.txt
- name: Upgrade pip and setuptools
# https://pypi.org/project/pip/
# https://pypi.org/project/setuptools/
# https://pypi.org/project/wheel/
run: python -m pip install --upgrade pip setuptools==65.6.3 wheel
- name: Install Hatch
uses: pypa/hatch@install
- name: Print info about the current python installation
run: make ci-info
- name: Install requirements
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,8 @@ jobs:
python-version: ${{ matrix.python-version }}
cache: 'pip'
cache-dependency-path: requirements/dev.txt
- name: Upgrade pip
run: python -m pip install --upgrade pip setuptools
- name: Install dependencies
run: pip install -r requirements/dev.txt
run: pip install -e .[dev]
- name: Static code analysis
run: make test-lint
- name: Python unit tests
Expand Down
37 changes: 37 additions & 0 deletions .hatch_build.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
# https://hatch.pypa.io/latest/how-to/config/dynamic-metadata/
import os
import typing as t

from hatchling.metadata.plugin.interface import MetadataHookInterface

HERE = os.path.dirname(__file__)


class MetaDataHook(MetadataHookInterface):
def update(self, metadata: dict[str, t.Any]) -> None:
about = load_about()
metadata["version"] = about["__package_version__"]
metadata["dependencies"] = load_requirements("base.in")
metadata["optional-dependencies"] = {
"dev": load_requirements("dev.txt"),
"full": load_requirements("plugins.txt"),
}


def load_about() -> dict[str, str]:
about: dict[str, str] = {}
with open(os.path.join(HERE, "tutor", "__about__.py"), "rt", encoding="utf-8") as f:
exec(f.read(), about) # pylint: disable=exec-used
return about


def load_requirements(filename: str) -> list[str]:
requirements = []
with open(
os.path.join(HERE, "requirements", filename), "rt", encoding="utf-8"
) as f:
for line in f:
line = line.strip()
if line != "" and not line.startswith("#"):
requirements.append(line)
return requirements
5 changes: 0 additions & 5 deletions MANIFEST.in

This file was deleted.

8 changes: 3 additions & 5 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -9,16 +9,14 @@ docs: ## Build HTML documentation
$(MAKE) -C docs

compile-requirements: ## Compile requirements files
pip-compile ${COMPILE_OPTS} --output-file=requirements/base.txt
pip-compile ${COMPILE_OPTS} requirements/base.in
pip-compile ${COMPILE_OPTS} requirements/dev.in
pip-compile ${COMPILE_OPTS} --extra=docs --output-file=requirements/docs.txt
pip-compile ${COMPILE_OPTS} requirements/docs.in

upgrade-requirements: ## Upgrade requirements files
$(MAKE) compile-requirements COMPILE_OPTS="--upgrade"

build-pythonpackage: build-pythonpackage-tutor ## Build Python packages ready to upload to pypi

build-pythonpackage-tutor: ## Build the "tutor" python package for upload to pypi
build-pythonpackage: ## Build the "tutor" python package for upload to pypi
python -m build --sdist

push-pythonpackage: ## Push python package to pypi
Expand Down
1 change: 1 addition & 0 deletions changelog.d/20241122_145752_regis_pyproject_toml.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
- [Improvement] Migrate packaging from setup.py/setuptools to pyproject.toml/hatch. This should not be a breaking change for most users. (by @regisb)
35 changes: 22 additions & 13 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
# https://packaging.python.org/en/latest/tutorials/packaging-projects/
# https://setuptools.pypa.io/en/latest/userguide/quickstart.html
# https://hatch.pypa.io/latest/config/build/

[project]
dynamic = ["version", "dependencies", "optional-dependencies"]
name = "tutor"
license = {file = "LICENSE.txt"}
authors = [
Expand All @@ -22,6 +21,8 @@ classifiers = [
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
]
# these fields will be set by hatch_build.py
dynamic = ["version", "dependencies", "optional-dependencies"]

[project.scripts]
tutor = "tutor.commands.cli:main"
Expand All @@ -35,17 +36,25 @@ Issues = "https://github.com/overhangio/tutor/issues"
Changelog = "https://github.com/overhangio/tutor/blob/master/CHANGELOG.md"
Community = "https://discuss.openedx.org/tag/tutor"

# Setuptools-specific configuration
[build-system]
requires = ["setuptools", "wheel"]

[tool.setuptools.dynamic]
version = {attr = "tutor.__about__.__package_version__"}
dependencies = {file = ["requirements/base.in"] }
# hatch-specific configuration
[tool.hatch.metadata.hooks.custom]
path = ".hatch_build.py"

[tool.setuptools.dynamic.optional-dependencies]
dev = {file = ["requirements/dev.txt"]}
full = {file = ["requirements/plugins.txt"]}
[build-system]
requires = ["hatchling"]
build-backend = "hatchling.build"

[tool.setuptools.packages.find]
[tool.hatch.build.targets.sdist]
# Disable strict naming, otherwise twine is not able to detect name/version
strict-naming = false
include = [
"/tutor",
"requirements/base.in",
"requirements/plugins.txt",
"requirements/dev.txt",
]
exclude = ["tests*"]

[tool.hatch.metadata]
# Allow github dependencies in plugins.txt
allow-direct-references = true
34 changes: 19 additions & 15 deletions requirements/base.txt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
#
# This file is autogenerated by pip-compile with Python 3.12
# This file is autogenerated by pip-compile with Python 3.9
# by the following command:
#
# pip-compile --output-file=requirements/base.txt
# pip-compile requirements/base.in
#
appdirs==1.4.4
# via tutor (pyproject.toml)
# via -r requirements/base.in
cachetools==5.5.0
# via google-auth
certifi==2024.8.30
Expand All @@ -15,47 +15,47 @@ certifi==2024.8.30
charset-normalizer==3.4.0
# via requests
click==8.1.7
# via tutor (pyproject.toml)
# via -r requirements/base.in
durationpy==0.9
# via kubernetes
google-auth==2.35.0
# via kubernetes
idna==3.10
# via requests
importlib-metadata==8.5.0
# via tutor (pyproject.toml)
# via -r requirements/base.in
importlib-resources==6.4.5
# via tutor (pyproject.toml)
# via -r requirements/base.in
jinja2==3.1.4
# via tutor (pyproject.toml)
# via -r requirements/base.in
kubernetes==31.0.0
# via tutor (pyproject.toml)
# via -r requirements/base.in
markupsafe==3.0.2
# via jinja2
mypy==1.13.0
# via tutor (pyproject.toml)
# via -r requirements/base.in
mypy-extensions==1.0.0
# via mypy
oauthlib==3.2.2
# via
# kubernetes
# requests-oauthlib
packaging==24.1
# via tutor (pyproject.toml)
packaging==24.2
# via -r requirements/base.in
pyasn1==0.6.1
# via
# pyasn1-modules
# rsa
pyasn1-modules==0.4.1
# via google-auth
pycryptodome==3.21.0
# via tutor (pyproject.toml)
# via -r requirements/base.in
python-dateutil==2.9.0.post0
# via kubernetes
pyyaml==6.0.2
# via
# -r requirements/base.in
# kubernetes
# tutor (pyproject.toml)
requests==2.32.3
# via
# kubernetes
Expand All @@ -68,15 +68,19 @@ six==1.16.0
# via
# kubernetes
# python-dateutil
tomli==2.1.0
# via mypy
typing-extensions==4.12.2
# via
# -r requirements/base.in
# mypy
# tutor (pyproject.toml)
urllib3==2.2.3
# via
# kubernetes
# requests
websocket-client==1.8.0
# via kubernetes
zipp==3.20.2
# via importlib-metadata
# via
# importlib-metadata
# importlib-resources
1 change: 0 additions & 1 deletion requirements/dev.in
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,3 @@ docutils<0.19.0
# Types packages
types-docutils
types-PyYAML
types-setuptools
24 changes: 15 additions & 9 deletions requirements/dev.txt
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,7 @@
# pip-compile requirements/dev.in
#
altgraph==0.17.4
# via
# macholib
# pyinstaller
# via pyinstaller
appdirs==1.4.4
# via -r requirements/base.txt
astroid==3.3.5
Expand All @@ -29,6 +27,8 @@ certifi==2024.8.30
# -r requirements/base.txt
# kubernetes
# requests
cffi==1.17.1
# via cryptography
charset-normalizer==3.4.0
# via
# -r requirements/base.txt
Expand All @@ -44,6 +44,8 @@ click-log==0.4.0
# via scriv
coverage==7.6.4
# via -r requirements/dev.in
cryptography==43.0.3
# via secretstorage
dill==0.3.9
# via pylint
docutils==0.18.1
Expand Down Expand Up @@ -80,6 +82,10 @@ jaraco-context==6.0.1
# via keyring
jaraco-functools==4.1.0
# via keyring
jeepney==0.8.0
# via
# keyring
# secretstorage
jinja2==3.1.4
# via
# -r requirements/base.txt
Expand All @@ -88,8 +94,6 @@ keyring==25.5.0
# via twine
kubernetes==31.0.0
# via -r requirements/base.txt
macholib==1.16.3
# via pyinstaller
markdown-it-py==3.0.0
# via
# rich
Expand Down Expand Up @@ -120,7 +124,7 @@ oauthlib==3.2.2
# -r requirements/base.txt
# kubernetes
# requests-oauthlib
packaging==24.1
packaging==24.2
# via
# -r requirements/base.txt
# black
Expand All @@ -146,6 +150,8 @@ pyasn1-modules==0.4.1
# via
# -r requirements/base.txt
# google-auth
pycparser==2.22
# via cffi
pycryptodome==3.21.0
# via -r requirements/base.txt
pygments==2.18.0
Expand Down Expand Up @@ -196,12 +202,14 @@ rsa==4.9
# google-auth
scriv==1.5.1
# via -r requirements/dev.in
secretstorage==3.3.3
# via keyring
six==1.16.0
# via
# -r requirements/base.txt
# kubernetes
# python-dateutil
tomli==2.0.2
tomli==2.1.0
# via
# -r requirements/base.txt
# black
Expand All @@ -217,8 +225,6 @@ types-docutils==0.21.0.20241005
# via -r requirements/dev.in
types-pyyaml==6.0.12.20240917
# via -r requirements/dev.in
types-setuptools==75.2.0.20241025
# via -r requirements/dev.in
typing-extensions==4.12.2
# via
# -r requirements/base.txt
Expand Down
Loading

0 comments on commit a071906

Please sign in to comment.