diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index e051f467..565b221e 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -38,7 +38,7 @@ jobs: - uses: conda-incubator/setup-miniconda@v2 with: auto-update-conda: true - python-version: 3.9 + python-version: 3.12 channels: conda-forge channel-priority: true diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml index 7c719fae..5ac6b4ab 100644 --- a/.github/workflows/lint.yml +++ b/.github/workflows/lint.yml @@ -16,10 +16,10 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - name: Set up Python 3.9 + - name: Set up Python 3.12 uses: actions/setup-python@v2 with: - python-version: 3.9 + python-version: 3.12 - name: Lint run: | diff --git a/.github/workflows/test-cli.yml b/.github/workflows/test-cli.yml new file mode 100644 index 00000000..cb3a1f76 --- /dev/null +++ b/.github/workflows/test-cli.yml @@ -0,0 +1,43 @@ +name: Test CLI + +on: [push, pull_request] + +jobs: + test-cli: + # We want to run on external PRs, but not on our own internal PRs as they'll be run + # by the push to the branch. Without this if check, checks are duplicated since + # internal PRs match both the push and pull_request events. + if: + github.event_name == 'push' || github.event.pull_request.head.repo.full_name != + github.repository + + runs-on: ${{ matrix.os }} + + defaults: + run: + shell: bash -l {0} + + strategy: + fail-fast: false + matrix: + os: [ubuntu-latest, macos-latest] + python-version: ["3.10", "3.11", "3.12"] + + steps: + - uses: actions/checkout@v3 + with: + submodules: true + - name: Set up Python ${{ matrix.python-version }} + uses: actions/setup-python@v4 + with: + python-version: ${{ matrix.python-version }} + + - name: Install dependencies + run: python -m pip install nox tomli + + - name: Run the tests + run: nox --session test test-cli --python ${{ matrix.python-version }} --verbose + + - name: Coveralls + if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9' + uses: AndreMiras/coveralls-python-action@v20201129 diff --git a/.github/workflows/build-test-ci.yml b/.github/workflows/test-langs.yml similarity index 71% rename from .github/workflows/build-test-ci.yml rename to .github/workflows/test-langs.yml index a52b5c9e..2b32dd0e 100644 --- a/.github/workflows/build-test-ci.yml +++ b/.github/workflows/test-langs.yml @@ -1,9 +1,9 @@ -name: Build/Test CI +name: Test languages on: [push, pull_request] jobs: - build-and-test: + test-langs: # We want to run on external PRs, but not on our own internal PRs as they'll be run # by the push to the branch. Without this if check, checks are duplicated since # internal PRs match both the push and pull_request events. @@ -18,18 +18,16 @@ jobs: shell: bash -l {0} strategy: + fail-fast: false matrix: os: [ubuntu-latest, macos-latest] - python-version: ["3.9", "3.10"] + python-version: ["3.10", "3.11", "3.12"] + language: ["c", "cxx", "python", "fortran"] steps: - uses: actions/checkout@v3 with: submodules: true - - name: Set up Python ${{ matrix.python-version }} - uses: actions/setup-python@v4 - with: - python-version: ${{ matrix.python-version }} - uses: conda-incubator/setup-miniconda@v2 with: @@ -43,13 +41,10 @@ jobs: run: python -m pip install nox tomli - name: Install compilers - run: mamba install c-compiler cxx-compiler fortran-compiler cmake - - - name: Run the tests - run: nox --session test test-cli --python ${{ matrix.python-version }} --verbose + run: mamba install c-compiler cxx-compiler fortran-compiler - name: Run the language tests - run: nox --non-interactive --error-on-missing-interpreter --session test-langs --python ${{ matrix.python-version }} --verbose + run: nox -s "test-langs-${{ matrix.python-version }}(lang='${{ matrix.language }}')" --python ${{ matrix.python-version }} --verbose - name: Coveralls if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.9' diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index cd8f9928..170e3ef5 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/psf/black - rev: 22.3.0 + rev: 24.2.0 hooks: - id: black name: black @@ -25,7 +25,7 @@ repos: exclude: ^babelizer/data - repo: https://github.com/pycqa/flake8 - rev: 4.0.1 + rev: 7.0.0 hooks: - id: flake8 additional_dependencies: @@ -35,21 +35,21 @@ repos: exclude: ^babelizer/data - repo: https://github.com/asottile/pyupgrade - rev: v2.34.0 + rev: v3.15.1 hooks: - id: pyupgrade - args: [--py38-plus] + args: [--py310-plus] exclude: ^babelizer/data - repo: https://github.com/PyCQA/isort - rev: 5.10.1 + rev: 5.13.2 hooks: - id: isort files: \.py$ exclude: ^babelizer/data - repo: https://github.com/pre-commit/pre-commit-hooks - rev: v4.3.0 + rev: v4.5.0 hooks: - id: check-builtin-literals exclude: ^babelizer/data @@ -66,7 +66,7 @@ repos: - id: trailing-whitespace - repo: https://github.com/PyCQA/pydocstyle - rev: 6.1.1 + rev: 6.3.0 hooks: - id: pydocstyle files: babelizer/.*\.py$ @@ -77,7 +77,7 @@ repos: additional_dependencies: [".[toml]"] - repo: https://github.com/pre-commit/mirrors-mypy - rev: v0.982 + rev: v1.8.0 hooks: - id: mypy additional_dependencies: [types-all] diff --git a/babelizer/__init__.py b/babelizer/__init__.py index 78120efc..546781d0 100644 --- a/babelizer/__init__.py +++ b/babelizer/__init__.py @@ -1,4 +1,5 @@ """The *babelizer*.""" + from ._version import __version__ __all__ = ["__version__"] diff --git a/babelizer/cli.py b/babelizer/cli.py index a85bd3dd..a408e6b8 100644 --- a/babelizer/cli.py +++ b/babelizer/cli.py @@ -1,13 +1,20 @@ """The command line interface to the babelizer.""" + import fnmatch import os import pathlib +import sys import tempfile from functools import partial import click import git -import pkg_resources + +if sys.version_info >= (3, 12): # pragma: no cover (PY12+) + import importlib.resources as importlib_resources +else: # pragma: no cover (= (3, 12): # pragma: no cover (PY12+) + import importlib.resources as importlib_resources +else: # pragma: no cover (= (3, 12): # pragma: no cover (PY12+) + import importlib.resources as importlib_resources +else: # pragma: no cover ( None: build_examples(session, lang) - session.conda_install("pip", "bmi-tester>=0.5.4") + session.conda_install("pip", "bmi-tester>=0.5.4", "cmake") session.install(".[testing]") with session.chdir(tmpdir): diff --git a/pyproject.toml b/pyproject.toml index 9a988b3f..7ebf617c 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,111 +1,159 @@ -[build-system] -requires = ["setuptools", "wheel"] -build-backend = "setuptools.build_meta" - [project] name = "babelizer" +requires-python = ">=3.10" description = "Wrap BMI libraries with Python bindings" +keywords = [ + "bmi", + "component modeling", + "geosciences", + "interoperability", + "model coupling", + "numerical modeling", + "pymt", +] authors = [ - {name = "Eric Hutton", email = "huttone@colorado.edu"}, + { name = "Eric Hutton", email = "huttone@colorado.edu" }, ] maintainers = [ - {name = "Eric Hutton", email = "huttone@colorado.edu"}, - {name = "Mark Piper", email = "mark.piper@colorado.edu"}, + { name = "Eric Hutton", email = "huttone@colorado.edu" }, + { name = "Mark Piper", email = "mark.piper@colorado.edu" }, ] -keywords = [ - "bmi", - "component modeling", - "geosciences", - "interoperability", - "model coupling", - "numerical modeling", - "pymt", -] -license = {text = "MIT License"} classifiers = [ - "Development Status :: 4 - Beta", - "Intended Audience :: Developers", - "Intended Audience :: Science/Research", - "License :: OSI Approved :: MIT License", - "Operating System :: MacOS :: MacOS X", - "Operating System :: POSIX :: Linux", - "Programming Language :: Python :: 3 :: Only", - "Programming Language :: Python :: 3.8", - "Programming Language :: Python :: 3.9", - "Programming Language :: Python :: 3.10", - "Topic :: Software Development :: Code Generators", -] -requires-python = ">=3.8" + "Development Status :: 4 - Beta", + "Intended Audience :: Developers", + "Intended Audience :: Science/Research", + "License :: OSI Approved :: MIT License", + "Operating System :: MacOS :: MacOS X", + "Operating System :: POSIX :: Linux", + "Programming Language :: Python :: 3 :: Only", + "Programming Language :: Python :: 3.10", + "Programming Language :: Python :: 3.11", + "Programming Language :: Python :: 3.12", + "Topic :: Software Development :: Code Generators", +] dependencies = [ - "black", - "click", - "gitpython", - "pyyaml", - "tomlkit", - "isort>=5", - "cookiecutter", + "black", + "click", + "cookiecutter", + "gitpython", + "importlib-resources; python_version < '3.12'", + "isort>=5", + "pyyaml", + "tomlkit", ] -dynamic = ["readme", "version"] +dynamic = [ + "readme", + "version", +] + +[project.license] +text = "MIT" [project.urls] -homepage = "https://babelizer.readthedocs.io/" +changelog = "https://github.com/csdms/babelizer/blob/master/CHANGES.rst" documentation = "https://babelizer.readthedocs.io/" +homepage = "https://babelizer.readthedocs.io/" repository = "https://github.com/csdms/babelizer" -changelog = "https://github.com/csdms/babelizer/blob/master/CHANGES.rst" [project.optional-dependencies] dev = [ - "black", - "flake8", - "flake8-bugbear", - "isort", - "nox", - "pre-commit", - "towncrier", + "black", + "flake8", + "flake8-bugbear", + "isort", + "nox", + "pre-commit", + "towncrier", ] docs = [ - "sphinx>=4", - "sphinx-click", - "sphinx-copybutton", - "sphinx-inline-tabs", - "sphinxcontrib.towncrier", - "pygments>=2.4", - "sphinx-inline-tabs", - "furo", + "furo", + "pygments>=2.4", + "sphinx-click", + "sphinx-copybutton", + "sphinx-inline-tabs", + "sphinx-inline-tabs", + "sphinx>=4", + "sphinxcontrib.towncrier", ] testing = [ - "pytest", - "pytest-cov", - "pytest-datadir", - "pytest-xdist", - "coverage[toml]", - "coveralls", + "coverage[toml]", + "coveralls", + "pytest", + "pytest-cov", + "pytest-datadir", + "pytest-xdist", ] [project.scripts] babelize = "babelizer.cli:babelize" +[build-system] +requires = [ + "setuptools", + "wheel", +] +build-backend = "setuptools.build_meta" + [tool.setuptools] include-package-data = true +[tool.setuptools.dynamic.readme] +file = "README.rst" +content-type = "text/x-rst" + +[tool.setuptools.dynamic.version] +attr = "babelizer._version.__version__" + [tool.setuptools.package-data] babelizer = [ - "data/*", + "data/*", ] [tool.setuptools.packages.find] -where = ["."] -include = ["babelizer*"] +where = [ + ".", +] +include = [ + "babelizer*", +] -[tool.setuptools.dynamic] -readme = {file = ["README.rst", "CREDITS.rst", "CHANGES.rst", "LICENSE.rst"]} -version = {attr = "babelizer._version.__version__"} +[tool.black] +line-length = 88 +exclude = """ +( + babelizer/data + | external +) +""" + +[tool.coverage.run] +omit = [ + "*/babelizer/data/*", +] +relative_files = true + +[tool.isort] +multi_line_output = 3 +include_trailing_comma = true +force_grid_wrap = 0 +combine_as_imports = true +line_length = 88 +skip = [ + "babelizer/data", +] [tool.pytest.ini_options] minversion = "6.0" -testpaths = ["babelizer", "tests"] -norecursedirs = [".*", "*.egg*", "build", "dist"] -# usefixtures = suppress_resource_warning +testpaths = [ + "babelizer", + "tests", +] +norecursedirs = [ + ".*", + "*.egg*", + "build", + "dist", +] addopts = """ --ignore setup.py --ignore babelizer/data @@ -118,26 +166,9 @@ addopts = """ doctest_optionflags = [ "NORMALIZE_WHITESPACE", "IGNORE_EXCEPTION_DETAIL", - "ALLOW_UNICODE" + "ALLOW_UNICODE", ] -[tool.isort] -multi_line_output = 3 -include_trailing_comma = true -force_grid_wrap = 0 -combine_as_imports = true -line_length = 88 -skip = ["babelizer/data"] - -[tool.black] -line-length = 88 -exclude = ''' -( - babelizer/data - | external -) -''' - [tool.towncrier] directory = "news" package = "babelizer" @@ -147,3 +178,7 @@ underlines = "-^\"" issue_format = "`#{issue} `_" title_format = "{version} ({project_date})" wrap = true + +[tool.zest-releaser] +tag-format = "v{version}" +python-file-with-version = "babelizer/_version.py" diff --git a/requirements.py b/requirements.py index dbe42cd7..f7b8d501 100755 --- a/requirements.py +++ b/requirements.py @@ -22,9 +22,9 @@ def requirements(extras): if extras: optional_dependencies = project.get("optional-dependencies", {}) for extra in extras: - dependencies[ - f"[project.optional-dependencies.{extra}]" - ] = optional_dependencies[extra] + dependencies[f"[project.optional-dependencies.{extra}]"] = ( + optional_dependencies[extra] + ) else: dependencies["[project.dependencies]"] = project["dependencies"] diff --git a/setup.cfg b/setup.cfg index 911da7e0..23f551ef 100644 --- a/setup.cfg +++ b/setup.cfg @@ -5,11 +5,3 @@ ignore = E501 W503 max-line-length = 88 - -[zest.releaser] -tag-format = v{version} -python-file-with-version = babelizer/_version.py - -[coverage:run] -omit = */babelizer/data/* -relative_files = True diff --git a/tests/test_cli.py b/tests/test_cli.py index ba9d3512..eec00562 100644 --- a/tests/test_cli.py +++ b/tests/test_cli.py @@ -1,4 +1,5 @@ """Test the babelizer command-line interface""" + from click.testing import CliRunner from babelizer.cli import babelize