diff --git a/.github/dependabot.yaml b/.github/dependabot.yaml new file mode 100644 index 0000000..bc63aca --- /dev/null +++ b/.github/dependabot.yaml @@ -0,0 +1,6 @@ +version: 2 +updates: + - package-ecosystem: 'github-actions' + directory: '/' + schedule: + interval: 'monthly' diff --git a/.github/workflows/ci.yaml b/.github/workflows/ci.yaml index 7d7b030..a381e3a 100644 --- a/.github/workflows/ci.yaml +++ b/.github/workflows/ci.yaml @@ -33,13 +33,15 @@ jobs: with: submodules: recursive - name: Create conda environment - uses: mamba-org/provision-with-micromamba@main + uses: mamba-org/setup-micromamba@v2 with: - cache-downloads: true - micromamba-version: 'latest' + micromamba-version: 'latest' # any version from https://github.com/mamba-org/micromamba-releases environment-file: ci/environment.yml - extra-specs: | + create-args: >- python=${{ matrix.python-version }} + post-cleanup: 'all' + cache-environment: true + cache-downloads: true - name: Install aerobulk-python run: | python -m pip install -e . --no-deps diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index 92b273e..2fea8bd 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -1,45 +1,42 @@ -name: Upload Python Package - +name: Build and Upload aerobulk-python to PyPI on: + push: + branches: + - "main" + pull_request: + branches: + - "*" release: - types: [created] + types: + - published jobs: - deploy: - if: github.repository == 'xgcm/aerobulk-python' + build-artifacts: runs-on: ubuntu-latest + if: github.repository == 'xgcm/aerobulk-python' steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 with: - submodules: recursive + fetch-depth: 0 - name: Set up Python - uses: actions/setup-python@v3 + uses: actions/setup-python@v5 with: - python-version: '3.11' + python-version: "3.11" - name: Install dependencies run: | python -m pip install --upgrade pip - pip install numpy setuptools setuptools-scm wheel twine - - name: Build tarball - run: python setup.py sdist - - name: Check dist - run: ls -la dist - - name: Check version - run: python setup.py --version - - name: Check built artifacts + python -m pip install --upgrade setuptools setuptools-scm build twine numpy + - name: Build only + if: github.event_name != 'release' run: | - python -m twine check dist/* - pwd - if [ -f dist/aerobulk-python-0.0.0.tar.gz ]; then - echo "❌ INVALID VERSION NUMBER" - exit 1 - else - echo "✅ Looks good" - fi - - name: Publish a Package to PyPI - uses: pypa/gh-action-pypi-publish@v1.5.0 - with: - user: __token__ - password: ${{ secrets.PYPI_API_TOKEN }} - verbose: true - verify_metadata: true + python -m build + twine check dist/* + - name: Build and publish + if: github.event_name == 'release' + env: + TWINE_USERNAME: "__token__" + TWINE_PASSWORD: ${{ secrets.PYPI_API_TOKEN }} + run: | + python -m build + twine check dist/* + twine upload dist/* diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 0000000..95a6044 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,68 @@ +[build-system] +requires = [ + "setuptools >= 61.0", + "setuptools-scm[toml] >= 6.2", + "wheel", + "numpy >= 1.20.0" +] +build-backend = "setuptools.build_meta" + +[project] +name = "aerobulk-python" +description = "General Circulation Model Postprocessing with xarray" +readme = "README.md" +license = {text = "GPLv3"} +authors = [ + {name = "aerobulk-python Developers", email = "julius@ldeo.columbia.edu"} +] +classifiers = [ + "Development Status :: 2 - Pre-Alpha", + "Intended Audience :: Science/Research", + "Topic :: Scientific/Engineering", + "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", + "Operating System :: OS Independent", + "Programming Language :: Python :: 3.8", + "Programming Language :: Python :: 3.9", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", +] +requires-python = ">=3.8,<3.12" +dependencies = [ + "numpy", +] +dynamic = ["version"] + +[project.urls] +Homepage = "https://github.com/xgcm/aerobulk-python" +Repository = "https://github.com/xgcm/aerobulk-python" + +[tool.setuptools] +package-dir = {"" = "source"} + +[tool.setuptools.packages.find] +where = ["source"] + +[tool.setuptools_scm] +write_to = "source/aerobulk/_version.py" +write_to_template = '__version__ = "{version}"' +tag_regex = '^(?Pv)?(?P[^\+]+)(?P.*)?$' + +# Tool configurations from setup.cfg +[tool.flake8] +exclude = ["**__init__.py", ".eggs", "doc"] +ignore = [ + # whitespace before ':' - doesn't work well with black + "E203", + "E402", + # line too long - let black worry about that + "E501", + # do not assign a lambda expression, use a def + "E731", + # line break before binary operator + "W503", + "E265", + "F811" +] + +[tool.pytest.ini_options] +testpaths = ["tests"] diff --git a/setup.cfg b/setup.cfg deleted file mode 100644 index 3c3793c..0000000 --- a/setup.cfg +++ /dev/null @@ -1,16 +0,0 @@ -[flake8] -exclude = __init__.py,.eggs,doc -ignore = - # whitespace before ':' - doesn't work well with black - E203 - E402 - # line too long - let black worry about that - E501 - # do not assign a lambda expression, use a def - E731 - # line break before binary operator - W503 - E265 - F811 -[tool:pytest] -testpaths = tests diff --git a/setup.py b/setup.py index 6894f37..01e5cfc 100644 --- a/setup.py +++ b/setup.py @@ -1,33 +1,15 @@ import os -# We need to import setuptools here in order for it to persist in sys.modules. -# Its presence/absence is used in subclassing setup in numpy/distutils/core.py. -# However, we need to run the distutils version of sdist, so import that first -# so that it is in sys.modules import numpy.distutils.command.sdist # noqa import setuptools # noqa from numpy.distutils.core import Extension, setup from numpy.distutils.fcompiler import get_default_fcompiler -# Trying this from the numpy setup.py - - -here = os.path.dirname(__file__) -with open(os.path.join(here, "README.md"), encoding="utf-8") as f: - long_description = f.read() - -install_requires = [ - "numpy", -] - # figure out which compiler we're going to use compiler = get_default_fcompiler() # set some fortran compiler-dependent flags f90flags = [] if compiler == "gnu95": - # f90flags.append('-fno-range-check') - # f90flags.append('-ffree-form') - # These are the flags I used in the manual version (might have some more here) f90flags.append("-fdefault-real-8") f90flags.append("-ffree-line-length-200") elif compiler == "intel" or compiler == "intelem": @@ -37,84 +19,55 @@ # Suppress all compiler warnings (avoid huge CI log files) f90flags.append("-w") -# for this API we will only expose a single extension? +# Extension modules ext_modules = [ Extension( name="mod_aerobulk_wrap_noskin", sources=[ - "./source/fortran/aerobulk/src/mod_const.f90", - "./source/fortran/aerobulk/src/mod_phymbl.f90", - "./source/fortran/aerobulk/src/mod_skin_coare.f90", - "./source/fortran/aerobulk/src/mod_skin_ecmwf.f90", - "./source/fortran/aerobulk/src/mod_blk_andreas.f90", - "./source/fortran/aerobulk/src/mod_common_coare.f90", - "./source/fortran/aerobulk/src/mod_blk_coare3p0.f90", - "./source/fortran/aerobulk/src/mod_blk_coare3p6.f90", - "./source/fortran/aerobulk/src/mod_blk_ecmwf.f90", - "./source/fortran/aerobulk/src/mod_blk_ncar.f90", - "./source/fortran/aerobulk/src/mod_blk_neutral_10m.f90", - "./source/fortran/aerobulk/src/mod_aerobulk_compute.f90", - "./source/fortran/aerobulk/src/mod_aerobulk.f90", - "./source/fortran/mod_aerobulk_wrap_noskin.f90", - "./source/fortran/mod_aerobulk_wrap_noskin.pyf", + "source/fortran/aerobulk/src/mod_const.f90", + "source/fortran/aerobulk/src/mod_phymbl.f90", + "source/fortran/aerobulk/src/mod_skin_coare.f90", + "source/fortran/aerobulk/src/mod_skin_ecmwf.f90", + "source/fortran/aerobulk/src/mod_blk_andreas.f90", + "source/fortran/aerobulk/src/mod_common_coare.f90", + "source/fortran/aerobulk/src/mod_blk_coare3p0.f90", + "source/fortran/aerobulk/src/mod_blk_coare3p6.f90", + "source/fortran/aerobulk/src/mod_blk_ecmwf.f90", + "source/fortran/aerobulk/src/mod_blk_ncar.f90", + "source/fortran/aerobulk/src/mod_blk_neutral_10m.f90", + "source/fortran/aerobulk/src/mod_aerobulk_compute.f90", + "source/fortran/aerobulk/src/mod_aerobulk.f90", + "source/fortran/mod_aerobulk_wrap_noskin.f90", + "source/fortran/mod_aerobulk_wrap_noskin.pyf", ], extra_f90_compile_args=f90flags, - # f2py_options=['--quiet'], ), Extension( name="mod_aerobulk_wrap_skin", sources=[ - "./source/fortran/aerobulk/src/mod_const.f90", - "./source/fortran/aerobulk/src/mod_phymbl.f90", - "./source/fortran/aerobulk/src/mod_skin_coare.f90", - "./source/fortran/aerobulk/src/mod_skin_ecmwf.f90", - "./source/fortran/aerobulk/src/mod_blk_andreas.f90", - "./source/fortran/aerobulk/src/mod_common_coare.f90", - "./source/fortran/aerobulk/src/mod_blk_coare3p0.f90", - "./source/fortran/aerobulk/src/mod_blk_coare3p6.f90", - "./source/fortran/aerobulk/src/mod_blk_ecmwf.f90", - "./source/fortran/aerobulk/src/mod_blk_ncar.f90", - "./source/fortran/aerobulk/src/mod_blk_neutral_10m.f90", - "./source/fortran/aerobulk/src/mod_aerobulk_compute.f90", - "./source/fortran/aerobulk/src/mod_aerobulk.f90", - "./source/fortran/mod_aerobulk_wrap_skin.f90", - "./source/fortran/mod_aerobulk_wrap_skin.pyf", + "source/fortran/aerobulk/src/mod_const.f90", + "source/fortran/aerobulk/src/mod_phymbl.f90", + "source/fortran/aerobulk/src/mod_skin_coare.f90", + "source/fortran/aerobulk/src/mod_skin_ecmwf.f90", + "source/fortran/aerobulk/src/mod_blk_andreas.f90", + "source/fortran/aerobulk/src/mod_common_coare.f90", + "source/fortran/aerobulk/src/mod_blk_coare3p0.f90", + "source/fortran/aerobulk/src/mod_blk_coare3p6.f90", + "source/fortran/aerobulk/src/mod_blk_ecmwf.f90", + "source/fortran/aerobulk/src/mod_blk_ncar.f90", + "source/fortran/aerobulk/src/mod_blk_neutral_10m.f90", + "source/fortran/aerobulk/src/mod_aerobulk_compute.f90", + "source/fortran/aerobulk/src/mod_aerobulk.f90", + "source/fortran/mod_aerobulk_wrap_skin.f90", + "source/fortran/mod_aerobulk_wrap_skin.pyf", ], extra_f90_compile_args=f90flags, f2py_options=["--quiet"], ), ] +# Minimal setup call - most configuration is now in pyproject.toml setup( - name="aerobulk-python", - description="General Circulation Model Postprocessing with xarray", - url="https://github.com/xgcm/aerobulk-python", - author="aerobulk-python Developers", - author_email="julius@ldeo.columbia.edu", - license="GPLv3", - classifiers=[ - "Development Status :: 2 - Pre-Alpha", - "Intended Audience :: Science/Research", - "Topic :: Scientific/Engineering", - "License :: OSI Approved :: GNU General Public License v3 (GPLv3)", - "Operating System :: OS Independent", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Programming Language :: Python :: 3.11", - ], - install_requires=install_requires, - python_requires=">=3.8, <3.12", - # long_description=long_description, - # long_description_content_type="text/x-rst", - setup_requires="setuptools_scm", - use_scm_version={ - "write_to": "source/aerobulk/_version.py", - "write_to_template": '__version__ = "{version}"', - "tag_regex": r"^(?Pv)?(?P[^\+]+)(?P.*)?$", - }, - package_dir={"": "source"}, - packages=["aerobulk"], - ext_package="aerobulk.aerobulk", + ext_package="aerobulk", ext_modules=ext_modules, )