Skip to content

Commit dbda14f

Browse files
committed
[WIP][Python] Improved the pyproject.toml spec (not enough to get rid of setup.py)
1 parent ccdacb8 commit dbda14f

File tree

7 files changed

+266
-11
lines changed

7 files changed

+266
-11
lines changed

.gitignore

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,30 @@
1-
tmp
2-
/build/
3-
/_skbuild/
4-
/dist/
5-
/opentrep.egg-info/
1+
#
2+
tmp/
3+
4+
# OpenTREP
5+
/pyopentrep.log
6+
/opentrep-*.log
7+
8+
# CMake / build
69
/build2/
710
/.tox/
811
/MANIFEST
912
/MANIFEST.in
13+
14+
# Python
1015
/Pipfile.lock
11-
/.python-version
12-
*.pyc
13-
/pyopentrep.log
16+
/_skbuild/
17+
/build/
18+
/dist/
19+
/.venv/
20+
.ipynb_checkpoints/
21+
*.py[cod]
22+
__pycache__/
23+
/requirements.txt
24+
/build/
25+
*.egg-info/
26+
typings/
27+
/poetry.lock
28+
/uv.lock
29+
.python-version
30+

Makefile

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
2+
# Today's date
3+
EXTRACT_DATE := $(shell date '+%Y%m%d')
4+
TODAY_DATE := $(shell date '+%Y-%m-%d')
5+
6+
isset-%: ## Test if variable % is set or exit with error
7+
echo # @: $(if $(value $*),,$(error Variable $* is not set))
8+
9+
.DEFAULT_GOAL:=help
10+
11+
# Cleaners
12+
clean-caches: ## Clean the project caches.
13+
rm -f .coverage
14+
rm -rf .hypothesis/
15+
rm -rf .mypy_cache/
16+
rm -rf .pytest_cache/
17+
18+
clean-python: ## Clean the Python caches.
19+
find . -type f -name '*.py[co]' -delete
20+
find . -type d -name __pycache__ -delete
21+
22+
clean-poetry: ## Clean Poetry environment
23+
rm -f poetry.lock
24+
25+
clean-python-cmake: ## Clean SciKit-Build
26+
rm -rf _skbuild/
27+
28+
clean-package: ## Clean the project package.
29+
rm -rf dist/
30+
31+
clean-install: ## Clean the project installation.
32+
rm -rf .venv/
33+
34+
clean-reports: ## Clean the project generated reports.
35+
rm -rf reports/*.*
36+
37+
cleaners: clean-caches clean-python clean-python-cmake clean-poetry clean-package clean-install clean-reports ## Run all the cleaners
38+
39+
# Installers
40+
init-poetry: clean-package clean-install clean-python clean-poetry ## Re-initialize Poetry dependencies
41+
poetry lock
42+
43+
install-dev: ## Install the project in dev mode
44+
python -mpip install -U poetry-plugin-export
45+
poetry lock #--no-update
46+
poetry run python -mpip install -U pip
47+
poetry run python -mpip install -U poetry-core setuptools wheel scikit-build cmake ninja protobuf
48+
poetry install --all-extras
49+
50+
install-local: ## Install the project in the local Python environment
51+
@python -mpip install --force-reinstall \
52+
dist/opentrep-*.whl
53+
54+
uninstall-local: ## Uninstall the project from the local Python environment
55+
python -mpip uninstall -y pyopentrep
56+
57+
# Bumpers
58+
bump-package-project: ## Bump the package version of the project.
59+
sed -i.bak 's/^version = .*/version = "$(shell cat VERSION)"/' pyproject.toml && rm pyproject.toml.bak
60+
61+
62+
# Builders
63+
build-deterministic-wheel: clean-package ## Build the software artifact (wheel)
64+
poetry run python3 -m pip install --upgrade build
65+
poetry export --without-hashes --without-urls -f requirements.txt --output requirements.txt
66+
poetry run python3 -m build --wheel
67+
68+
builders: build-deterministic-wheel ## Run all the builders
69+
70+

VERSION

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
0.7.18

build.py.new

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
2+
import os, sys, setuptools
3+
import skbuild
4+
import skbuild.constants
5+
6+
__all__ = ("build",)
7+
8+
9+
def build(setup_kwargs: dict) -> None:
10+
with open("README.md", "r") as fh:
11+
long_description = fh.read()
12+
13+
skbuild.setup (
14+
**setup_kwargs,
15+
cmake_args = [
16+
'-DINSTALL_DOC:BOOL=OFF',
17+
'-DRUN_GCOV:BOOL=OFF',
18+
'-DLIB_SUFFIX='
19+
] + (
20+
['-DREADLINE_ROOT=/usr/local/opt/portable-readline',
21+
'-DREADLINE_INCLUDE_DIR=/usr/local/opt/portable-readline/include',
22+
'-DREADLINE_LIBRARY=/usr/local/opt/libedit/lib/libedit.dylib',
23+
'-DICU_ROOT=/usr/local/opt/icu4c'] if sys.platform.startswith("darwin") else []
24+
)
25+
)
26+
27+
if __name__ == "__main__":
28+
build({})

