diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 47e4305b..12266386 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -10,29 +10,25 @@ jobs: python-version: ["3.10", "3.11"] steps: - uses: actions/checkout@master - - uses: actions/setup-python@v5 - name: Setup Python ${{ matrix.python-version }} + - name: Install uv and set the python version ${{ matrix.python-version }} + uses: astral-sh/setup-uv@v5 with: python-version: ${{ matrix.python-version }} - name: Install system dependencies 📦 - run: sudo apt-get update && sudo apt-get install -y dh-python devscripts fakeroot debhelper python3-all python3-setuptools build-essential - - name: Install requirements 📦 - run: | - python3 -m pip install --upgrade pip - pip3 install -r requirements-dev.txt - - name: Install package 📦 - run: python3 setup.py install + run: sudo apt-get update && sudo apt-get install -y dh-python devscripts fakeroot debhelper python3-all python3-setuptools build-essential pybuild-plugin-pyproject + - name: Install dependencies and package 📦 + run: uv sync --extra dev - name: run tests ⚙️ - run: python3 setup.py test + run: uv run tests/run_tests.py - name: run test coverage ⚙️ run: | - coverage run --source pygeometa setup.py test - coverage report -m + uv run coverage run --source pygeometa tests/run_tests.py + uv run coverage report -m - name: build docs 🏗️ - run: mkdocs build -f docs/mkdocs.yml + run: uv run mkdocs build -f docs/mkdocs.yml - name: run flake8 ⚙️ - run: flake8 + run: uv run flake8 tests pygeometa - name: build Python package 🏗️ - run: python3 setup.py sdist bdist_wheel --universal + run: uv build - name: build Debian package 🏗️ run: sudo debuild -b -uc -us diff --git a/MANIFEST.in b/MANIFEST.in deleted file mode 100644 index 7b0e203e..00000000 --- a/MANIFEST.in +++ /dev/null @@ -1,4 +0,0 @@ -recursive-include pygeometa *.j2 *.yaml -include LICENSE.md -include README.md -include requirements.txt diff --git a/README.md b/README.md index 9e6dcf70..c62575f4 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,13 @@ cd my-env . bin/activate git clone https://github.com/geopython/pygeometa.git cd pygeometa -python3 setup.py build -python3 setup.py install +pip install . +``` +**Alternative**: using `uv` +```bash +git clone https://github.com/geopython/pygeometa.git +cd pygeometa +uv sync ``` ## Running @@ -120,7 +125,13 @@ Same as installing a package. Use a virtualenv. Also install developer requirements: ```bash -pip3 install -r requirements-dev.txt +pip3 install .[dev] +``` + +**Alternative**: using `uv` + +```bash +uv sync --extra dev ``` ### Adding a Metadata Schema to the Core @@ -163,11 +174,10 @@ vi pygeometa/schemas/foo/__init__.py ### Running Tests ```bash -# via setuptools -python3 setup.py test # manually -cd tests -python3 run_tests.py +python3 tests/run_tests.py +# using uv +uv run tests/run_tests.py ``` ## Releasing @@ -183,7 +193,7 @@ git tag -a x.y.z -m 'tagging release x.y.z' # push tag git push --tags rm -fr build dist *.egg-info -python3 setup.py sdist bdist_wheel --universal +python3 -m build twine upload dist/* ``` diff --git a/debian/control b/debian/control index 806b7ad4..42d38d50 100644 --- a/debian/control +++ b/debian/control @@ -6,7 +6,8 @@ Uploaders: Angelos Tzotsos Build-Depends: debhelper (>= 9), dh-python, python3-all, - python3-setuptools + python3-setuptools, + pybuild-plugin-pyproject Standards-Version: 4.3.0 Vcs-Git: https://github.com/geopython/pygeometa.git Homepage: https://geopython.github.io/pygeometa diff --git a/debian/rules b/debian/rules index c8d77302..c7d073cf 100755 --- a/debian/rules +++ b/debian/rules @@ -5,6 +5,7 @@ #export DH_VERBOSE=1 export PYBUILD_NAME=pygeometa +export PYBUILD_SYSTEM=pyproject %: dh $@ --with python3 --buildsystem pybuild diff --git a/pygeometa/core.py b/pygeometa/core.py index 328205ab..4b306dd7 100644 --- a/pygeometa/core.py +++ b/pygeometa/core.py @@ -50,7 +50,7 @@ import logging import os import pathlib -import pkg_resources +from importlib.metadata import version import re from typing import IO, Union from xml.dom import minidom @@ -70,7 +70,7 @@ SCHEMAS = pathlib.Path(__file__).resolve().parent / 'schemas' -VERSION = pkg_resources.require('pygeometa')[0].version +VERSION = version('pygeometa') def get_charstring(option: Union[str, dict], language: str, diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..fe9deb2c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,54 @@ +[project] +name = "pygeometa" +description = "pygeometa is a Python package to generate metadata for geospatial datasets" +readme = "README.md" +authors = [{ name = "Tom Kralidis", email = "tomkralidis@gmail.com" }] +maintainers = [{ name = "Tom Kralidis", email = "tomkralidis@gmail.com" }] +dependencies = ["Click", "Jinja2", "jsonschema", "lxml", "OWSLib", "pyyaml"] +license = "MIT" +license-files = [ + "LICENSE.md" +] +dynamic = ['version'] +classifiers = [ + 'Development Status :: 4 - Beta', + 'Environment :: Console', + 'Intended Audience :: Developers', + 'Intended Audience :: Science/Research', + 'Operating System :: OS Independent', + 'Programming Language :: Python', + 'Topic :: Scientific/Engineering :: GIS', +] +keywords = ["geospatial", "metadata", "catalogue", "discovery"] +requires-python = ">=3.10" + +[project.optional-dependencies] +dev = ["coverage", "setuptools>=77.0.3", "flake8", "mkdocs", "mkdocs-bootswatch", "twine", "wheel", "build"] + +[project.urls] +"Home page" = "https://geopython.github.io/pygeometa" + +[project.scripts] +pygeometa = "pygeometa:cli" + +[build-system] +requires = ["setuptools>=77.0.3", "wheel"] +build-backend = "setuptools.build_meta" + + +[tool.setuptools] +platforms = ["all"] + +[tool.setuptools.packages.find] +where = ["."] +include = [ + "pygeometa*" +] + + +[tool.setuptools.package-data] +pygeometa = ["*.j2", "*.yaml",] + + +[tool.setuptools.dynamic] +version = {attr = "pygeometa.__version__"} diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 2452fc50..00000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,6 +0,0 @@ -coverage -flake8 -mkdocs -mkdocs-bootswatch -twine -wheel diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index e9394a08..00000000 --- a/requirements.txt +++ /dev/null @@ -1,6 +0,0 @@ -Click -Jinja2 -jsonschema -lxml -OWSLib -pyyaml diff --git a/setup.py b/setup.py deleted file mode 100644 index 33b0a3c6..00000000 --- a/setup.py +++ /dev/null @@ -1,139 +0,0 @@ -# ================================================================= -# -# Terms and Conditions of Use -# -# Unless otherwise noted, computer program source code of this -# distribution # is covered under Crown Copyright, Government of -# Canada, and is distributed under the MIT License. -# -# The Canada wordmark and related graphics associated with this -# distribution are protected under trademark law and copyright law. -# No permission is granted to use them outside the parameters of -# the Government of Canada's corporate identity program. For -# more information, see -# http://www.tbs-sct.gc.ca/fip-pcim/index-eng.asp -# -# Copyright title to all 3rd party software distributed with this -# software is held by the respective copyright holders as noted in -# those files. Users are asked to read the 3rd Party Licenses -# referenced with those assets. -# -# Copyright (c) 2016 Government of Canada -# Copyright (c) 2025 Tom Kralidis -# -# Permission is hereby granted, free of charge, to any person -# obtaining a copy of this software and associated documentation -# files (the "Software"), to deal in the Software without -# restriction, including without limitation the rights to use, -# copy, modify, merge, publish, distribute, sublicense, and/or sell -# copies of the Software, and to permit persons to whom the -# Software is furnished to do so, subject to the following -# conditions: -# -# The above copyright notice and this permission notice shall be -# included in all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -# OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND -# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT -# HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, -# WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -# OTHER DEALINGS IN THE SOFTWARE. -# -# ================================================================= - -from pathlib import Path -from setuptools import Command, find_packages, setup -import re -import sys - - -class PyTest(Command): - user_options = [] - - def initialize_options(self): - pass - - def finalize_options(self): - pass - - def run(self): - import subprocess - errno = subprocess.call([sys.executable, 'tests/run_tests.py']) - raise SystemExit(errno) - - -def read(filename) -> str: - """read file contents""" - - fullpath = Path(__file__).resolve().parent / filename - - with fullpath.open() as fh: - contents = fh.read().strip() - - return contents - - -def get_package_version(): - """get version from top-level package init""" - - version_file = read('pygeometa/__init__.py') - version_match = re.search(r"^__version__ = ['\"]([^'\"]*)['\"]", - version_file, re.M) - if version_match: - return version_match.group(1) - - raise RuntimeError("Unable to find version string.") - - -LONG_DESCRIPTION = read('README.md') - -DESCRIPTION = 'pygeometa is a Python package to generate metadata for geospatial datasets' # noqa - -MANIFEST = Path('MANIFEST') - -if MANIFEST.exists(): - MANIFEST.unlink() - -setup( - name='pygeometa', - version=get_package_version(), - description=DESCRIPTION.strip(), - long_description=LONG_DESCRIPTION, - long_description_content_type='text/markdown', - license='MIT', - platforms='all', - keywords=' '.join([ - 'geospatial', - 'metadata', - 'catalogue', - 'discovery' - ]), - author='Tom Kralidis', - author_email='tomkralidis@gmail.com', - maintainer='Tom Kralidis', - maintainer_email='tomkralidis@gmail.com', - url='https://geopython.github.io/pygeometa', - install_requires=read('requirements.txt').splitlines(), - packages=find_packages(), - include_package_data=True, - entry_points={ - 'console_scripts': [ - 'pygeometa=pygeometa:cli' - ] - }, - classifiers=[ - 'Development Status :: 4 - Beta', - 'Environment :: Console', - 'Intended Audience :: Developers', - 'Intended Audience :: Science/Research', - 'License :: OSI Approved :: MIT License', - 'Operating System :: OS Independent', - 'Programming Language :: Python', - 'Topic :: Scientific/Engineering :: GIS' - ], - cmdclass={'test': PyTest}, - test_suite='tests.run_tests' -)