Skip to content

Commit

Permalink
Merge branch 'main' into ruff
Browse files Browse the repository at this point in the history
* main:
  [pre-commit.ci] pre-commit autoupdate (SciTools#425)
  Adopt cython3 (require >=3) (SciTools#460)
  Add repo-review (SciTools#456)
  Fully support Python 3.12 (SciTools#461)
  Bump peter-evans/create-pull-request from 6.0.4 to 7.0.5 (SciTools#459)
  Fix for bad git path in GHA macos instances. (SciTools#464)
  test macos wheels (SciTools#458)
  Bump pypa/cibuildwheel from 2.20.0 to 2.21.1 (SciTools#457)
  Fixes for CI wheels (SciTools#455)
  Dependabot check weekly. (SciTools#439)

# Conflicts:
#	.pre-commit-config.yaml
#	cf_units/tests/test_coding_standards.py
#	pyproject.toml
  • Loading branch information
stephenworsley committed Sep 24, 2024
2 parents 23c47fb + cc0ea12 commit 47592b4
Show file tree
Hide file tree
Showing 24 changed files with 979 additions and 805 deletions.
8 changes: 6 additions & 2 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,12 @@ updates:
- package-ecosystem: "github-actions"
directory: "/"
schedule:
# Check for updates to GitHub Actions every weekday
interval: "daily"
# Check later in the week - the upstream dependabot check in `workflows` runs deliberately early in the week.
# Therefore allowing time for the `workflows` update to be merged-and-released first.
interval: "weekly"
day: "thursday"
time: "01:00"
timezone: "Europe/London"
labels:
- "New: Pull Request"
- "Bot"
6 changes: 3 additions & 3 deletions .github/workflows/ci-locks.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
ENV_NAME: "ci-locks"
strategy:
matrix:
lock: [py39-lock, py310-lock, py311-lock]
lock: [py310-lock, py311-lock, py312-lock]
steps:
- name: "Checkout"
uses: actions/checkout@v4
Expand All @@ -54,7 +54,7 @@ jobs:
miniforge-version: latest
channels: conda-forge,defaults
activate-environment: ${{ env.ENV_NAME }}
auto-update-conda: true
auto-update-conda: true
use-only-tar-bz2: true

- name: "Conda environment cache"
Expand Down Expand Up @@ -122,7 +122,7 @@ jobs:
- name: "Push pull-request"
id: cpr
# v3.12.1 (release date 31 Jan 2022)
uses: peter-evans/create-pull-request@9153d834b60caba6d51c9b9510b087acf9f33f83
uses: peter-evans/create-pull-request@5e914681df9dc83aa4e4905692ca88beb2f9e91f
with:
token: ${{ steps.generate-token.outputs.token }}
add-paths: ${{ github.workspace }}/requirements/locks/*.txt
Expand Down
15 changes: 12 additions & 3 deletions .github/workflows/ci-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,26 @@ jobs:
strategy:
matrix:
os: [ubuntu-latest]
version: [py39, py310, py311]
version: [py310, py311, py312]
gitpath-prepend: [""]
include:
- os: ubuntu-latest
platform: linux
- os: ubuntu-latest
version: py311
version: py312
posargs: "--cov-report=xml --cov"
post-command: codecov
- os: macos-latest
version: py311
version: py312
platform: osx
# On macos, the up-to-date git may not be first on the path
# N.B. setting includes a final ":", to simplify the path setting command
gitpath-prepend: "/opt/homebrew/bin:"
steps:
- name: "Checkout"
uses: actions/checkout@v4
with:
fetch-depth: 0

- name: "Environment configure"
env:
Expand Down Expand Up @@ -106,4 +112,7 @@ jobs:
env:
POST_COMMAND: ${{ matrix.post-command }}
run: |
export PATH=${{ matrix.gitpath-prepend }}$PATH
which git
git --version
tox -e ${{ matrix.version }}-${{ matrix.platform }}-test -- ${{ matrix.posargs }}
26 changes: 20 additions & 6 deletions .github/workflows/ci-wheels.yml
Original file line number Diff line number Diff line change
Expand Up @@ -20,45 +20,59 @@ on:
- "pre-commit-ci-update-config"
- "dependabot/*"

workflow_dispatch:

concurrency:
group: ${{ github.workflow }}-${{ github.ref }}
cancel-in-progress: true

jobs:
build_bdist:
name: "Build ${{ matrix.os }} (${{ matrix.arch }}) wheels"
# TBD: extend to support windows
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
# TBD: extend to support windows
os: ["ubuntu-latest", "macos-11", "macos-14"]
os: ["ubuntu-latest", "macos-latest", "macos-13"]
arch: ["x86_64", "arm64"]
include:
- os: ubuntu-latest
arch: x86_64
incdir: /usr/include/udunits2
libdir: /usr/lib64
xml_path: /usr/share/udunits/udunits2.xml
- os: macos-11
- os: macos-13
arch: x86_64
incdir: /usr/local/Cellar/udunits/2.2.28/include
libdir: /usr/local/Cellar/udunits/2.2.28/lib
xml_path: /usr/local/Cellar/udunits/2.2.28/share/udunits/udunits2-common.xml
- os: macos-14
- os: macos-latest
arch: arm64
incdir: /opt/homebrew/Cellar/udunits/2.2.28/include
libdir: /opt/homebrew/Cellar/udunits/2.2.28/lib
xml_path: /opt/homebrew/Cellar/udunits/2.2.28/share/udunits/udunits2-common.xml
exclude:
- os: "ubuntu-latest"
arch: "arm64"
- os: "macos-latest"
arch: "x86_64"
- os: "macos-13"
arch: "arm64"

steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0

- name: "Set MACOSX_DEPLOYMENT_TARGET"
if: startsWith(matrix.os, 'macos')
run: echo "MACOSX_DEPLOYMENT_TARGET=$([[ ${{ matrix.os }} == 'macos-latest' ]] && echo '14.0' || echo '13.0')" >> $GITHUB_ENV

- name: "Building ${{ matrix.os }} (${{ matrix.arch }}) wheels"
uses: pypa/cibuildwheel@v2.16.5
uses: pypa/cibuildwheel@v2.21.1
env:
CIBW_SKIP: "cp36-* cp37-* cp38-* cp312-* pp* *-musllinux*"
CIBW_SKIP: "cp39-* cp313-* pp* *-musllinux*"
CIBW_ARCHS: ${{ matrix.arch }}
CIBW_BUILD_FRONTEND: build
CIBW_MANYLINUX_X86_64_IMAGE: manylinux2014
Expand Down
8 changes: 8 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
# See https://pre-commit.com for more information
# See https://pre-commit.com/hooks.html for more hooks
# See https://github.com/scientific-python/cookie#sp-repo-review for repo-review

repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
Expand All @@ -24,6 +25,13 @@ repos:
- id: sort-all
types: [file, python]

- repo: https://github.com/scientific-python/cookie
rev: 2024.08.19
hooks:
- id: sp-repo-review
additional_dependencies: ["repo-review[cli]"] # TODO: Only neededed if extra dependencies are required
#args: ["--show=errskip"] # show everything for the moment

- repo: https://github.com/astral-sh/ruff-pre-commit
rev: "v0.1.5"
hooks:
Expand Down
3 changes: 3 additions & 0 deletions cf_units/_udunits2.pyx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ import numpy as np
cimport numpy as np
from libc cimport errno, string

# Must be called to use the C-API with Numpy
np.import_array()


cdef int _STRING_BUFFER_DEPTH = 128
cdef list _UT_STATUS = ['UT_SUCCESS', 'UT_BAD_ARG', 'UT_EXISTS', 'UT_NO_UNIT',
Expand Down
132 changes: 104 additions & 28 deletions cf_units/tests/test_coding_standards.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,10 @@
# This file is part of cf-units and is released under the BSD license.
# See LICENSE in the root of the repository for full licensing details.

import os
import subprocess
from datetime import datetime
from fnmatch import fnmatch
from glob import glob
from pathlib import Path

import pytest

Expand All @@ -19,21 +18,18 @@
# See LICENSE in the root of the repository for full licensing details."""


# Guess cf_units repo directory of cf_units - realpath is used to mitigate
# against Python finding the cf_units package via a symlink.
DIR = os.path.realpath(os.path.dirname(cf_units.__file__))
REPO_DIR = os.path.dirname(DIR)
DOCS_DIR = os.path.join(REPO_DIR, "doc")
DOCS_DIR = cf_units.config.get_option("Resources", "doc_dir", default=DOCS_DIR)
REPO_DIR = Path(__file__).resolve().parents[2]
DOCS_DIR = REPO_DIR / "docs"
DOCS_DIR = Path(
cf_units.config.get_option("Resources", "doc_dir", default=DOCS_DIR)
)
exclusion = ["Makefile", "make.bat", "build"]
DOCS_DIRS = glob(os.path.join(DOCS_DIR, "*"))
DOCS_DIRS = [
DOC_DIR
for DOC_DIR in DOCS_DIRS
if os.path.basename(DOC_DIR) not in exclusion
]
DOCS_DIRS = DOCS_DIR.glob("*")
DOCS_DIRS = [DOC_DIR for DOC_DIR in DOCS_DIRS if DOC_DIR.name not in exclusion]
IS_GIT_REPO = (REPO_DIR / ".git").is_dir()


@pytest.mark.skipif(not IS_GIT_REPO, reason="Not a git repository.")
class TestLicenseHeaders:
@staticmethod
def whatchanged_parse(whatchanged_output):
Expand Down Expand Up @@ -73,10 +69,6 @@ def last_change_by_fname():
or cannot be found by subprocess, an IOError may also be raised.
"""
# Check the ".git" folder exists at the repo dir.
if not os.path.isdir(os.path.join(REPO_DIR, ".git")):
raise ValueError(f"{REPO_DIR} is not a git repository.")

# Call "git whatchanged" to get the details of all the files and when
# they were last changed.
output = subprocess.check_output(
Expand All @@ -100,20 +92,14 @@ def test_license_headers(self):
"cf_units/_udunits2_parser/parser/*",
)

try:
last_change_by_fname = self.last_change_by_fname()
except ValueError:
# Caught the case where this is not a git repo.
return pytest.skip(
"cf_units installation did not look like a " "git repo."
)
last_change_by_fname = self.last_change_by_fname()

failed = False
for fname in sorted(last_change_by_fname):
full_fname = os.path.join(REPO_DIR, fname)
full_fname = REPO_DIR / fname
if (
full_fname.endswith(".py")
and os.path.isfile(full_fname)
full_fname.suffix == ".py"
and full_fname.is_file()
and not any(fnmatch(fname, pat) for pat in exclude_patterns)
):
with open(full_fname) as fh:
Expand All @@ -129,3 +115,93 @@ def test_license_headers(self):
raise AssertionError(
"There were license header failures. See stdout."
)


@pytest.mark.skipif(not IS_GIT_REPO, reason="Not a git repository.")
def test_python_versions():
"""Confirm alignment of ALL files listing supported Python versions."""
supported = ["3.10", "3.11", "3.12"]
supported_strip = [ver.replace(".", "") for ver in supported]
supported_latest = supported_strip[-1]

workflows_dir = REPO_DIR / ".github" / "workflows"

# Places that are checked:
pyproject_toml_file = REPO_DIR / "pyproject.toml"
setup_cfg_file = REPO_DIR / "setup.cfg"
tox_file = REPO_DIR / "tox.ini"
ci_locks_file = workflows_dir / "ci-locks.yml"
ci_tests_file = workflows_dir / "ci-tests.yml"
ci_wheels_file = workflows_dir / "ci-wheels.yml"

text_searches: list[tuple[Path, str]] = [
(
pyproject_toml_file,
"target-version = ["
+ ", ".join([f'"py{p}"' for p in supported_strip])
+ "]",
),
(
setup_cfg_file,
"\n ".join(
[
f"Programming Language :: Python :: {ver}"
for ver in supported
]
),
),
(
tox_file,
"[testenv:py{" + ",".join(supported_strip) + "}-lock]",
),
(
tox_file,
"[testenv:py{"
+ ",".join(supported_strip)
+ "}-{linux,osx,win}-test]",
),
(
ci_locks_file,
"lock: ["
+ ", ".join([f"py{p}-lock" for p in supported_strip])
+ "]",
),
(
ci_tests_file,
(
f"os: [ubuntu-latest]\n"
f"{8*' '}version: ["
+ ", ".join([f"py{p}" for p in supported_strip])
+ "]"
),
),
(
ci_tests_file,
(f"os: ubuntu-latest\n" f"{12*' '}version: py{supported_latest}"),
),
(
ci_tests_file,
(f"os: macos-latest\n" f"{12*' '}version: py{supported_latest}"),
),
]

# This routine will not check for file existence first - if files are
# being added/removed we want developers to be aware that this test will
# need to be updated.
for path, search in text_searches:
assert search in path.read_text()

tox_text = tox_file.read_text()
for version in supported_strip:
# A fairly lazy implementation, but should catch times when the section
# header does not match the conda_spec for the `tests` section.
# (Note that Tox does NOT provide its own helpful error in these cases).
py_version = f"py{version}"
assert tox_text.count(f" {py_version}-") == 3
assert tox_text.count(f"{py_version}-lock") == 3

ci_wheels_text = ci_wheels_file.read_text()
(cibw_line,) = [
line for line in ci_wheels_text.splitlines() if "CIBW_SKIP" in line
]
assert all([p not in cibw_line for p in supported_strip])
27 changes: 25 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ requires = [
"setuptools_scm[toml]>=7.0",
"wheel",
"oldest-supported-numpy",
"Cython"
"Cython>=3.0"
]
# Defined by PEP 517
build-backend = "setuptools.build_meta"
Expand Down Expand Up @@ -47,7 +47,7 @@ local_scheme = "dirty-tag"

[tool.ruff]
line-length = 79
target-version = "py38"
target-version = ["py310", "py311", "py312"]
select = [
# pyflakes
"F",
Expand Down Expand Up @@ -77,3 +77,26 @@ convention = "numpy"
[tool.ruff.per-file-ignores]
# Allow the longer comment lines that the generated code produces.
"cf_units/_udunits2_parser/parser/*.py" = ["E501"]

[tool.repo-review]
# These are a list of the currently failing tests:
ignore = [
"PY005", # Has tests folder
"PP003", # Does not list wheel as a build-dep
"PP304", # Sets the log level in pytest
"PP305", # Specifies xfail_strict
"PP306", # Specifies strict config
"PP307", # Specifies strict markers
"PP309", # Filter warnings specified
"GH104", # Use unique names for upload-artifact
"GH212", # Require GHA update grouping
"PC110", # Uses black or ruff-format
"PC140", # Uses a type checker
"PC160", # Uses a spell checker
"PC170", # Uses PyGrep hooks (only needed if rST present)
"PC180", # Uses a markdown formatter
"PC190", # Uses Ruff
"PC901", # Custom pre-commit CI message
"MY100", # Uses MyPy (pyproject config)
"RF001", # Uses RUFF
]
Loading

0 comments on commit 47592b4

Please sign in to comment.