build.py.orig

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
"""Build script."""
2+
3+
import shutil
4+
import sys
5+
from distutils import log as distutils_log
6+
from pathlib import Path
7+
from typing import Any, Dict
8+
9+
import skbuild
10+
import skbuild.constants
11+
12+
__all__ = ("build",)
13+
14+
15+
def build(setup_kwargs: Dict[str, Any]) -> None:
16+
"""Build C-extensions."""
17+
cmake_args = [
18+
'-DINSTALL_DOC:BOOL=OFF',
19+
'-DRUN_GCOV:BOOL=OFF',
20+
'-DLIB_SUFFIX='
21+
] + (
22+
['-DREADLINE_ROOT=/usr/local/opt/portable-readline',
23+
'-DREADLINE_INCLUDE_DIR=/usr/local/opt/portable-readline/include',
24+
'-DREADLINE_LIBRARY=/usr/local/opt/libedit/lib/libedit.dylib',
25+
'-DICU_ROOT=/usr/local/opt/icu4c'] if sys.platform.startswith("darwin") else []
26+
)
27+
skbuild.setup(**setup_kwargs, script_args=["build_ext"])
28+
# skbuild.setup(**setup_kwargs, script_args=cmake_args)
29+
30+
src_dir = Path(skbuild.constants.CMAKE_INSTALL_DIR()) / "opentrep"
31+
dest_dir = Path("opentrep")
32+
33+
# Delete C-extensions copied in previous runs, just in case.
34+
remove_files(dest_dir, "**/*.pyd")
35+
remove_files(dest_dir, "**/*.so")
36+
37+
# Copy built C-extensions back to the project.
38+
copy_files(src_dir, dest_dir, "**/*.pyd")
39+
copy_files(src_dir, dest_dir, "**/*.so")
40+
41+
42+
def remove_files(target_dir: Path, pattern: str) -> None:
43+
"""Delete files matched with a glob pattern in a directory tree."""
44+
for path in target_dir.glob(pattern):
45+
if path.is_dir():
46+
shutil.rmtree(path)
47+
else:
48+
path.unlink()
49+
distutils_log.info(f"removed {path}")
50+
51+
52+
def copy_files(src_dir: Path, dest_dir: Path, pattern: str) -> None:
53+
"""Copy files matched with a glob pattern in a directory tree to another."""
54+
for src in src_dir.glob(pattern):
55+
dest = dest_dir / src.relative_to(src_dir)
56+
if src.is_dir():
57+
# NOTE: inefficient if subdirectories also match to the pattern.
58+
copy_files(src, dest, "*")
59+
else:
60+
dest.parent.mkdir(parents=True, exist_ok=True)
61+
shutil.copy2(src, dest)
62+
distutils_log.info(f"copied {src} to {dest}")
63+
64+
65+
if __name__ == "__main__":
66+
build({})
67+

opentrep/python/pyopentrep.py.in

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
# -*- coding: utf-8 -*-
1+
#!/usr/bin/env python
22
#
33
# File:
44
# https://github.com/trep/opentrep/blob/master/opentrep/python/pyopentrep.py.in
@@ -515,7 +515,10 @@ def search(openTrepLibrary, searchString, outputFormat):
515515
############################
516516
# Main
517517
############################
518-
if __name__ == "__main__":
518+
def main():
519+
"""
520+
Main entry point
521+
"""
519522
(
520523
command,
521524
logPath,
@@ -581,3 +584,7 @@ if __name__ == "__main__":
581584

582585
# Free the OpenTREP library resource
583586
openTrepLibrary.finalize()
587+
588+
if __name__ == "__main__":
589+
main()
590+

pyproject.toml

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,68 @@
1+
#
2+
# References:
3+
# * https://github.com/tueda/test-poetry-scikit-build
4+
# * https://setuptools.pypa.io/en/latest/userguide/quickstart.html
5+
#
6+
7+
[project]
8+
name = "opentrep"
9+
version = "0.7.18"
10+
description = "Simple Python wrapper for OpenTREP"
11+
readme = "README.md"
12+
requires-python = ">=3.11,<3.14"
13+
authors = [
14+
{name = "Denis Arnaud", email = "[email protected]"},
15+
]
16+
license = "MIT"
17+
urls = {repository = "https://github.com/trep/opentrep"}
18+
dynamic = ["dependencies"]
19+
120
[build-system]
2-
requires = ["setuptools", "wheel", "scikit-build", "cmake", "ninja"]
21+
requires = ["poetry-core", "setuptools", "wheel", "scikit-build", "cmake", "ninja", "protobuf"]
22+
build-backend = "setuptools.build_meta"
23+
#build-backend = "poetry.core.masonry.api"
24+
25+
[project.scripts]
26+
trep = "pyopentrep:main"
27+
28+
[tool.setuptools.packages]
29+
find = {}
30+
31+
[tool.skbuild.setup]
32+
cmake_args = ["-DINSTALL_DOC:BOOL=OFF", "-DRUN_GCOV:BOOL=OFF", "-DLIB_SUFFIX="]
33+
34+
[tool.setuptools.dynamic]
35+
dependencies = {file = ["requirements.txt"]}
36+
37+
[tool.poetry]
38+
include = [
39+
# Source files for C extensions must be included in the source distribution.
40+
{ path = "CMakeLists.txt", format = "sdist" },
41+
{ path = "opentrep/**/*.cpp", format = "sdist" },
42+
# C extensions must be included in the wheel distribution.
43+
{ path = "opentrep/**/*.pyd", format = "wheel" },
44+
{ path = "opentrep/**/*.so", format = "wheel" },
45+
]
46+
exclude = ["opentrep/**/*.cpp", "opentrep/**/*.pyd", "opentrep/**/*.so"]
47+
48+
[tool.mypy]
49+
pretty = true
50+
show_error_codes = true
51+
strict = true
52+
warn_unreachable = true
53+
54+
[tool.pytest.ini_options]
55+
addopts = [
56+
"--cov-report=html",
57+
"--cov-report=term",
58+
"--cov=opentrep",
59+
"--doctest-modules",
60+
"--ignore=_skbuild",
61+
"--ignore=build.py",
62+
]
63+
64+
[tool.taskipy.tasks]
65+
build_ext.cmd = "python build.py"
66+
build_ext.help = "builds C extensions"
67+
368

0 commit comments

Comments
 (0)