diff --git a/.github/fetch_version.py b/.github/fetch_version.py new file mode 100644 index 00000000..ddecd809 --- /dev/null +++ b/.github/fetch_version.py @@ -0,0 +1,13 @@ +from policyengine_core.__version__ import __version__ + + +def fetch_version(): + try: + return __version__ + except Exception as e: + print(f"Error fetching version: {e}") + return None + + +if __name__ == "__main__": + print(fetch_version()) diff --git a/.github/is-version-number-acceptable.sh b/.github/is-version-number-acceptable.sh index 0f704a93..a9067e6b 100755 --- a/.github/is-version-number-acceptable.sh +++ b/.github/is-version-number-acceptable.sh @@ -12,7 +12,7 @@ then exit 0 fi -current_version=`python setup.py --version` +current_version=`python .github/fetch_version.py` if git rev-parse --verify --quiet $current_version then diff --git a/.github/publish-git-tag.sh b/.github/publish-git-tag.sh index 0143c67b..420f08f0 100755 --- a/.github/publish-git-tag.sh +++ b/.github/publish-git-tag.sh @@ -1,4 +1,4 @@ #! /usr/bin/env bash -git tag `python setup.py --version` +git tag `python .github/fetch_version.py` git push --tags || true # update the repository version diff --git a/Makefile b/Makefile index c04fd21e..1f7bfa19 100644 --- a/Makefile +++ b/Makefile @@ -21,11 +21,11 @@ test: test-country-template coverage xml -i build: - python setup.py sdist bdist_wheel + python -m build changelog: build-changelog changelog.yaml --output changelog.yaml --update-last-date --start-from 0.1.0 --append-file changelog_entry.yaml build-changelog changelog.yaml --org PolicyEngine --repo policyengine-core --output CHANGELOG.md --template .github/changelog_template.md - bump-version changelog.yaml setup.py + bump-version changelog.yaml pyproject.toml rm changelog_entry.yaml || true touch changelog_entry.yaml \ No newline at end of file diff --git a/changelog_entry.yaml b/changelog_entry.yaml index e69de29b..a95257f6 100644 --- a/changelog_entry.yaml +++ b/changelog_entry.yaml @@ -0,0 +1,7 @@ +- bump: minor + changes: + added: + - pyproject.toml, transforming from setup.py + - testing for pyproject.toml + changed: + - edited dependencies in setup.py to avoid overwriting diff --git a/policyengine_core/__version__.py b/policyengine_core/__version__.py new file mode 100644 index 00000000..f10d0c84 --- /dev/null +++ b/policyengine_core/__version__.py @@ -0,0 +1,9 @@ +import importlib.metadata +import tomli + +try: + with open("pyproject.toml", "rb") as f: + pyproject = tomli.load(f) + __version__ = pyproject["project"]["version"] +except Exception as e: + __version__ = importlib.metadata.version("policyengine_core") diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..7f526992 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,74 @@ +[build-system] +requires = ["setuptools"] +build-backend = "setuptools.build_meta" + +[project] +name = "policyengine-core" +version = "3.6.3" +dependencies = [ + "pytest>=8,<9", + "numpy~=1.26.4", + "black", + "linecheck<1", + "yaml-changelog<1", + "coverage", + "sortedcontainers<3", + "numexpr<3", + "dpath<3", + "psutil<6", + "wheel<1", + "h5py>=3,<4", + "requests>=2.27.1,<3", + "pandas>=1", + "plotly>=5.6.0,<6", + "ipython>=7.17.0,<8", + "pyvis>=0.3.2", + "tomli==2.0.1", + "build==1.2.2", +] +requires-python = ">=3.9" +authors = [ + {name = "PolicyEngine", email = "hello@policyengine.org"} +] +description = "Core microsimulation engine enabling country-specific policy models." +readme = "README.md" +license = {file = "LICENSE"} +keywords = ["tax", "benefit", "microsimulation", "framework"] +classifiers = [ + "Development Status :: 5 - Production/Stable", + "License :: OSI Approved :: GNU Affero General Public License v3", + "Operating System :: POSIX", + "Programming Language :: Python", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Information Analysis", +] +dynamic = ["scripts"] + +[project.optional-dependencies] +dev = [ + "jupyter-book<1", + "furo<2023", + "markupsafe==2.0.1", + "coverage", + "furo", + "mypy<2", + "sphinx==5.0.0", + "sphinx-argparse==0.4.0", + "sphinx-math-dollar==1.2.1", + "types-PyYAML==6.0.12.2", + "types-requests==2.28.11.7", + "types-setuptools==65.6.0.2", + "types-urllib3==1.26.25.4", +] + +[project.urls] +Homepage = "https://github.com/policyengine/policyengine-core" + +[tool.setuptools] +include-package-data = true + +[project.entry-points.console_scripts] +policyengine-core = "policyengine_core.scripts.policyengine_command:main" diff --git a/setup.py b/setup.py deleted file mode 100644 index 55e82b6d..00000000 --- a/setup.py +++ /dev/null @@ -1,83 +0,0 @@ -from pathlib import Path - -from setuptools import find_packages, setup - -# Read the contents of our README file for PyPi -this_directory = Path(__file__).parent -long_description = (this_directory / "README.md").read_text() - -# Please make sure to cap all dependency versions, in order to avoid unwanted -# functional and integration breaks caused by external code updates. - -general_requirements = [ - "pytest>=8,<9", - "numpy~=1.26.4", - "black", - "linecheck<1", - "yaml-changelog<1", - "coverage", - "sortedcontainers<3", - "numexpr<3", - "dpath<3", - "psutil<6", - "wheel<1", - "h5py>=3,<4", - "requests>=2.27.1,<3", - "pandas>=1", - "plotly>=5.6.0,<6", - "ipython>=7.17.0,<8", - "pyvis>=0.3.2", -] - -dev_requirements = [ - "jupyter-book<1", - "furo<2023", - "markupsafe==2.0.1", - "coverage", - "furo", - "mypy<2", - "sphinx==5.0.0", - "sphinx-argparse==0.4.0", - "sphinx-math-dollar==1.2.1", - "types-PyYAML==6.0.12.2", - "types-requests==2.28.11.7", - "types-setuptools==65.6.0.2", - "types-urllib3==1.26.25.4", -] - -setup( - name="policyengine-core", - version="3.6.6", - author="PolicyEngine", - author_email="hello@policyengine.org", - classifiers=[ - "Development Status :: 5 - Production/Stable", - "License :: OSI Approved :: GNU Affero General Public License v3", - "Operating System :: POSIX", - "Programming Language :: Python", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - "Programming Language :: Python :: 3.12", - "Topic :: Scientific/Engineering :: Information Analysis", - ], - description="Core microsimulation engine enabling country-specific policy models.", - keywords="tax benefit microsimulation framework", - license="https://www.fsf.org/licensing/licenses/agpl-3.0.html", - license_files=("LICENSE",), - url="https://github.com/policyengine/policyengine-core", - long_description=long_description, - long_description_content_type="text/markdown", - entry_points={ - "console_scripts": [ - "policyengine-core=policyengine_core.scripts.policyengine_command:main", - ], - }, - python_requires=">=3.9", - extras_require={ - "dev": dev_requirements, - }, - include_package_data=True, # Will read MANIFEST.in - install_requires=general_requirements, - packages=find_packages(exclude=["tests*"]), -) diff --git a/tests/core/test_toml.py b/tests/core/test_toml.py new file mode 100644 index 00000000..288b3224 --- /dev/null +++ b/tests/core/test_toml.py @@ -0,0 +1,41 @@ +import os +from pathlib import Path + +import pytest +import tomli + + +@pytest.fixture(scope="module") +def toml_data(): + # get the path of current file and find pyproject.toml relatively + file_path = ( + Path(os.path.abspath(os.path.dirname(__file__))).parents[1] + / "pyproject.toml" + ) + if not file_path.exists(): + pytest.fail(f"pyproject.toml not found in the current directory.") + with open(file_path, "rb") as f: + return tomli.load(f) + + +def test_toml_syntax(toml_data): + try: + toml_data + except tomli.TOMLDecodeError as e: + pytest.fail(f"TOML syntax error: {e}") + + +def test_required_fields(toml_data): + required_fields = ["name", "version", "dependencies"] + for field in required_fields: + assert field in toml_data.get( + "project", {} + ), f"Missing required field: {field}" + + +def test_build_system(toml_data): + build_system = toml_data.get("build-system", {}) + assert "requires" in build_system, "Build system 'requires' is missing." + assert ( + "build-backend" in build_system + ), "Build system 'build-backend' is missing."