cf-xarray 0.11.1__tar.gz → 0.11.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/PKG-INFO +1 -1
- cf_xarray-0.11.2/cf_xarray/_version.py +1 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/accessor.py +40 -10
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/sgrid.py +25 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/test_accessor.py +75 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray.egg-info/PKG-INFO +1 -1
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/sgrid_ugrid.md +17 -0
- cf_xarray-0.11.1/cf_xarray/_version.py +0 -1
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.binder/environment.yml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.deepsource.toml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.github/dependabot.yml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.github/release.yml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.github/workflows/ci.yaml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.github/workflows/parse_logs.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.github/workflows/pypi.yaml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.github/workflows/testpypi-release.yaml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.github/workflows/upstream-dev-ci.yaml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.gitignore +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.pre-commit-config.yaml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.readthedocs.yml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/.tributors +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/CITATION.cff +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/LICENSE +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/README.rst +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/__init__.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/coding.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/criteria.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/datasets.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/formatting.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/geometry.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/groupers.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/helpers.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/options.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/parametric.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/py.typed +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/scripts/make_doc.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/scripts/print_versions.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/__init__.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/conftest.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/test_coding.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/test_geometry.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/test_groupers.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/test_helpers.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/test_options.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/test_parametric.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/test_scripts.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/tests/test_units.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/units.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray/utils.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray.egg-info/SOURCES.txt +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray.egg-info/dependency_links.txt +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray.egg-info/requires.txt +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/cf_xarray.egg-info/top_level.txt +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/codecov.yml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/2D_bounds_averaged.png +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/2D_bounds_error.png +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/2D_bounds_nonunique.png +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/Makefile +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/_static/dataset-diagram-logo.tex +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/_static/full-logo.png +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/_static/logo.png +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/_static/logo.svg +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/_static/rich-repr-example.png +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/_static/style.css +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/api.rst +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/bounds.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/cartopy_rotated_pole.png +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/coding.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/conf.py +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/contributing.rst +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/coord_axes.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/custom-criteria.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/dsg.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/examples/introduction.ipynb +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/faq.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/flags.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/geometry.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/grid_mappings.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/howtouse.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/index.rst +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/make.bat +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/parametricz.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/plotting.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/provenance.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/quickstart.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/roadmap.rst +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/selecting.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/units.md +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/doc/whats-new.rst +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/pyproject.toml +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/setup.cfg +0 -0
- {cf_xarray-0.11.1 → cf_xarray-0.11.2}/uv.lock +0 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.11.2"
|
|
@@ -556,6 +556,37 @@ def _parse_grid_mapping_attribute(
|
|
|
556
556
|
return Frozen(result)
|
|
557
557
|
|
|
558
558
|
|
|
559
|
+
def _hashable_attrs(attrs: Mapping[Any, Any]) -> tuple:
|
|
560
|
+
"""Return a hashable, order-independent representation of an attrs mapping.
|
|
561
|
+
|
|
562
|
+
List- and array-valued attributes (e.g. ``standard_parallel``) are coerced
|
|
563
|
+
to tuples so the result can be used as an ``lru_cache`` key.
|
|
564
|
+
"""
|
|
565
|
+
frozen = []
|
|
566
|
+
for key, value in attrs.items():
|
|
567
|
+
if hasattr(value, "tolist"): # numpy scalars/arrays
|
|
568
|
+
value = value.tolist()
|
|
569
|
+
if isinstance(value, list | tuple):
|
|
570
|
+
value = tuple(value)
|
|
571
|
+
frozen.append((key, value))
|
|
572
|
+
frozen.sort(key=lambda kv: repr(kv[0]))
|
|
573
|
+
return tuple(frozen)
|
|
574
|
+
|
|
575
|
+
|
|
576
|
+
@functools.lru_cache(maxsize=256)
|
|
577
|
+
def _crs_from_cf_attrs(attrs_items: tuple) -> Any:
|
|
578
|
+
"""Build a ``pyproj.CRS`` from frozen CF grid-mapping attrs (memoized).
|
|
579
|
+
|
|
580
|
+
``pyproj.CRS.from_cf`` re-parses the datum/ellipsoid on every call, which is
|
|
581
|
+
expensive for grid mappings carrying explicit ellipsoid parameters (e.g.
|
|
582
|
+
geostationary). A dataset routinely references the same grid mapping from
|
|
583
|
+
many variables, so cache on the attribute items.
|
|
584
|
+
"""
|
|
585
|
+
import pyproj
|
|
586
|
+
|
|
587
|
+
return pyproj.CRS.from_cf(dict(attrs_items))
|
|
588
|
+
|
|
589
|
+
|
|
559
590
|
def _create_grid_mapping(
|
|
560
591
|
var_name: str,
|
|
561
592
|
ds: Dataset,
|
|
@@ -669,7 +700,7 @@ def _create_grid_mapping(
|
|
|
669
700
|
}
|
|
670
701
|
)
|
|
671
702
|
else:
|
|
672
|
-
crs =
|
|
703
|
+
crs = _crs_from_cf_attrs(_hashable_attrs(var.attrs))
|
|
673
704
|
|
|
674
705
|
# Get associated coordinate variables, fallback to dimension names
|
|
675
706
|
coordinates: list[Hashable] = grid_mapping_dict.get(var_name, [])
|
|
@@ -2076,17 +2107,14 @@ class CFAccessor:
|
|
|
2076
2107
|
"""
|
|
2077
2108
|
|
|
2078
2109
|
obj = self._obj
|
|
2110
|
+
if isinstance(obj, DataArray):
|
|
2111
|
+
variables = [*obj.coords.variables.values(), obj.variable]
|
|
2112
|
+
else:
|
|
2113
|
+
variables = list(obj.variables.values())
|
|
2079
2114
|
all_attrs = [
|
|
2080
|
-
ChainMap(
|
|
2081
|
-
for
|
|
2115
|
+
ChainMap(var.attrs, var.encoding).get("cell_measures", "")
|
|
2116
|
+
for var in variables
|
|
2082
2117
|
]
|
|
2083
|
-
if isinstance(obj, DataArray):
|
|
2084
|
-
all_attrs += [ChainMap(obj.attrs, obj.encoding).get("cell_measures", "")]
|
|
2085
|
-
elif isinstance(obj, Dataset):
|
|
2086
|
-
all_attrs += [
|
|
2087
|
-
ChainMap(da.attrs, da.encoding).get("cell_measures", "")
|
|
2088
|
-
for da in obj.data_vars.values()
|
|
2089
|
-
]
|
|
2090
2118
|
as_dataset = self._maybe_to_dataset().reset_coords()
|
|
2091
2119
|
|
|
2092
2120
|
keys: dict[str, str] = {}
|
|
@@ -2269,6 +2297,8 @@ class CFAccessor:
|
|
|
2269
2297
|
|
|
2270
2298
|
if grid := attrs_or_encoding.get("grid", None):
|
|
2271
2299
|
coords["grid"] = [grid]
|
|
2300
|
+
if isinstance(self._obj, Dataset):
|
|
2301
|
+
coords["coordinates"].extend(sgrid.get_topology_coords(self._obj, grid))
|
|
2272
2302
|
|
|
2273
2303
|
if grid_mapping_attr := attrs_or_encoding.get("grid_mapping", None):
|
|
2274
2304
|
# Parse grid mapping variables and their coordinates
|
|
@@ -11,6 +11,31 @@ SGRID_DIM_ATTRS = [
|
|
|
11
11
|
# "edge3_dimensions",
|
|
12
12
|
]
|
|
13
13
|
|
|
14
|
+
SGRID_COORD_ATTRS = [
|
|
15
|
+
"node_coordinates",
|
|
16
|
+
"face_coordinates",
|
|
17
|
+
"edge1_coordinates",
|
|
18
|
+
"edge2_coordinates",
|
|
19
|
+
"volume_coordinates",
|
|
20
|
+
]
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
def get_topology_coords(ds, grid_var_name):
|
|
24
|
+
"""Return coordinate variable names referenced by an SGRID topology variable.
|
|
25
|
+
|
|
26
|
+
Reads ``node_coordinates``, ``face_coordinates``, ``edge{1,2}_coordinates``,
|
|
27
|
+
and ``volume_coordinates`` from the topology variable's attrs and filters
|
|
28
|
+
to names that are actually present in ``ds``.
|
|
29
|
+
"""
|
|
30
|
+
if grid_var_name not in ds.variables:
|
|
31
|
+
return []
|
|
32
|
+
grid_attrs = ds[grid_var_name].attrs
|
|
33
|
+
names: list[str] = []
|
|
34
|
+
for attr_name in SGRID_COORD_ATTRS:
|
|
35
|
+
if coord_str := grid_attrs.get(attr_name):
|
|
36
|
+
names.extend(n for n in coord_str.split() if n in ds.variables)
|
|
37
|
+
return names
|
|
38
|
+
|
|
14
39
|
|
|
15
40
|
def parse_axes(ds):
|
|
16
41
|
import re
|
|
@@ -1254,6 +1254,44 @@ def test_grid_mappings_property():
|
|
|
1254
1254
|
assert gm.coordinates == ("x", "y")
|
|
1255
1255
|
|
|
1256
1256
|
|
|
1257
|
+
@requires_pyproj
|
|
1258
|
+
def test_grid_mappings_crs_construction_is_cached(monkeypatch):
|
|
1259
|
+
"""``pyproj.CRS.from_cf`` is memoized per grid-mapping attrs.
|
|
1260
|
+
|
|
1261
|
+
Building the CRS re-parses the datum/ellipsoid on every call. A dataset
|
|
1262
|
+
references the same grid mapping from many variables and the property may
|
|
1263
|
+
be accessed repeatedly, so each distinct grid mapping should be built once.
|
|
1264
|
+
"""
|
|
1265
|
+
import pyproj
|
|
1266
|
+
|
|
1267
|
+
from ..accessor import _crs_from_cf_attrs
|
|
1268
|
+
|
|
1269
|
+
_crs_from_cf_attrs.cache_clear()
|
|
1270
|
+
|
|
1271
|
+
from ..datasets import hrrrds
|
|
1272
|
+
|
|
1273
|
+
ds = hrrrds
|
|
1274
|
+
|
|
1275
|
+
calls = {"n": 0}
|
|
1276
|
+
orig = pyproj.CRS.from_cf
|
|
1277
|
+
|
|
1278
|
+
def counting_from_cf(*args, **kwargs):
|
|
1279
|
+
calls["n"] += 1
|
|
1280
|
+
return orig(*args, **kwargs)
|
|
1281
|
+
|
|
1282
|
+
monkeypatch.setattr(pyproj.CRS, "from_cf", staticmethod(counting_from_cf))
|
|
1283
|
+
|
|
1284
|
+
# Repeated property accesses, including via a DataArray, must not rebuild
|
|
1285
|
+
# the same CRS: hrrrds has 3 distinct grid mappings, each built once.
|
|
1286
|
+
ds.cf.grid_mappings
|
|
1287
|
+
ds.cf.grid_mappings
|
|
1288
|
+
ds.foo.cf.grid_mappings
|
|
1289
|
+
|
|
1290
|
+
assert calls["n"] == 3
|
|
1291
|
+
|
|
1292
|
+
_crs_from_cf_attrs.cache_clear()
|
|
1293
|
+
|
|
1294
|
+
|
|
1257
1295
|
@requires_pyproj
|
|
1258
1296
|
def test_grid_mappings_coordinates_attribute():
|
|
1259
1297
|
"""Test that coordinates attribute is always populated correctly for DataArray grid mappings."""
|
|
@@ -2484,6 +2522,43 @@ def test_sgrid():
|
|
|
2484
2522
|
}
|
|
2485
2523
|
|
|
2486
2524
|
|
|
2525
|
+
def test_sgrid_includes_topology_coordinates():
|
|
2526
|
+
"""Variables referenced in node/face/edge/volume_coordinates of the
|
|
2527
|
+
grid_topology variable should be pulled in by ds.cf[[var]]."""
|
|
2528
|
+
roms = sgrid_roms.copy()
|
|
2529
|
+
for pos in ("psi", "rho", "u", "v"):
|
|
2530
|
+
roms[f"lon_{pos}"] = ((f"xi_{pos}", f"eta_{pos}"), np.zeros((2, 2)))
|
|
2531
|
+
roms[f"lat_{pos}"] = ((f"xi_{pos}", f"eta_{pos}"), np.zeros((2, 2)))
|
|
2532
|
+
|
|
2533
|
+
expected_coord_vars = {
|
|
2534
|
+
"lon_psi",
|
|
2535
|
+
"lat_psi",
|
|
2536
|
+
"lon_rho",
|
|
2537
|
+
"lat_rho",
|
|
2538
|
+
"lon_u",
|
|
2539
|
+
"lat_u",
|
|
2540
|
+
"lon_v",
|
|
2541
|
+
"lat_v",
|
|
2542
|
+
}
|
|
2543
|
+
assoc = roms.cf.get_associated_variable_names("u")
|
|
2544
|
+
assert expected_coord_vars.issubset(set(assoc["coordinates"]))
|
|
2545
|
+
|
|
2546
|
+
subset = roms.cf[["u"]]
|
|
2547
|
+
assert "grid" in subset.variables
|
|
2548
|
+
assert expected_coord_vars.issubset(set(subset.variables))
|
|
2549
|
+
|
|
2550
|
+
# only dim-compatible coords attach to the DataArray form
|
|
2551
|
+
u_da = roms.cf["u"]
|
|
2552
|
+
assert {"lon_u", "lat_u"}.issubset(set(u_da.coords))
|
|
2553
|
+
|
|
2554
|
+
delft = sgrid_delft.copy()
|
|
2555
|
+
delft["node_lon"] = (("inode", "jnode"), np.zeros((2, 2)))
|
|
2556
|
+
delft["node_lat"] = (("inode", "jnode"), np.zeros((2, 2)))
|
|
2557
|
+
delft["foo"] = (("icell", "jcell"), np.ones((2, 2)), {"grid": "grid"})
|
|
2558
|
+
delft_subset = delft.cf[["foo"]]
|
|
2559
|
+
assert {"grid", "node_lon", "node_lat"}.issubset(set(delft_subset.variables))
|
|
2560
|
+
|
|
2561
|
+
|
|
2487
2562
|
def test_ancillary_variables_extra_dim():
|
|
2488
2563
|
ds = xr.Dataset(
|
|
2489
2564
|
{
|
|
@@ -61,6 +61,23 @@ only `xi_u`, `eta_u` are listed in the repr even though the attributes on the `g
|
|
|
61
61
|
variable `grid` list many more dimension names.
|
|
62
62
|
```
|
|
63
63
|
|
|
64
|
+
### Coordinate variables
|
|
65
|
+
|
|
66
|
+
`cf_xarray` also follows the `node_coordinates`, `face_coordinates`,
|
|
67
|
+
`edge1_coordinates`, `edge2_coordinates`, and `volume_coordinates` attributes
|
|
68
|
+
on the `grid_topology` variable. When you select a data variable that
|
|
69
|
+
references a `grid_topology` via its `grid` attribute, the referenced
|
|
70
|
+
coordinate variables are pulled in alongside it:
|
|
71
|
+
|
|
72
|
+
```python
|
|
73
|
+
ds.cf[["u"]] # includes `grid`, lon_psi/lat_psi, lon_rho/lat_rho, ...
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
Only names actually present in the dataset are propagated. For the
|
|
77
|
+
`DataArray` form (`ds.cf["u"]`) xarray only attaches coordinates whose
|
|
78
|
+
dimensions are compatible with the variable, so e.g. only `lon_u`/`lat_u`
|
|
79
|
+
appear as coords on `u`.
|
|
80
|
+
|
|
64
81
|
## UGRID
|
|
65
82
|
|
|
66
83
|
### Topology variable
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
__version__ = "0.11.1"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|