[Git][debian-gis-team/cftime][master] 4 commits: New upstream version 1.6.6.1
Bas Couwenberg (@sebastic)
gitlab at salsa.debian.org
Thu Oct 15 04:15:40 BST 2026
Bas Couwenberg pushed to branch master at Debian GIS Project / cftime
Commits:
fb409f6e by Bas Couwenberg at 2026-10-15T05:11:08+02:00
New upstream version 1.6.6.1
- - - - -
e6046807 by Bas Couwenberg at 2026-10-15T05:11:08+02:00
Update upstream source from tag 'upstream/1.6.6.1'
Update to upstream version '1.6.6.1'
with Debian dir 04fcd3511848a0e292de6013441f6a6c44246ea3
- - - - -
6a3e27a1 by Bas Couwenberg at 2026-10-15T05:11:23+02:00
New upstream release.
- - - - -
703443a5 by Bas Couwenberg at 2026-10-15T05:12:01+02:00
Set distribution to unstable.
- - - - -
12 changed files:
- .github/workflows/cibuildwheel.yml
- .github/workflows/deploy-docs.yml
- .github/workflows/tests_latest.yml → .github/workflows/tests.yml
- − .github/workflows/tests_conda.yml
- Changelog
- README.md
- debian/changelog
- docs/conf.py
- docs/index.rst
- pyproject.toml
- src/cftime/_cftime.pyx
- test/test_cftime.py
Changes:
=====================================
.github/workflows/cibuildwheel.yml
=====================================
@@ -36,25 +36,9 @@ jobs:
fetch-depth: 0
persist-credentials: false
- - name: Build just oldest and newest on PRs, all on tags
- if: ${{ github.event_name == 'pull_request' }}
- shell: bash
- # - On PPs, omit musllinux for speed
- # - On PRs, run just oldest and newest Python versions (3.11 is the oldest abi3 target)
- run: |
- CIBW_SKIP="cp310-win_arm64 *musllinux*"
- echo "CIBW_SKIP=$CIBW_SKIP" >> $GITHUB_ENV
- echo "Setting CIBW_SKIP=$CIBW_SKIP"
-
- CIBW_TEST_SKIP="cp312-* cp313-*"
- echo "CIBW_TEST_SKIP=$CIBW_TEST_SKIP" >> $GITHUB_ENV
- echo "Setting CIBW_TEST_SKIP=$CIBW_TEST_SKIP"
-
- name: "Building ${{ matrix.os }} (${{ matrix.arch }}) wheels"
- uses: pypa/cibuildwheel at 1828c10ab37f080699c7b81cea34097c684a7074 # v4.2.0
+ uses: pypa/cibuildwheel at e090b81e30c4d855ea63bf4b6e59204c09a101ae # v4.2.1
env:
- CIBW_SKIP: ${{ env.CIBW_SKIP }}
- CIBW_TEST_SKIP: ${{ env.CIBW_TEST_SKIP }}
CIBW_ARCHS: ${{ matrix.arch }}
- uses: actions/upload-artifact at 043fb46d1a93c77aae656e7c1c64a875d1fc6a0a # v7.0.1
@@ -90,8 +74,8 @@ jobs:
needs: [build_bdist, build_sdist]
name: "Publish to PyPI"
runs-on: ubuntu-24.04
- # upload to PyPI for every tag starting with 'v'
- if: github.event_name == 'push' && startsWith(github.event.ref, 'refs/tags/v')
+ # upload to PyPI when github release made
+ if: github.event_name == 'release' && github.event.action == 'published'
steps:
- uses: actions/download-artifact at 3e5f45b2cfb9172054b4087a40e8e0b5a5461e7c # v8
with:
=====================================
.github/workflows/deploy-docs.yml
=====================================
@@ -25,27 +25,21 @@ jobs:
fetch-depth: 0
persist-credentials: false
- - name: Setup Mamba
- uses: mamba-org/setup-micromamba at f457c30a868e4760d3a6fcea5f25dc655b8edf39 # v3.2.1
+ - name: Set up Python
+ uses: actions/setup-python at 5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
- environment-name: TEST
- create-args: >-
- python=3
- numpy>1.13.3
- sphinx
-
- - name: Build environment
- shell: bash -l {0}
+ python-version: "3.x"
+
+ - name: Install cftime
run: |
- python -m pip install -e . --no-deps --force-reinstall
+ pip install --group dev
+ pip install -e .
- name: Get the version
- shell: bash -l {0}
id: get_version
- run: echo "name=VERSION::$(python setup.py --version)" >> $GITHUB_OUTPUT
+ run: echo "name=VERSION::$(python -c 'import cftime; print(cftime.__version__)')" >> $GITHUB_OUTPUT
- name: Build documentation
- shell: bash -l {0}
run: |
set -e
pushd docs
=====================================
.github/workflows/tests_latest.yml → .github/workflows/tests.yml
=====================================
@@ -1,48 +1,39 @@
-name: Build and test with development python
+name: TESTS
on:
pull_request:
push:
+ branches: [ master ]
# Deny all permissions by default
permissions: {}
jobs:
- build-linux:
- name: Python (${{ matrix.python-version }})
- runs-on: ubuntu-latest
+ run:
+ runs-on: ${{ matrix.os }}
strategy:
+ fail-fast: false
matrix:
- python-version: ["3.14"]
- steps:
+ python-version: [ "3.11", "3.15-dev" ]
+ os: [ windows-latest, ubuntu-latest, macos-latest, macos-15-intel ]
+ steps:
- uses: actions/checkout at 3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- - name: Set up Python ${{ matrix.python-version }}
+ - name: Set up Python
uses: actions/setup-python at 5fda3b95a4ea91299a34e894583c3862153e4b97 # v7.0.0
with:
python-version: ${{ matrix.python-version }}
- - name: Update Pip
- run: |
- python -m pip install --upgrade pip
-
- - name: Install unstable cftime dependencies via pip
- run: |
- python -m pip install --pre --group dev
- # get nightly wheels for numpy
- python -m pip install \
- --index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple/ \
- --trusted-host pypi.anaconda.org \
- --no-deps --pre --upgrade \
- numpy
-
- name: Install cftime
run: |
- python -m pip install .
+ pip install --group dev
+ pip install -e .
+
- - name: Test cftime
+ - name: Run Tests
run: |
- pytest -vv test
+ coverage run -m pytest -vv test
+ coverage report
=====================================
.github/workflows/tests_conda.yml deleted
=====================================
@@ -1,66 +0,0 @@
-name: TESTS-CONDA-ENV
-
-on:
- pull_request:
- push:
- branches: [master]
-
-# Deny all permissions by default
-permissions: {}
-
-jobs:
- run:
- runs-on: ${{ matrix.os }}
- continue-on-error: ${{ matrix.experimental }}
- strategy:
- fail-fast: false
- matrix:
- python-version: [ "3.10", "3.11", "3.12", "3.13", "3.14" ]
- os: [windows-latest, ubuntu-latest, macos-latest]
- platform: [x64, x32]
- experimental: [false]
- exclude:
- - os: macos-latest
- platform: x32
- include:
- - python-version: "3.12"
- os: "ubuntu-latest"
- experimental: true
-
- steps:
- - uses: actions/checkout at 3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
- with:
- persist-credentials: false
-
- - name: Setup micromamba Env
- uses: mamba-org/setup-micromamba at f457c30a868e4760d3a6fcea5f25dc655b8edf39 # v3.2.1
- with:
- environment-name: TEST
- create-args: >-
- python=${{ matrix.python-version }}
- numpy>1.13.3
- cython>=0.29.20
- pytest
- coverage
- - name: Install unstable dependencies
- if: matrix.experimental == true
- shell: bash -l {0}
- run: |
- python -m pip install \
- --index-url https://pypi.anaconda.org/scientific-python-nightly-wheels/simple/ \
- --trusted-host pypi.anaconda.org \
- --no-deps --pre --upgrade \
- numpy;
- python -m pip install -v -e . --no-deps --no-build-isolation --force-reinstall
-
- - name: Install cftime
- if: matrix.experimental != true
- shell: bash -l {0}
- run: |
- python -m pip install -v -e . --no-deps --force-reinstall
-
- - name: Run Tests
- shell: bash -l {0}
- run: |
- coverage run -m pytest -vv test
- coverage report
=====================================
Changelog
=====================================
@@ -1,3 +1,9 @@
+version 1.6.6.1 (release tag v1.6.6.1)
+======================================
+* ensure has_year_zero=False is ignored for idealized calendars, including when
+ constructing year zero dates (issue #419).
+* include free-threaded wheels (issue #421).
+
version 1.6.6 (release tag v1.6.6rel)
=====================================
* added new CF calendar "tai", which is the same as proleptic_gregorian but is only
=====================================
README.md
=====================================
@@ -11,6 +11,8 @@ Time-handling functionality from netcdf4-python
## News
For details on the latest updates, see the [Changelog](https://github.com/Unidata/cftime/blob/master/Changelog).
+10/15/2026: Version 1.6.6.1 release. Includes free-threaded wheels.
+
9/15/2026: Version 1.6.6 release. Limited API compliant wheels (should work with python 3.15). New cftime calendar "tai".
10/13/2025: Version 1.6.5 release. Minor bugfixes/optimizations, wheels for python 3.14, no more wheels for 3.8/3.9.
=====================================
debian/changelog
=====================================
@@ -1,3 +1,9 @@
+cftime (1.6.6.1-1) unstable; urgency=medium
+
+ * New upstream release.
+
+ -- Bas Couwenberg <sebastic at debian.org> Thu, 15 Oct 2026 05:11:53 +0200
+
cftime (1.6.6-1) unstable; urgency=medium
* New upstream release.
=====================================
docs/conf.py
=====================================
@@ -18,15 +18,14 @@
# -- Project information -----------------------------------------------------
+import cftime
project = 'cftime'
copyright = '2018, Jeff Whitaker'
author = 'Jeff Whitaker'
# The short X.Y version
-version = ''
-# The full version, including alpha/beta/rc tags
-release = '1.0'
+version = release = cftime.__version__
# -- General configuration ---------------------------------------------------
=====================================
docs/index.rst
=====================================
@@ -4,6 +4,25 @@ cftime
Python library for decoding time units and variable values in a netCDF file
conforming to the `Climate and Forecasting (CF) netCDF conventions <http://cfconventions.org/cf-conventions/cf-conventions#time-coordinate>`__.
+Example
+-------
+
+Convert numeric time coordinates to dates with :func:`cftime.num2date`,
+and convert dates back to numeric coordinates with :func:`cftime.date2num`.
+The units specify both a time interval and a reference date::
+
+ >>> import cftime
+ >>> units = 'common_years since 0347-01-01'
+ >>> date = cftime.num2date(1, units, calendar='noleap')
+ >>> (date.year, date.month, date.day)
+ (348, 1, 1)
+ >>> int(cftime.date2num(date, units, calendar='noleap'))
+ 1
+
+``noleap`` and ``365_day`` are names for the same calendar, in which every
+year has 365 days. Either name can be used with ``common_years`` units.
+Include the day in the reference date (``0347-01-01``, not ``0347-01``).
+
Contents
--------
=====================================
pyproject.toml
=====================================
@@ -1,6 +1,6 @@
[project]
name = "cftime"
-version = "1.6.6"
+version = "1.6.6.1"
description = "Time-handling functionality from netcdf4-python"
readme = "README.md"
authors = [
@@ -15,7 +15,6 @@ classifiers = [
'Operating System :: POSIX :: Linux',
'Programming Language :: Python',
'Programming Language :: Python :: 3',
- 'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: 3.12',
'Programming Language :: Python :: 3.13',
@@ -24,10 +23,9 @@ classifiers = [
'Topic :: Scientific/Engineering',
]
dependencies = [
- "numpy>=2.3.0; platform_system == 'Windows' and platform_machine == 'ARM64'",
- "numpy>=1.21.2; platform_system != 'Windows' or platform_machine != 'ARM64'",
+ "numpy>=1.23.2",
]
-requires-python = ">=3.10"
+requires-python = ">=3.11"
[dependency-groups]
dev = [
@@ -109,24 +107,13 @@ ignore = [
[tool.cibuildwheel]
build-verbosity = 1
-skip = [
- "*musllinux_aarch64*",
- # Skipped due to unavailability of Python binary and NumPy for Win-ARM64
- "cp310-win_arm64",
-]
+skip = "*-musllinux*"
-test-skip = [
- # Emulated testing is slow, so trust that the Python 3.14 test is good enough on aarch64
- # (takes about 5 minutes per wheel to build, and 5 minutes to test)
- "cp3{10,11,12,13}-*_aarch64",
-]
test-groups = "dev"
test-command = [
'''python -c "import cftime; print(f'cftime v{cftime.__version__}')"''',
"python -m pytest -vv {package}/test"
]
-#manylinux-x86_64-image = "manylinux2014"
-#manylinux-aarch64-image = "manylinux2014"
manylinux-x86_64-image = "manylinux_2_28"
manylinux-aarch64-image = "manylinux_2_28"
environment = { CFTIME_LIMITED_API = "1" }
=====================================
src/cftime/_cftime.pyx
=====================================
@@ -155,7 +155,8 @@ def date2num(dates, units, calendar=None, has_year_zero=None, longdouble=False):
describing the time units. **<time units>** can be days, hours, minutes,
seconds, milliseconds or microseconds. **<reference time>** is the time
origin. **months since** is allowed *only* for the **360_day** calendar
- and **common_years since** is allowed *only* for the **365_day** calendar.
+ and **common_years since** is allowed *only* for the **365_day** calendar
+ (also called **noleap**).
**calendar**: describes the calendar to be used in the time calculations.
All the values currently defined in the
@@ -541,7 +542,8 @@ def num2date(
describing the time units. **<time units>** can be days, hours, minutes,
seconds, milliseconds or microseconds. **<reference time>** is the time
origin. **months since** is allowed *only* for the **360_day** calendar
- and **common_years since** is allowed *only* for the **365_day** calendar.
+ and **common_years since** is allowed *only* for the **365_day** calendar
+ (also called **noleap**).
**calendar**: describes the calendar used in the time calculations.
All the values currently defined in the
@@ -1099,8 +1101,9 @@ CF version 1.9 conventions (False for 'julian', 'gregorian'/'standard', True
for 'proleptic_gregorian' (ISO 8601) and True for the idealized
calendars 'noleap'/'365_day', '360_day', 366_day'/'all_leap')
The defaults can only be over-ridden for the real-world calendars,
-for the the idealized calendars the year zero
-always exists and the has_year_zero kwarg is ignored.
+for the idealized calendars the year zero always exists and the
+has_year_zero kwarg is ignored. Passing False emits a warning and the
+instance's has_year_zero attribute is set to True.
This kwarg is not needed to define calendar systems allowed by CF
(the calendar-specific defaults do this).
@@ -1167,13 +1170,15 @@ The default format of the string produced by strftime is controlled by self.form
raise ValueError('dates before 1958-01-01 not allowed in TAI calendar')
if has_year_zero:
raise ValueError('year zero not allowed in TAI calendar')
+ # Idealized calendars always have a year zero, even if False is passed.
+ if not has_year_zero and calendar in _idealized_calendars:
+ warnings.warn('has_year_zero kwarg ignored for idealized calendars (always True)')
+ has_year_zero = True
# raise exception if year zero requested but has_year_zero set
# to False (issue #248).
if year == 0 and has_year_zero==False:
msg='year zero requested, but has_year_zero=False'
raise ValueError(msg)
- if not has_year_zero and calendar in _idealized_calendars:
- warnings.warn('has_year_zero kwarg ignored for idealized calendars (always True)')
self.has_year_zero = has_year_zero
if calendar == 'gregorian' or calendar == 'standard':
# dates after 1582-10-15 can be converted to and compared to
=====================================
test/test_cftime.py
=====================================
@@ -6,6 +6,7 @@ from cftime import (Datetime360Day, DatetimeAllLeap,
DatetimeProlepticGregorian, DatetimeTAI, _parse_date,
date2index, date2num, num2date, UNIT_CONVERSION_FACTORS)
import copy
+import pickle
import unittest
import warnings
from collections import namedtuple
@@ -1560,6 +1561,84 @@ def test_zero_year(date_type):
date_type(0, 1, 1, has_year_zero=False)
+
+ at pytest.fixture(params=[
+ (datetimex, 'noleap', 365),
+ (datetimex, '365_day', 365),
+ (datetimex, 'all_leap', 366),
+ (datetimex, '366_day', 366),
+ (datetimex, '360_day', 360),
+ (DatetimeNoLeap, 'noleap', 365),
+ (DatetimeAllLeap, 'all_leap', 366),
+ (Datetime360Day, '360_day', 360),
+], ids=[
+ 'noleap', '365_day', 'all_leap', '366_day', '360_day',
+ 'DatetimeNoLeap', 'DatetimeAllLeap', 'Datetime360Day',
+])
+def idealized_year_zero_calendar(request):
+ return request.param
+
+
+ at pytest.mark.parametrize('year', [-1, 0, 1, 2000])
+def test_idealized_has_year_zero_false(idealized_year_zero_calendar, year):
+ # Issue #419: the ignored argument must not change the stored convention.
+ date_type, calendar, _ = idealized_year_zero_calendar
+ with pytest.warns(UserWarning, match='has_year_zero kwarg ignored'):
+ date = date_type(year, 1, 1, 12, calendar=calendar, has_year_zero=False)
+ expected = date_type(year, 1, 1, 12, calendar=calendar)
+ assert date.has_year_zero is True
+ assert date == expected
+ assert date - expected == timedelta(0)
+ assert datetimex.fromordinal(
+ date.toordinal(), calendar=calendar,
+ has_year_zero=date.has_year_zero) == date
+ restored = pickle.loads(pickle.dumps(date))
+ assert type(restored) is type(date)
+ assert restored.has_year_zero is True
+ assert restored == date
+
+
+ at pytest.mark.parametrize('year', [-1, 0, 1])
+def test_idealized_replace_has_year_zero_false(idealized_year_zero_calendar, year):
+ date_type, calendar, _ = idealized_year_zero_calendar
+ date = date_type(1, 1, 1, calendar=calendar)
+ with pytest.warns(UserWarning, match='has_year_zero kwarg ignored'):
+ replaced = date.replace(year=year, has_year_zero=False)
+ assert replaced.has_year_zero is True
+ assert replaced == date_type(year, 1, 1, calendar=calendar)
+
+
+ at pytest.mark.parametrize('year', [-1, 0])
+def test_idealized_has_year_zero_false_arithmetic(
+ idealized_year_zero_calendar, year):
+ date_type, calendar, days_per_year = idealized_year_zero_calendar
+ with pytest.warns(UserWarning, match='has_year_zero kwarg ignored'):
+ start = date_type(year, 1, 1, calendar=calendar, has_year_zero=False)
+ end = date_type(year + 1, 1, 1, calendar=calendar)
+ delta = timedelta(days=days_per_year)
+ assert end - start == delta
+ assert start + delta == end
+ assert end - delta == start
+ assert (start + delta).has_year_zero is True
+ assert (end - delta).has_year_zero is True
+
+
+ at pytest.mark.parametrize('calendar', [
+ 'standard', 'gregorian', 'julian', 'proleptic_gregorian',
+])
+def test_real_world_has_year_zero_false(calendar):
+ with warnings.catch_warnings():
+ warnings.simplefilter('ignore', cftime.CFWarning)
+ before = datetimex(-1, 12, 31, calendar=calendar, has_year_zero=False)
+ after = datetimex(1, 1, 1, calendar=calendar, has_year_zero=False)
+ assert before.has_year_zero is False
+ assert after.has_year_zero is False
+ assert before + timedelta(days=1) == after
+ assert after - before == timedelta(days=1)
+ with pytest.raises(ValueError, match='year zero requested'):
+ datetimex(0, 1, 1, calendar=calendar, has_year_zero=False)
+
+
def test_invalid_month(date_type):
with pytest.raises(ValueError):
date_type(1, 0, 1)
View it on GitLab: https://salsa.debian.org/debian-gis-team/cftime/-/compare/2169d617487bf503374c32372751ec9305f415a9...703443a51d0028683de8fbfb514fb1bd93dc0a2e
--
View it on GitLab: https://salsa.debian.org/debian-gis-team/cftime/-/compare/2169d617487bf503374c32372751ec9305f415a9...703443a51d0028683de8fbfb514fb1bd93dc0a2e
You're receiving this email because of your account on salsa.debian.org. Manage all notifications: https://salsa.debian.org/-/profile/notifications | Help: https://salsa.debian.org/help
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://alioth-lists.debian.net/pipermail/pkg-grass-devel/attachments/20261015/b130a2c0/attachment-0001.htm>
More information about the Pkg-grass-devel
mailing list