[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