Skip to content

Commit 31bc41e

Browse files
committed
Merge branch 'main' into create-bounds
2 parents cb80aad + 5aa5209 commit 31bc41e

File tree

4,644 files changed

+172785
-33873
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

4,644 files changed

+172785
-33873
lines changed

Changelog.rst

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ version 3.??.?
99
version 3.17.0
1010
--------------
1111

12-
**2025-03-24**
12+
**2025-04-02**
1313

1414
* Set new minimum version of `dask`: ``2025.2.0``
1515
(https://github.com/NCAS-CMS/cf-python/issues/849)
@@ -24,10 +24,13 @@ version 3.17.0
2424
* Fix bug that caused `Data._axes` to be incorrect after a call to
2525
`cf.Field.collapse`
2626
(https://github.com/NCAS-CMS/cf-python/issues/857)
27+
* Fix bug that caused wrong directions from
28+
`cf.DimensionCoordinate.direction`
29+
(https://github.com/NCAS-CMS/cf-python/issues/859)
2730
* Changed dependency: ``Python>=3.9.0``
2831
* Changed dependency: ``numpy>=2.0.0``
29-
* Changed dependency: ``cfdm>=1.12.0.0, <1.12.1.0``
30-
* Changed dependency: ``dask>=2025.2.0``
32+
* Changed dependency: ``cfdm>=1.12.1.0, <1.12.2.0``
33+
* Changed dependency: ``dask>=2025.2.0, <=2025.3.0``
3134
* Changed dependency: ``netCDF4>=1.7.2``
3235
* Changed dependency: ``cftime>=1.6.4``
3336
* Changed optional dependency: ``esmpy>=8.7.0``

DOCUMENTATION.md renamed to RECIPES.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
# Instructions for the cf-python gallery of code recipes
2+
3+
## Environment
4+
15
* The generation of recipes using Sphinx-Gallery requires `Python<3.12.0` and:
26

37
```txt
@@ -14,6 +18,13 @@
1418
pip install alabaster==0.7.13
1519
pip install sphinx==2.4.5
1620
```
21+
22+
* **Note** this is a very old very of Sphinx and some of its plugins etc., which will be updated soon so we
23+
use the latest, but is necessary for now to maintain certain features. When installing libraries, take
24+
care not to allow the newest version of Sphinx to be installed by default during the operation.
25+
26+
27+
## Notes
1728

1829
* The `.py` files to generate recipes are stored in `docs/source/recipes/`.
1930

@@ -51,3 +62,20 @@
5162
<button data-filter="testfilter">Test</button>
5263
</div>
5364
```
65+
66+
67+
## Building for a release
68+
69+
* Since the datasets to use are often very large, it is best to build only new recipes and re-build any
70+
which have been updated (usually to replace deprecated keywords or methods, etc.).
71+
* To force the prevention of re-builds, move the relevant `docs/source/recipes/plot_*_recipe.py` script(s)
72+
out of that directory (or `rm` them, they can be recovered by version control) and they won't be built.
73+
Use that to build only recipes that are new or updated.
74+
* The HTML files, code and generated notebooks under `_downloads` and generated plots
75+
and thumbnail images under `_images`, for any previously-built recipes, can then be manually copied
76+
across from stored archive builds, to create the full recipe listing.
77+
* The `index.html` will need to be updated to list the previously-generated recipes, also.
78+
* Note that recipes built for the `dev` or `archive` documentation builds will have paths in the
79+
recipes HTML files beginning with the relative path `../../` whereas for the `latest` documentation
80+
build this needs to be `../` only i.e. is one level up in the tree structure, so if copying anything over
81+
note this might need to be updated.

RELEASE.md

Lines changed: 36 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
* Decide the version name to set for the new release, by
1+
- [ ] Decide the version name to set for the new release, by
22
heeding the Versioning Strategy (see
33
https://ncas-cms.github.io/cf-python/releases.html#versioning-strategy).
44

5-
* Set the `NEXTVERSION` version marker across the codebase (added in PRs
5+
- [ ] Set the `NEXTVERSION` version marker across the codebase (added in PRs
66
to mark the next version where the exact number/name is not yet decided)
77
by recursively finding all occurences within the `cf` directory and replacing
88
them with the upcoming version name `X.Y.Z` (replace `X`, `Y` and `Z`
@@ -14,63 +14,63 @@
1414
$ find cf/ -type f | xargs sed -i 's/NEXTVERSION/X.Y.Z/g'
1515
```
1616

17-
* Change the version and date in `cf/__init__.py` (`__version__` and
17+
- [ ] Change the version and date in `cf/__init__.py` (`__version__` and
1818
`__date__` variables)
1919

20-
* Ensure that the requirements on dependencies & their versions are
20+
- [ ] Ensure that the requirements on dependencies & their versions are
2121
up-to-date and consistent in both the `requirements.txt` and in
2222
`docs/source/installation.rst`; and in the `_requires` list and
2323
`Version` checks in `cf/__init__.py`.
2424

25-
* Make sure that `README.md` is up to date.
25+
- [ ] Make sure that `README.md` is up to date.
2626

27-
* Make sure that the `long_description` in `setup.py` is up to date.
27+
- [ ] Make sure that the `long_description` in `setup.py` is up to date.
2828

29-
* Make sure that `Changelog.rst` is up to date (version, date and
29+
- [ ] Make sure that `Changelog.rst` is up to date (version, date and
3030
changes).
3131

32-
* Deprecated methods and keyword arguments: Check the code for
32+
- [ ] Deprecated methods and keyword arguments: Check the code for
3333
deprecated methods and keyword arguments that can be completely
3434
removed, i.e. those with a ``removed_at`` version that is at or
3535
before the version being released. Remove any reference to them in
3636
the method, class, or fucntion (including, if appropriate, the
3737
``@_deprecated_kwarg_check`` decorator), and remove them from the
3838
relevant documentation ``.rst`` files.
3939

40-
* Check that the documentation API coverage is complete:
40+
- [ ] Check that the documentation API coverage is complete:
4141

4242
```bash
4343
./check_docs_api_coverage
4444
```
4545

46-
* If it is not complete, add any undocumented attributes, methods,
46+
- [ ] If it is not complete, add any undocumented attributes, methods,
4747
functions and keyword arguments (e.g. as listed in the change log)
4848
to the `.rst` files in `docs/source/class/`.
4949

50-
* Check external links to the CF conventions are up to date in
50+
- [ ] Check external links to the CF conventions are up to date in
5151
`docs/source/tutorial.rst` and `docs/source/field_analysis.rst`
5252

53-
* Create a link to the new documentation in
53+
- [ ] Create a link to the new documentation in
5454
`docs/source/releases.rst`, including the release date.
5555

56-
* Test tutorial code:
56+
- [ ] Test tutorial code:
5757

5858
```bash
5959
export PYTHONPATH=$PWD:$PYTHONPATH
6060
./test_tutorial_code
6161
```
6262

63-
* **Follow all of the steps outlined externally in `DOCUMENTATION.md`**,
63+
- [ ] **Follow all of the steps outlined externally in [`RECIPES.md`](./RECIPES.md)**,
6464
notably so that the correct Sphinx-related environment is prepared for
6565
documentation building.
6666

67-
* Ensure that the [PDF for Cheat Sheet](docs/_downloads/cheatsheet.pdf)
67+
- [ ] Ensure that the [PDF for Cheat Sheet](docs/_downloads/cheatsheet.pdf)
6868
is updated to include any API changes. The PDF is created using Canva
6969
keeping in mind the colours and fonts of the website. The same could
7070
be edited using this
7171
[link](https://www.canva.com/design/DAFk9_BVfNY/gmQHycBiV_YbTIWMqYxK1g/edit).
7272

73-
* Build a development copy of the documentation using to check API
73+
- [ ] Build a development copy of the documentation using to check API
7474
pages for any new methods are present & correct, & that the overall
7575
formatting has not been adversely affected for comprehension by any
7676
updates in the latest Sphinx or theme etc. (Do not manually commit
@@ -80,17 +80,17 @@
8080
./release_docs dev-scrub
8181
```
8282

83-
* Check that no typos or spelling mistakes have been introduced to the
83+
- [ ] Check that no typos or spelling mistakes have been introduced to the
8484
documentation:
8585

86-
* Run a dummy build of the documentation to detect invalid words:
86+
- [ ] Run a dummy build of the documentation to detect invalid words:
8787

8888
```console
8989
$ cd docs
9090
$ make spelling build
9191
```
9292

93-
* If there are words raised with 'Spell check' warnings for the dummy
93+
- [ ] If there are words raised with 'Spell check' warnings for the dummy
9494
build, such as:
9595

9696
```bash
@@ -104,13 +104,13 @@
104104
`/attribute` or `/function` which will be fixed along with the origin
105105
docstrings after a 'latest' build) as follows:
106106

107-
* If there are words that are in fact valid, add the valid words to
107+
- [ ] If there are words that are in fact valid, add the valid words to
108108
the list of false positives for the spelling checker extension,
109109
`docs/source/spelling_false_positives.txt`.
110-
* Correct any words that are not valid in the codebase under `cf` or
110+
- [ ] Correct any words that are not valid in the codebase under `cf` or
111111
in the `docs/source` content files.
112112

113-
* Note that, in the case there are many words raised as warnings, it
113+
- [ ] Note that, in the case there are many words raised as warnings, it
114114
helps to automate the above steps. The following commands are a means
115115
to do this processing:
116116

@@ -132,58 +132,60 @@
132132
5. Remove duplicate words and sort alphabetically via:
133133
`sort -u -o docs/source/spelling_false_positives.txt docs/source/spelling_false_positives.txt`
134134

135-
* Create an archived copy of the documentation:
135+
- [ ] For major or epoch releases *only* (i.e. not minor, see the versioning strategy at
136+
https://ncas-cms.github.io/cf-python/releases.html#versioning-strategy)
137+
create an archived copy of the documentation:
136138

137139
```bash
138140
./release_docs archive
139141
```
140142

141-
* Update the latest documentation:
143+
- [ ] Update the latest documentation:
142144

143145
```bash
144146
./release_docs latest
145147
```
146148

147-
* Create a source tarball:
149+
- [ ] Create a source tarball:
148150

149151
```bash
150152
python setup.py sdist
151153
```
152154

153-
* Test the tarball release using
155+
- [ ] Test the tarball release using
154156

155157
```bash
156158
./test_release <vn> # E.g. ./test_release 3.14.0
157159
```
158160

159-
* Push recent commits using
161+
- [ ] Push recent commits using
160162

161163
```bash
162164
git push origin main
163165
```
164166

165-
* Tag the release:
167+
- [ ] Tag the release:
166168

167169
```bash
168170
./tag <vn> # E.g. ./tag 3.14.0
169171
```
170172

171-
* Upload the source tarball to PyPI. Note this requires the `twine`
173+
- [ ] Upload the source tarball to PyPI. Note this requires the `twine`
172174
library (which can be installed via `pip`) and relevant project
173175
privileges on PyPI.
174176

175177
```bash
176178
./upload_to_pypi <vn> # E.g. ./upload_to_pypi 3.14.0
177179
```
178180

179-
* Update the GitHub releases page for the new version:
181+
- [ ] Update the GitHub releases page for the new version:
180182
https://github.com/NCAS-CMS/cf-python/releases
181183

182-
* Upload the new release to Zenodo: https://zenodo.org/record/3961353
184+
- [ ] Upload the new release to Zenodo: https://zenodo.org/record/3961353
183185

184-
* Copy the archive docs to https://github.com/NCAS-CMS/cf-python-docs
185-
186-
* Move and commit the previously-generated archived copy of the documentation to https://github.com/NCAS-CMS/cf-python-docs (fork or clone that repo first):
186+
- [ ] For major or epoch releases *only*, move the archive docs generated earlier to
187+
https://github.com/NCAS-CMS/cf-python-docs and commit them (you may have to
188+
fork or clone that repo first):
187189

188190
```bash
189191
mv docs/<vn>/ ~/cf-python-docs/

cf/__init__.py

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -80,7 +80,7 @@
8080
8181
"""
8282

83-
__date__ = "2025-03-24"
83+
__date__ = "2025-04-02"
8484
__version__ = "3.17.0"
8585

8686
_requires = (
@@ -121,16 +121,16 @@
121121
raise ImportError(_error0 + str(error1))
122122
else:
123123
# Check the version of cfdm
124-
_minimum_vn = "1.12.0.0"
125-
_maximum_vn = "1.12.1.0"
124+
_minimum_vn = "1.12.1.0"
125+
_maximum_vn = "1.12.2.0"
126126
_cfdm_version = Version(cfdm.__version__)
127127
if _cfdm_version < Version(_minimum_vn) or _cfdm_version >= Version(
128128
_maximum_vn
129129
):
130130
raise RuntimeError(
131131
"Bad cfdm version: cf requires "
132132
f"{_minimum_vn}<=cfdm<{_maximum_vn}. "
133-
f"Got {cfdm.__version__} at {cfdm.__file__}"
133+
f"Got {_cfdm_version} at {cfdm.__file__}"
134134
)
135135

136136
__cf_version__ = cfdm.__cf_version__
@@ -202,10 +202,15 @@
202202
raise ImportError(_error0 + str(error1))
203203
else:
204204
_minimum_vn = "2025.2.0"
205-
if Version(dask.__version__) < Version(_minimum_vn):
206-
raise ValueError(
207-
f"Bad dask version: cf requires dask>={_minimum_vn}. "
208-
f"Got {dask.__version__} at {dask.__file__}"
205+
# Note in this case max is inclusive, change inequalities if this changes
206+
_maximum_vn = "2025.3.0"
207+
_dask_version = Version(dask.__version__)
208+
if _dask_version < Version(_minimum_vn) or _dask_version > Version(
209+
_maximum_vn
210+
):
211+
raise RuntimeError(
212+
"Bad dask version: cf requires "
213+
f"{_minimum_vn}<=dask<={_maximum_vn}. Got {_dask_version}."
209214
)
210215

211216
try:

cf/dimensioncoordinate.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -131,9 +131,9 @@ def _infer_direction(self):
131131
"""Return True if a coordinate is increasing, otherwise return
132132
False.
133133
134-
A dimension coordinate construct is considered to be increasing if
135-
its data array values are increasing in index space, or if it has
136-
no data nor bounds.
134+
A dimension coordinate construct is considered to be
135+
increasing if its data array values are not strictly
136+
decreasing in index space, or if it has no data nor bounds.
137137
138138
If the direction can not be inferred from the data not bounds then
139139
the coordinate's units are used.
@@ -168,12 +168,12 @@ def _infer_direction(self):
168168
c = data._get_cached_elements()
169169
if c:
170170
try:
171-
return bool(c.get(0) < c.get(1))
171+
return bool(c.get(0) <= c.get(1))
172172
except TypeError:
173173
pass
174174

175175
data = data[:2].compute()
176-
return bool(data.item(0) < data.item(1))
176+
return bool(data.item(0) <= data.item(1))
177177

178178
# Still here?
179179
data = self.get_bounds_data(None, _fill_value=False)
@@ -182,12 +182,12 @@ def _infer_direction(self):
182182
c = data._get_cached_elements()
183183
if c:
184184
try:
185-
return bool(c.get(0) < c.get(1))
185+
return bool(c.get(0) <= c.get(1))
186186
except TypeError:
187187
pass
188188

189189
b = data[0].compute()
190-
return bool(b.item(0) < b.item(1))
190+
return bool(b.item(0) <= b.item(1))
191191

192192
# Still here? Then infer the direction from the units.
193193
return not self.Units.ispressure

cf/test/test_DimensionCoordinate.py

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -818,6 +818,30 @@ def test_DimensionCoordinate_anchor(self):
818818
self.assertEqual(e[0].array, d[0].array - 360)
819819

820820

821+
def test_DimensionCoordinate_direction(self):
822+
"""Test DimensionCoordinate.direction"""
823+
d = self.dim.copy()
824+
825+
# Test the use case of
826+
# https://github.com/NCAS-CMS/cf-python/issues/859
827+
#
828+
# Create a coordinate with all equal values
829+
d.data[...] = d[0].array
830+
for i, x in enumerate(d.array):
831+
d.bounds.data[i, :] = x
832+
833+
d._custom["direction"] = None # Force a re-calculation of direction
834+
self.assertTrue(d.direction())
835+
d._custom["direction"] = None
836+
self.assertTrue(d[0].direction())
837+
838+
d.del_bounds()
839+
d._custom["direction"] = None
840+
self.assertTrue(d.direction())
841+
d._custom["direction"] = None
842+
self.assertTrue(d[0].direction())
843+
844+
821845
if __name__ == "__main__":
822846
print("Run date:", datetime.datetime.now())
823847
cf.environment()

0 commit comments

Comments
 (0)