From e6d8f4b61a0d88c1c7fd40304c90184c8ba84c02 Mon Sep 17 00:00:00 2001 From: Tyler Sutterley Date: Fri, 23 Aug 2024 15:56:11 -0700 Subject: [PATCH] refactor: modernize build with `pyproject.toml` (#322) --- .dockerignore | 35 --------- .github/workflows/python-publish.yml | 4 +- .github/workflows/python-request.yml | 2 +- MANIFEST.in | 1 + postBuild | 3 - pyproject.toml | 102 ++++++++++++++++++++++++++- requirements-dev.txt | 6 -- requirements.txt | 8 --- setup.cfg | 27 ------- setup.py | 89 +---------------------- 10 files changed, 106 insertions(+), 171 deletions(-) delete mode 100644 .dockerignore delete mode 100644 postBuild delete mode 100644 requirements-dev.txt delete mode 100644 requirements.txt delete mode 100644 setup.cfg diff --git a/.dockerignore b/.dockerignore deleted file mode 100644 index 0d888ac2..00000000 --- a/.dockerignore +++ /dev/null @@ -1,35 +0,0 @@ -# Python Build # -################ -__pycache__ -build/ -dist/ -develop-eggs/ -run/ -wheels/ -*.egg-info/ -.installed.cfg -*.egg -.pytest_cache -pythonenv*/ -setup.cfg -# Jupyter # -########### -notebooks/ -.ipynb_checkpoints -Untitled.ipynb -# Documentation # -################# -requirements-dev.txt -environment.yml -readthedocs.yml -codecov.yml -postBuild -test/ -doc/ -# OS generated files # -###################### -.DS_Store -.DS_Store? -._* -.Spotlight-V100 -.Trashes diff --git a/.github/workflows/python-publish.yml b/.github/workflows/python-publish.yml index 2c2e5b03..c465018e 100644 --- a/.github/workflows/python-publish.yml +++ b/.github/workflows/python-publish.yml @@ -21,12 +21,12 @@ jobs: - name: Install dependencies run: | python -m pip install --upgrade pip - pip install setuptools wheel twine + pip install build setuptools wheel twine - name: Build and publish env: TWINE_USERNAME: ${{ secrets.PYPI_USERNAME }} TWINE_PASSWORD: ${{ secrets.PYPI_PASSWORD }} run: | - python setup.py sdist bdist_wheel + python -m build twine upload dist/* diff --git a/.github/workflows/python-request.yml b/.github/workflows/python-request.yml index 5fafb7f2..78564310 100644 --- a/.github/workflows/python-request.yml +++ b/.github/workflows/python-request.yml @@ -37,6 +37,7 @@ jobs: post-cleanup: 'all' create-args: >- blas + boto3 python=${{ matrix.python-version }} flake8 pytest @@ -62,7 +63,6 @@ jobs: - name: Test with pytest run: | pip install --no-deps . - if [ -f requirements-dev.txt ]; then pip install -r requirements-dev.txt; fi pytest --verbose --capture=no --cov=./ --cov-report=xml \ --username=${{ secrets.EARTHDATA_USERNAME }} \ --password=${{ secrets.EARTHDATA_PASSWORD }} \ diff --git a/MANIFEST.in b/MANIFEST.in index af7f5e3c..437b119e 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -2,6 +2,7 @@ graft pyTMD/data prune .github* prune doc* prune notebooks* +prune run* prune test* exclude *.cfg exclude *.yml diff --git a/postBuild b/postBuild deleted file mode 100644 index 52fffdbc..00000000 --- a/postBuild +++ /dev/null @@ -1,3 +0,0 @@ -jupyter labextension install --clean @jupyter-widgets/jupyterlab-manager \ - jupyter-matplotlib jupyter-leaflet -pip install -e . diff --git a/pyproject.toml b/pyproject.toml index 1d4dd3b6..bde78e23 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,3 +1,103 @@ [build-system] -requires = ["setuptools", "setuptools_scm"] +requires = ["setuptools>=64", "setuptools_scm>=8"] build-backend = "setuptools.build_meta" + +[project] +name = "pyTMD" +description = "Tide Model Driver to read OTIS, ATLAS, GOT and FES formatted tidal solutions and make tidal predictions" +keywords = [ + "Ocean Tides", + "Load Tides", + "Pole Tides", + "Solid Earth Tides", + "Tidal Prediction", +] +authors = [ + {name = "Tyler Sutterley"}, + {name = "Karen Alley"}, + {name = "Kelly Brunt"}, + {name = "Susan Howard"}, + {name = "Laurie Padman"}, + {name = "Matt Siegfried"}, + {email = "tsutterl@uw.edu"} +] +maintainers = [{ name = "pyTMD contributors" }] +license = {file = "LICENSE"} +readme = "README.rst" + +requires-python = "~=3.6" +dependencies = [ + "lxml", + "netCDF4", + "numpy", + "pyproj", + "python-dateutil", + "scipy>=1.10.1", + "setuptools_scm", + "timescale>=0.0.3", +] + +dynamic = ["version"] + +classifiers=[ + "Development Status :: 3 - Alpha", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3", + "Programming Language :: Python :: 3.6", + "Programming Language :: Python :: 3.7", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Scientific/Engineering :: Physics", +] + +[project.urls] +Homepage = "https://pyTMD.readthedocs.io" +Documentation = "https://pyTMD.readthedocs.io" +Repository = "https://github.com/tsutterley/pyTMD" +Issues = "https://github.com/tsutterley/pyTMD/issues" + +[project.optional-dependencies] +doc = ["docutils", "fontconfig", "freetype", "graphviz", "numpydoc", "sphinx", "sphinx-argparse>=0.4", "sphinx_rtd_theme"] +all = ["cartopy", "gdal", "h5py", "ipyleaflet", "ipywidgets", "jplephem", "matplotlib", "mpi4py", "notebook", "pandas", "pyyaml"] +dev = ["flake8", "pytest>=4.6", "pytest-cov", "oct2py", "boto3"] + +[tool.setuptools.packages.find] +exclude = ["test*", "run*"] + +[tool.pytest.ini_options] +minversion = "6.0" +norecursedirs = ".git" +python_files = [ + "test*.py" +] +testpaths = [ + "test" +] + +[tool.coverage.run] +branch = true +source = [ + "pyTMD", + "test", +] +omit = [ + "setup.py", + "conf.py", + "scripts/*", + "pyTMD/calc_astrol_longitudes.py", + "pyTMD/compute_tide_corrections.py", + "pyTMD/convert_crs.py", + "pyTMD/convert_ll_xy.py", + "pyTMD/load_constituent.py", + "pyTMD/load_nodal_corrections.py", + "test/def_to_json.py", +] + +[tool.coverage.report] +show_missing = true +precision = 2 diff --git a/requirements-dev.txt b/requirements-dev.txt deleted file mode 100644 index 64efd58d..00000000 --- a/requirements-dev.txt +++ /dev/null @@ -1,6 +0,0 @@ -flake8 -pytest>=4.6 -pytest-cov -numpy -oct2py -boto3 diff --git a/requirements.txt b/requirements.txt deleted file mode 100644 index 9a6b6d3a..00000000 --- a/requirements.txt +++ /dev/null @@ -1,8 +0,0 @@ -lxml -netCDF4 -numpy -pyproj -python-dateutil -scipy>=1.10.1 -setuptools_scm -timescale>=0.0.3 diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 9a449e3b..00000000 --- a/setup.cfg +++ /dev/null @@ -1,27 +0,0 @@ -[tool:pytest] -minversion = 2.0 -norecursedirs = .git -python_files = test*.py -testpaths = - test - -[coverage:run] -branch = true -source = - pyTMD - test -omit = - setup.py - conf.py - scripts/* - pyTMD/calc_astrol_longitudes.py - pyTMD/compute_tide_corrections.py - pyTMD/convert_crs.py - pyTMD/convert_ll_xy.py - pyTMD/load_constituent.py - pyTMD/load_nodal_corrections.py - test/def_to_json.py - -[coverage:report] -show_missing = true -precision = 2 diff --git a/setup.py b/setup.py index d4a24828..cf8f6251 100644 --- a/setup.py +++ b/setup.py @@ -1,29 +1,5 @@ import os -import sys -import logging -import subprocess -from setuptools import setup, find_packages - -logging.basicConfig(stream=sys.stderr, level=logging.INFO) -log = logging.getLogger() - -# package description and keywords -description = ('Tide Model Driver to read OTIS, ATLAS, GOT and FES ' - 'formatted tidal solutions and make tidal predictions') -keywords = 'Ocean Tides, Load Tides, Pole Tides, Tidal Prediction, OTIS, GOT, FES' -# get long_description from README.rst -with open('README.rst', mode='r', encoding='utf8') as fh: - long_description = fh.read() -long_description_content_type = "text/x-rst" - -# install requirements and dependencies -on_rtd = os.environ.get('READTHEDOCS') == 'True' -if on_rtd: - install_requires = [] -else: - # get install requirements - with open('requirements.txt', mode='r', encoding='utf8') as fh: - install_requires = [line.split().pop(0) for line in fh.read().splitlines()] +from setuptools import setup # get version with open('version.txt', mode='r', encoding='utf8') as fh: @@ -32,45 +8,6 @@ # list of all scripts to be included with package scripts=[os.path.join('scripts',f) for f in os.listdir('scripts') if f.endswith('.py')] -# run cmd from the command line -def check_output(cmd): - return subprocess.check_output(cmd).decode('utf') - -# check if GDAL is installed -gdal_output = [None] * 4 -try: - for i, flag in enumerate(("--cflags", "--libs", "--datadir", "--version")): - gdal_output[i] = check_output(['gdal-config', flag]).strip() -except Exception as exc: - log.warning('Failed to get options via gdal-config') -else: - log.info(f"GDAL version from via gdal-config: {gdal_output[3]}") -# if setting GDAL version from via gdal-config -if gdal_output[3] and ('gdal' in install_requires): - # add version information to gdal in install_requires - gdal_index = install_requires.index('gdal') - install_requires[gdal_index] = f'gdal=={gdal_output[3]}' -elif any(install_requires) and ('gdal' in install_requires): - # gdal version not found - gdal_index = install_requires.index('gdal') - install_requires.pop(gdal_index) - -# check if HDF5 is installed -hdf5_output = [None] * 2 -try: - for i, cmd in enumerate((["h5cc","-showconfig"], ["h5dump","--version"])): - hdf5_output[i] = check_output(cmd).strip() - # parse HDF5 version from h5dump - hdf5_version = hdf5_output[1].split().pop(2) -except Exception as exc: - log.warning('Failed to get HDF5 options') -else: - log.info(f"HDF5 version from via h5dump: {hdf5_version}") -# if the HDF5 version not found -if not any(hdf5_output) and ('h5py' in install_requires): - hdf5_index = install_requires.index('h5py') - install_requires.pop(hdf5_index) - # semantic version configuration for setuptools-scm setup_requires = ["setuptools_scm"] use_scm_version = { @@ -82,30 +19,6 @@ def check_output(cmd): setup( name='pyTMD', - description=description, - long_description=long_description, - long_description_content_type=long_description_content_type, - url='https://github.com/tsutterley/pyTMD', - author='Tyler Sutterley', - author_email='tsutterl@uw.edu', - license='MIT', - classifiers=[ - 'Development Status :: 3 - Alpha', - 'Intended Audience :: Science/Research', - 'Topic :: Scientific/Engineering :: Physics', - 'License :: OSI Approved :: MIT License', - 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.6', - 'Programming Language :: Python :: 3.7', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', - 'Programming Language :: Python :: 3.10', - ], - keywords=keywords, - packages=find_packages(), - install_requires=install_requires, - setup_requires=setup_requires, use_scm_version=use_scm_version, scripts=scripts, - include_package_data=True, )