From 2f7400e6c036b03aa1b3852ae8e8370600da3726 Mon Sep 17 00:00:00 2001 From: Alexander Minges Date: Thu, 10 Jul 2025 11:11:38 +0200 Subject: [PATCH] Migrate to pyproject.toml and modernize project configuration --- MANIFEST.in | 19 +++++++ doi2dataset.py | 23 +++++++-- pyproject.toml | 134 +++++++++++++++++++++++++++++++++++++++++++++++++ setup.py | 59 ---------------------- 4 files changed, 173 insertions(+), 62 deletions(-) create mode 100644 MANIFEST.in create mode 100644 pyproject.toml delete mode 100644 setup.py diff --git a/MANIFEST.in b/MANIFEST.in new file mode 100644 index 0000000..0862eea --- /dev/null +++ b/MANIFEST.in @@ -0,0 +1,19 @@ +include README.md +include LICENSE.md +include config_example.yaml +include requirements.txt +recursive-include assets *.webp +global-exclude *.pyc +global-exclude __pycache__ +global-exclude .DS_Store +global-exclude *.so +global-exclude .git* +global-exclude .venv* +global-exclude .pytest_cache* +global-exclude htmlcov* +global-exclude .coverage* +global-exclude coverage.xml +global-exclude junit.xml +global-exclude docs/build* +global-exclude tests* +global-exclude *.json diff --git a/doi2dataset.py b/doi2dataset.py index 438e3a2..2aac6e5 100755 --- a/doi2dataset.py +++ b/doi2dataset.py @@ -24,12 +24,13 @@ import json import sys import unicodedata import warnings # TODO: Remove once the warning is stripped from idutils +from collections.abc import Sequence from dataclasses import dataclass, field from datetime import datetime from enum import Enum from functools import reduce from pathlib import Path -from typing import Any, Sequence +from typing import Any import dns.resolver import requests @@ -48,6 +49,18 @@ from rich.progress import ( from rich.table import Table from rich.theme import Theme +# Get version from setuptools_scm +try: + from importlib.metadata import version + __version__ = version("doi2dataset") +except ImportError: + # Fallback for older Python versions + try: + import pkg_resources + __version__ = pkg_resources.get_distribution("doi2dataset").version + except Exception: + __version__ = "1.0.0" # Fallback version + # Idutils throws an unconditional warning about deprecation of relative imports. # Since we are not using them, supress the warning to not confuse users # TODO: Remove once the warning is stripped from idutils @@ -1693,8 +1706,8 @@ def process_doi_batch( return results -if __name__ == "__main__": - +def main(): + """Main entry point for the console script.""" console = Console(theme=THEME) try: @@ -1789,3 +1802,7 @@ if __name__ == "__main__": except Exception as e: console.print(f"\n{ICONS['error']} An unexpected error occurred: {str(e)}", style="error") sys.exit(1) + + +if __name__ == "__main__": + main() diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..bd1a783 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,134 @@ +[build-system] +requires = ["setuptools>=61.0", "wheel", "setuptools_scm>=8.0"] +build-backend = "setuptools.build_meta" + +[project] +name = "doi2dataset" +dynamic = ["version"] +description = "A tool to process DOIs and generate metadata for Dataverse.org datasets." +readme = "README.md" +license = "MIT" +license-files = ["LICENSE.md"] +authors = [{ name = "Alexander Minges", email = "alexander.minges@uni-due.de" }] +maintainers = [ + { name = "Alexander Minges", email = "alexander.minges@uni-due.de" }, +] +classifiers = [ + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering :: Information Analysis", + "Topic :: Software Development :: Libraries :: Python Modules", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Programming Language :: Python :: 3.13", + "Operating System :: OS Independent", +] +keywords = ["doi", "dataverse", "metadata", "research", "datasets"] +requires-python = ">=3.10" +dependencies = [ + "dnspython>=2.7.0,<3.0.0", + "requests>=2.32.3,<2.33.0", + "PyYAML>=6.0,<7.0", + "email_validator>=2.2.0,<3.0.0", + "rich>=13.9.4,<14.0.0", + "idutils>=1.4.2,<2.0.0", +] + +[project.urls] +Homepage = "https://git.uni-due.de/cbm343e/doi2dataset" +Repository = "https://git.uni-due.de/cbm343e/doi2dataset" +Documentation = "https://doi2dataset-66f763.gitpages.uni" +"Bug Tracker" = "https://git.uni-due.de/cbm343e/doi2dataset/-/issues" + +[project.optional-dependencies] +docs = ["sphinx>=8.2.3,<9.0.0", "sphinx_rtd_theme>=3.0,<4.0"] +dev = [ + "pytest>=8.3.5,<9.0", + "pytest-mock>=3.14.0,<4.0", + "pytest-cov>=6.0.0,<7.0", + "ruff>=0.11.1,<0.20", +] +test = [ + "pytest>=8.3.5,<9.0", + "pytest-mock>=3.14.0,<4.0", + "pytest-cov>=6.0.0,<7.0", +] + +[project.scripts] +doi2dataset = "doi2dataset:main" + +[tool.setuptools_scm] +version_scheme = "python-simplified-semver" +local_scheme = "no-local-version" +fallback_version = "1.0.0" + +[tool.setuptools] +py-modules = ["doi2dataset"] + +[tool.setuptools.package-data] +"*" = ["*.md", "*.yaml", "*.webp"] + +[tool.pytest.ini_options] +testpaths = ["tests"] +python_files = ["test_*.py"] +python_classes = ["Test*"] +python_functions = ["test_*"] +addopts = [ + "--strict-markers", + "--strict-config", + "--verbose", + "--cov=doi2dataset", + "--cov-report=term-missing", + "--cov-report=html", + "--cov-report=xml", + "--junit-xml=junit.xml", +] +markers = [ + "slow: marks tests as slow (deselect with '-m \"not slow\"')", + "integration: marks tests as integration tests", +] + +[tool.coverage.run] +source = ["doi2dataset"] +omit = ["tests/*", "setup.py", "docs/*", ".venv/*", "build/*", "dist/*"] + +[tool.coverage.report] +exclude_lines = [ + "pragma: no cover", + "def __repr__", + "if self.debug:", + "if settings.DEBUG", + "raise AssertionError", + "raise NotImplementedError", + "if 0:", + "if __name__ == .__main__.:", + "class .*\\bProtocol\\):", + "@(abc\\.)?abstractmethod", +] + +[tool.ruff] +line-length = 88 +target-version = "py310" +extend-exclude = [".venv", "build", "dist", "docs", ".pytest_cache", "htmlcov"] + +[tool.ruff.lint] +select = [ + "E", # pycodestyle errors + "W", # pycodestyle warnings + "F", # pyflakes + "I", # isort + "B", # flake8-bugbear + "C4", # flake8-comprehensions + "UP", # pyupgrade +] +ignore = [ + "E501", # line too long, handled by black + "B008", # do not perform function calls in argument defaults + "C901", # too complex +] + +[tool.ruff.lint.per-file-ignores] +"tests/*" = ["E501"] diff --git a/setup.py b/setup.py deleted file mode 100644 index 6ca8a0a..0000000 --- a/setup.py +++ /dev/null @@ -1,59 +0,0 @@ -import os - -from setuptools import find_packages, setup - -# Get the directory containing this file -here = os.path.abspath(os.path.dirname(__file__)) - -# Read the README file -readme_path = os.path.join(here, "README.md") -long_description = "" -if os.path.exists(readme_path): - with open(readme_path, encoding="utf-8") as f: - long_description = f.read() - -setup( - name="doi2dataset", - version="1.0", - description="A tool to process DOIs and generate metadata for Dataverse.org datasets.", - long_description=long_description, - long_description_content_type="text/markdown", - author="Alexander Minges", - author_email="alexander.minges@uni-due.de", - url="https://github.com/your_username/doi2dataset", - packages=find_packages(), - install_requires=[ - "dnspython>=2.7.0,<3.0.0", - "requests>=2.32.3,<2.33.0", - "PyYAML>=6.0,<7.0", - "email_validator>=2.2.0,<3.0.0", - "rich>=13.9.4,<14.0.0", - "idutils>=1.4.2,<2.0.0" - ], - extras_require={ - "docs": [ - "sphinx>=8.2.3,<9.0.0", - "sphinx_rtd_theme>=3.0,<4.0" - ], - "dev": [ - "pytest>=8.3.5,<9.0", - "pytest-mock>=3.14.0,<4.0", - "pytest-cov>=6.0.0,<7.0", - "ruff>=0.11.1,<0.20" - ] - }, - entry_points={ - "console_scripts": [ - "doi2dataset=doi2dataset:main" - ] - }, - classifiers=[ - "Programming Language :: Python :: 3", - "Operating System :: OS Independent", - "License :: OSI Approved :: MIT License", - "Development Status :: 4 - Beta", - "Intended Audience :: Developers", - "Topic :: Software Development :: Build Tools", - ], - python_requires='>=3.10', -)