Skip to content
forked from pydata/xarray

Commit f196efb

Browse files
committed
Merge remote-tracking branch 'upstream/master' into fix/groupby-nan
* upstream/master: MAGA (Make Azure Green Again) (pydata#3436) Test that Dataset and DataArray resampling are identical (pydata#3412) Avoid multiplication DeprecationWarning in rasterio backend (pydata#3428) Sync with latest version of cftime (v1.0.4) (pydata#3430) Add cftime git tip to upstream-dev + temporarily pin cftime (pydata#3431)
2 parents 54e29af + c8dac58 commit f196efb

File tree

11 files changed

+98
-52
lines changed

11 files changed

+98
-52
lines changed

ci/azure/install.yml

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,16 +15,18 @@ steps:
1515
--no-deps \
1616
--pre \
1717
--upgrade \
18-
numpy \
1918
matplotlib \
2019
pandas \
2120
scipy
21+
# numpy \ # FIXME https://github.com/pydata/xarray/issues/3409
2222
pip install \
2323
--no-deps \
2424
--upgrade \
2525
git+https://github.com/dask/dask \
2626
git+https://github.com/dask/distributed \
27-
git+https://github.com/zarr-developers/zarr
27+
git+https://github.com/zarr-developers/zarr \
28+
git+https://github.com/Unidata/cftime.git@refs/pull/127/merge
29+
# git+https://github.com/Unidata/cftime # FIXME PR 127 not merged yet
2830
condition: eq(variables['UPSTREAM_DEV'], 'true')
2931
displayName: Install upstream dev dependencies
3032

ci/min_deps_check.py

Lines changed: 43 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
import sys
77
from concurrent.futures import ThreadPoolExecutor
88
from datetime import datetime, timedelta
9-
from typing import Dict, Iterator, Tuple
9+
from typing import Dict, Iterator, Optional, Tuple
1010

1111
import yaml
1212

@@ -34,10 +34,14 @@ def error(msg: str) -> None:
3434
print("ERROR:", msg)
3535

3636

37-
def parse_requirements(fname) -> Iterator[Tuple[str, int, int]]:
37+
def warning(msg: str) -> None:
38+
print("WARNING:", msg)
39+
40+
41+
def parse_requirements(fname) -> Iterator[Tuple[str, int, int, Optional[int]]]:
3842
"""Load requirements/py36-min-all-deps.yml
3943
40-
Yield (package name, major version, minor version)
44+
Yield (package name, major version, minor version, [patch version])
4145
"""
4246
global has_errors
4347

@@ -52,15 +56,18 @@ def parse_requirements(fname) -> Iterator[Tuple[str, int, int]]:
5256
if pkg.endswith("<") or pkg.endswith(">") or eq != "=":
5357
error("package should be pinned with exact version: " + row)
5458
continue
59+
5560
try:
56-
major, minor = version.split(".")
57-
except ValueError:
58-
error("expected major.minor (without patch): " + row)
59-
continue
60-
try:
61-
yield pkg, int(major), int(minor)
61+
version_tup = tuple(int(x) for x in version.split("."))
6262
except ValueError:
63-
error("failed to parse version: " + row)
63+
raise ValueError("non-numerical version: " + row)
64+
65+
if len(version_tup) == 2:
66+
yield (pkg, *version_tup, None) # type: ignore
67+
elif len(version_tup) == 3:
68+
yield (pkg, *version_tup) # type: ignore
69+
else:
70+
raise ValueError("expected major.minor or major.minor.patch: " + row)
6471

6572

6673
def query_conda(pkg: str) -> Dict[Tuple[int, int], datetime]:
@@ -80,9 +87,9 @@ def query_conda(pkg: str) -> Dict[Tuple[int, int], datetime]:
8087
label = label.strip()
8188
if label == "file name":
8289
value = value.strip()[len(pkg) :]
83-
major, minor = value.split("-")[1].split(".")[:2]
84-
major = int(major)
85-
minor = int(minor)
90+
smajor, sminor = value.split("-")[1].split(".")[:2]
91+
major = int(smajor)
92+
minor = int(sminor)
8693
if label == "timestamp":
8794
assert major is not None
8895
assert minor is not None
@@ -109,17 +116,15 @@ def query_conda(pkg: str) -> Dict[Tuple[int, int], datetime]:
109116

110117

111118
def process_pkg(
112-
pkg: str, req_major: int, req_minor: int
113-
) -> Tuple[str, int, int, str, int, int, str, str]:
119+
pkg: str, req_major: int, req_minor: int, req_patch: Optional[int]
120+
) -> Tuple[str, str, str, str, str, str]:
114121
"""Compare package version from requirements file to available versions in conda.
115122
Return row to build pandas dataframe:
116123
117124
- package name
118-
- major version in requirements file
119-
- minor version in requirements file
125+
- major.minor.[patch] version in requirements file
120126
- publication date of version in requirements file (YYYY-MM-DD)
121-
- major version suggested by policy
122-
- minor version suggested by policy
127+
- major.minor version suggested by policy
123128
- publication date of version suggested by policy (YYYY-MM-DD)
124129
- status ("<", "=", "> (!)")
125130
"""
@@ -130,7 +135,7 @@ def process_pkg(
130135
req_published = versions[req_major, req_minor]
131136
except KeyError:
132137
error("not found in conda: " + pkg)
133-
return pkg, req_major, req_minor, "-", 0, 0, "-", "(!)"
138+
return pkg, fmt_version(req_major, req_minor, req_patch), "-", "-", "-", "(!)"
134139

135140
policy_months = POLICY_MONTHS.get(pkg, POLICY_MONTHS_DEFAULT)
136141
policy_published = datetime.now() - timedelta(days=policy_months * 30)
@@ -153,30 +158,39 @@ def process_pkg(
153158
else:
154159
status = "="
155160

161+
if req_patch is not None:
162+
warning("patch version should not appear in requirements file: " + pkg)
163+
status += " (w)"
164+
156165
return (
157166
pkg,
158-
req_major,
159-
req_minor,
167+
fmt_version(req_major, req_minor, req_patch),
160168
req_published.strftime("%Y-%m-%d"),
161-
policy_major,
162-
policy_minor,
169+
fmt_version(policy_major, policy_minor),
163170
policy_published_actual.strftime("%Y-%m-%d"),
164171
status,
165172
)
166173

167174

175+
def fmt_version(major: int, minor: int, patch: int = None) -> str:
176+
if patch is None:
177+
return f"{major}.{minor}"
178+
else:
179+
return f"{major}.{minor}.{patch}"
180+
181+
168182
def main() -> None:
169183
fname = sys.argv[1]
170184
with ThreadPoolExecutor(8) as ex:
171185
futures = [
172-
ex.submit(process_pkg, pkg, major, minor)
173-
for pkg, major, minor in parse_requirements(fname)
186+
ex.submit(process_pkg, pkg, major, minor, patch)
187+
for pkg, major, minor, patch in parse_requirements(fname)
174188
]
175189
rows = [f.result() for f in futures]
176190

177-
print("Package Required Policy Status")
178-
print("------------- ----------------- ----------------- ------")
179-
fmt = "{:13} {:>1d}.{:<2d} ({:10}) {:>1d}.{:<2d} ({:10}) {}"
191+
print("Package Required Policy Status")
192+
print("------------- -------------------- -------------------- ------")
193+
fmt = "{:13} {:7} ({:10}) {:7} ({:10}) {}"
180194
for row in rows:
181195
print(fmt.format(*row))
182196

ci/requirements/py36-min-all-deps.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ dependencies:
1313
- cartopy=0.17
1414
- cdms2=3.1
1515
- cfgrib=0.9
16-
- cftime=1.0
16+
- cftime=1.0.3 # FIXME need 1.0.5 (not released yet); 1.0.4 is broken
1717
- coveralls
1818
- dask=1.2
1919
- distributed=1.27

ci/requirements/py36.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ dependencies:
99
- cartopy
1010
- cdms2
1111
- cfgrib
12-
- cftime
12+
- cftime<1.0.4 # FIXME need 1.0.5 (not released yet); 1.0.4 is broken
1313
- coveralls
1414
- dask
1515
- distributed
@@ -25,7 +25,7 @@ dependencies:
2525
- nc-time-axis
2626
- netcdf4
2727
- numba
28-
- numpy
28+
- numpy<1.18 # FIXME https://github.com/pydata/xarray/issues/3409
2929
- pandas
3030
- pint
3131
- pip

ci/requirements/py37-windows.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ dependencies:
88
- bottleneck
99
- cartopy
1010
# - cdms2 # Not available on Windows
11-
# - cfgrib>=0.9.2 # Causes Python interpreter crash on Windows
12-
- cftime
11+
# - cfgrib # Causes Python interpreter crash on Windows
12+
- cftime<1.0.4 # FIXME need 1.0.5 (not released yet); 1.0.4 is broken
1313
- coveralls
1414
- dask
1515
- distributed
@@ -25,7 +25,7 @@ dependencies:
2525
- nc-time-axis
2626
- netcdf4
2727
- numba
28-
- numpy
28+
- numpy<1.18 # FIXME https://github.com/pydata/xarray/issues/3409
2929
- pandas
3030
- pint
3131
- pip

ci/requirements/py37.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ dependencies:
99
- cartopy
1010
- cdms2
1111
- cfgrib
12-
- cftime
12+
- cftime<1.0.4 # FIXME need 1.0.5 (not released yet); 1.0.4 is broken
1313
- coveralls
1414
- dask
1515
- distributed
@@ -25,7 +25,7 @@ dependencies:
2525
- nc-time-axis
2626
- netcdf4
2727
- numba
28-
- numpy
28+
- numpy<1.18 # FIXME https://github.com/pydata/xarray/issues/3409
2929
- pandas
3030
- pint
3131
- pip

doc/whats-new.rst

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,11 @@ What's New
1818
v0.14.1 (unreleased)
1919
--------------------
2020

21+
Breaking changes
22+
~~~~~~~~~~~~~~~~
23+
24+
- Minimum cftime version is now 1.0.3. By `Deepak Cherian <https://github.com/dcherian>`_.
25+
2126
New Features
2227
~~~~~~~~~~~~
2328
- Added integration tests against `pint <https://pint.readthedocs.io/>`_.
@@ -38,6 +43,10 @@ Bug fixes
3843
- Fix grouping over variables with NaNs. (:issue:`2383`, :pull:`3406`).
3944
By `Deepak Cherian <https://github.com/dcherian>`_.
4045

46+
- Sync with cftime by removing `dayofwk=-1` for cftime>=1.0.4.
47+
By `Anderson Banihirwe <https://github.com/andersy005>`_.
48+
49+
4150
Documentation
4251
~~~~~~~~~~~~~
4352

xarray/backends/rasterio_.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -257,8 +257,8 @@ def open_rasterio(filename, parse_coordinates=None, chunks=None, cache=None, loc
257257
if parse:
258258
nx, ny = riods.width, riods.height
259259
# xarray coordinates are pixel centered
260-
x, _ = (np.arange(nx) + 0.5, np.zeros(nx) + 0.5) * riods.transform
261-
_, y = (np.zeros(ny) + 0.5, np.arange(ny) + 0.5) * riods.transform
260+
x, _ = riods.transform * (np.arange(nx) + 0.5, np.zeros(nx) + 0.5)
261+
_, y = riods.transform * (np.zeros(ny) + 0.5, np.arange(ny) + 0.5)
262262
coords["y"] = y
263263
coords["x"] = x
264264
else:

xarray/coding/cftime_offsets.py

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
from ..core.pdcompat import count_not_none
5151
from .cftimeindex import CFTimeIndex, _parse_iso8601_with_reso
5252
from .times import format_cftime_datetime
53+
from distutils.version import LooseVersion
5354

5455

5556
def get_date_type(calendar):
@@ -222,6 +223,8 @@ def _adjust_n_years(other, n, month, reference_day):
222223
def _shift_month(date, months, day_option="start"):
223224
"""Shift the date to a month start or end a given number of months away.
224225
"""
226+
import cftime
227+
225228
delta_year = (date.month + months) // 12
226229
month = (date.month + months) % 12
227230

@@ -237,11 +240,14 @@ def _shift_month(date, months, day_option="start"):
237240
day = _days_in_month(reference)
238241
else:
239242
raise ValueError(day_option)
240-
# dayofwk=-1 is required to update the dayofwk and dayofyr attributes of
241-
# the returned date object in versions of cftime between 1.0.2 and
242-
# 1.0.3.4. It can be removed for versions of cftime greater than
243-
# 1.0.3.4.
244-
return date.replace(year=year, month=month, day=day, dayofwk=-1)
243+
if LooseVersion(cftime.__version__) < LooseVersion("1.0.4"):
244+
# dayofwk=-1 is required to update the dayofwk and dayofyr attributes of
245+
# the returned date object in versions of cftime between 1.0.2 and
246+
# 1.0.3.4. It can be removed for versions of cftime greater than
247+
# 1.0.3.4.
248+
return date.replace(year=year, month=month, day=day, dayofwk=-1)
249+
else:
250+
return date.replace(year=year, month=month, day=day)
245251

246252

247253
def roll_qtrday(other, n, month, day_option, modby=3):

xarray/coding/cftimeindex.py

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,8 @@ def parse_iso8601(datetime_string):
9696

9797

9898
def _parse_iso8601_with_reso(date_type, timestr):
99+
import cftime
100+
99101
default = date_type(1, 1, 1)
100102
result = parse_iso8601(timestr)
101103
replace = {}
@@ -107,12 +109,12 @@ def _parse_iso8601_with_reso(date_type, timestr):
107109
# TODO: Consider adding support for sub-second resolution?
108110
replace[attr] = int(value)
109111
resolution = attr
110-
111-
# dayofwk=-1 is required to update the dayofwk and dayofyr attributes of
112-
# the returned date object in versions of cftime between 1.0.2 and
113-
# 1.0.3.4. It can be removed for versions of cftime greater than
114-
# 1.0.3.4.
115-
replace["dayofwk"] = -1
112+
if LooseVersion(cftime.__version__) < LooseVersion("1.0.4"):
113+
# dayofwk=-1 is required to update the dayofwk and dayofyr attributes of
114+
# the returned date object in versions of cftime between 1.0.2 and
115+
# 1.0.3.4. It can be removed for versions of cftime greater than
116+
# 1.0.3.4.
117+
replace["dayofwk"] = -1
116118
return default.replace(**replace), resolution
117119

118120

xarray/tests/test_dataset.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3593,6 +3593,19 @@ def test_resample_old_api(self):
35933593
with raises_regex(TypeError, r"resample\(\) no longer supports"):
35943594
ds.resample("1D", dim="time")
35953595

3596+
def test_resample_ds_da_are_the_same(self):
3597+
time = pd.date_range("2000-01-01", freq="6H", periods=365 * 4)
3598+
ds = xr.Dataset(
3599+
{
3600+
"foo": (("time", "x"), np.random.randn(365 * 4, 5)),
3601+
"time": time,
3602+
"x": np.arange(5),
3603+
}
3604+
)
3605+
assert_identical(
3606+
ds.resample(time="M").mean()["foo"], ds.foo.resample(time="M").mean()
3607+
)
3608+
35963609
def test_ds_resample_apply_func_args(self):
35973610
def func(arg1, arg2, arg3=0.0):
35983611
return arg1.mean("time") + arg2 + arg3

0 commit comments

Comments
 (0)