ncfunc 0.1.0__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.
- ncfunc-0.1.0/PKG-INFO +192 -0
- ncfunc-0.1.0/README.md +180 -0
- ncfunc-0.1.0/pyproject.toml +34 -0
- ncfunc-0.1.0/pyproject.toml.orig +29 -0
- ncfunc-0.1.0/src/ncfunc/__init__.py +37 -0
- ncfunc-0.1.0/src/ncfunc/core.py +1000 -0
ncfunc-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
|
+
Name: ncfunc
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Add your description here
|
|
5
|
+
Author: lkkbox
|
|
6
|
+
Author-email: lkkbox <mail@mail.com>
|
|
7
|
+
Requires-Dist: datenum>=0.1.0
|
|
8
|
+
Requires-Dist: netcdf4>=1.7.3
|
|
9
|
+
Requires-Dist: numpy>=1.24
|
|
10
|
+
Requires-Python: >=3.10
|
|
11
|
+
Description-Content-Type: text/markdown
|
|
12
|
+
|
|
13
|
+
# ncfunc
|
|
14
|
+
|
|
15
|
+
Functional-style reading and writing of NetCDF data files.
|
|
16
|
+
|
|
17
|
+
`ncfunc` wraps [netCDF4](https://github.com/Unidata/netcdf4-python) and trades
|
|
18
|
+
its open-handle, object-oriented style for small stateless functions: every
|
|
19
|
+
call opens the file, does one thing, closes it, and leaves nothing behind.
|
|
20
|
+
Along the way it decodes CF time coordinates, subsets by coordinate bounds,
|
|
21
|
+
and turns opaque netCDF4 errors into messages that say what failed, where,
|
|
22
|
+
and why - keeping the original exception chained underneath.
|
|
23
|
+
|
|
24
|
+
## Features
|
|
25
|
+
|
|
26
|
+
- **Stateless functions** - no `Dataset` handles to open, close or leak
|
|
27
|
+
- **Readable errors** - Exceptions are raised with details such as file path,
|
|
28
|
+
variable name, dimension name, etc.
|
|
29
|
+
- **Time decoding** - `read_time` decodes CF `'delta since epoch'` units to
|
|
30
|
+
[datenum](https://pypi.org/project/datenum/) serials, including fixed-length
|
|
31
|
+
calendars (`360_day`, `365_day`)
|
|
32
|
+
- **Bounds-based subsetting** - `read_within` slices variables by coordinate
|
|
33
|
+
ranges instead of index arithmetic
|
|
34
|
+
- **Cached metadata** - structure queries reuse a path-keyed cache that
|
|
35
|
+
auto-refreshes when a file's mtime changes (`DatasetMeta`)
|
|
36
|
+
- **One-shot writer** - `save()` creates dimensions, coordinates and the
|
|
37
|
+
variable in a single call, with overwrite protection
|
|
38
|
+
|
|
39
|
+
## Installation
|
|
40
|
+
|
|
41
|
+
Requires Python >= 3.10, with dependencies numpy, netCDF4 and datenum installed
|
|
42
|
+
automatically:
|
|
43
|
+
|
|
44
|
+
```sh
|
|
45
|
+
pip install ncfunc
|
|
46
|
+
# or
|
|
47
|
+
uv add ncfunc
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
## Quickstart
|
|
51
|
+
|
|
52
|
+
```python
|
|
53
|
+
import ncfunc as ncf
|
|
54
|
+
|
|
55
|
+
file = "tests/ersst_2022-2024.nc"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## API overview
|
|
59
|
+
|
|
60
|
+
| function | purpose |
|
|
61
|
+
| --- | --- |
|
|
62
|
+
| `var_names(path)` | variable names |
|
|
63
|
+
| `dim_names(path, var)` | dimension names of a variable |
|
|
64
|
+
| `shape(path, var)` / `ndim(path, var)` | shape / rank of a variable |
|
|
65
|
+
| `attr_names(path, var)` / `attr_val(path, var, attr)` | attributes of a variable, or of the file with `var='/'` |
|
|
66
|
+
| `var_names_include(...)` | find variables by substring and rank |
|
|
67
|
+
| `attr_names_include(...)` | find attributes by substring |
|
|
68
|
+
| `read(path, var, subsets?)` | read a variable into `np.ndarray` |
|
|
69
|
+
| `read_time(path, ...)` | read and decode a time coordinate to datenum values |
|
|
70
|
+
| `read_within(path, var, withins, ...)` | bounds-based subset read with coordinates |
|
|
71
|
+
| `write(path, var, data, subsets?)` | write into an existing variable |
|
|
72
|
+
| `create(path, var, dim_specs, ...)` | create a variable (+ dimensions), idempotently |
|
|
73
|
+
| `save(path, data, ...)` | create + write a variable and its coordinates in one call |
|
|
74
|
+
| `write_attr(path, var, attr, value)` | set a variable or root (`'/'`) attribute |
|
|
75
|
+
| `DatasetMeta(path)` | static structural snapshot, cached per resolved path |
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
### Inspect metadata
|
|
79
|
+
|
|
80
|
+
```python
|
|
81
|
+
>>> ncf.var_names(file)
|
|
82
|
+
('time', 'lon', 'lat', 'sst', 'ssta')
|
|
83
|
+
|
|
84
|
+
>>> ncf.shape(file, 'sst')
|
|
85
|
+
(36, 121, 240)
|
|
86
|
+
|
|
87
|
+
>>> ncf.dim_names(file, 'sst')
|
|
88
|
+
('time', 'lat', 'lon')
|
|
89
|
+
|
|
90
|
+
>>> ncf.attr_val(file, '/', 'title') # '/' selects the file's root attributes
|
|
91
|
+
'NOAA monthly ERSSTv6 (in situ only)'
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
Search helpers locate variables and attributes by substring, and insist on an
|
|
95
|
+
unambiguous match (by rank or count) before returning:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
>>> ncf.var_names_include(file, ('sst',), accept_ndims=3)
|
|
99
|
+
('sst', 'ssta')
|
|
100
|
+
|
|
101
|
+
>>> ncf.var_names_include(file, name_includes=('sst',), accept_ndims=3, accept_counts=(2,))
|
|
102
|
+
('sst', 'ssta')
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Read data
|
|
106
|
+
|
|
107
|
+
```python
|
|
108
|
+
sst = ncf.read(file, 'sst') # whole variable
|
|
109
|
+
top = ncf.read(file, 'sst', ((slice(-4, None),) * 3)) # last 4 steps of every dim
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
### Decode time
|
|
113
|
+
|
|
114
|
+
```python
|
|
115
|
+
>>> import datenum as dn
|
|
116
|
+
>>> t = ncf.read_time(file)
|
|
117
|
+
>>> dn.to_string(t[0]), dn.to_string(t[-1])
|
|
118
|
+
('2022-01-15 00:00:00', '2024-12-15 00:00:00')
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
The time variable, its `units` attribute and its `calendar` attribute are all
|
|
122
|
+
guessed; pass `time_name`, `unit_name`, `calendar_name` explicitly to override.
|
|
123
|
+
Month/year-based units decode via month arithmetic, day-based ones against the
|
|
124
|
+
declared calendar - including `360_day` and `365_day` fixed calendars.
|
|
125
|
+
|
|
126
|
+
### Subset by bounds, not indices
|
|
127
|
+
|
|
128
|
+
`read_within` takes one `(lower, upper)` pair per dimension of the variable
|
|
129
|
+
(`None` = unbounded), reads only what intersects, and returns both the data
|
|
130
|
+
and the bounded coordinates. Coordinates come back ascending even when stored
|
|
131
|
+
descending; the data is flipped to stay aligned:
|
|
132
|
+
|
|
133
|
+
```python
|
|
134
|
+
>>> sst, (time, lat, lon) = ncf.read_within(
|
|
135
|
+
... file,
|
|
136
|
+
... 'sst',
|
|
137
|
+
... withins=((None, None), (-30.0, 30.0), (150.0, 210.0)),
|
|
138
|
+
... )
|
|
139
|
+
>>> sst.shape, lat[0], lat[-1]
|
|
140
|
+
((36, 41, 41), -30.0, 30.0)
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
The time dimension is found by guessing a time-named coordinate; point at it
|
|
144
|
+
explicitly with `idim_time=<index>` if the guess would be wrong, or disable
|
|
145
|
+
time handling with `decode_time=False`.
|
|
146
|
+
|
|
147
|
+
### Write data
|
|
148
|
+
|
|
149
|
+
`save` writes a variable plus its dimensions in one shot. The first entry is
|
|
150
|
+
the variable, the rest are its 1-D dimensions:
|
|
151
|
+
|
|
152
|
+
```python
|
|
153
|
+
import numpy as np
|
|
154
|
+
|
|
155
|
+
ncf.save(
|
|
156
|
+
"out.nc",
|
|
157
|
+
{
|
|
158
|
+
"tas": np.arange(12, dtype="f4").reshape(3, 4),
|
|
159
|
+
"time": np.array([0, 31, 59]),
|
|
160
|
+
"lon": np.linspace(0.5, 3.5, 4),
|
|
161
|
+
},
|
|
162
|
+
)
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
This creates `out.nc` with dimensions `time` and `lon`, coordinate variables
|
|
166
|
+
stamped with CF-ish attributes (`axis`, `units`, `standard_name`), and the
|
|
167
|
+
compressed `tas` variable. If `tas` already exists in the file, `save` asks
|
|
168
|
+
for confirmation on the terminal; `overwrite_var=True` and `overwrite_dim=True`
|
|
169
|
+
skips the question.
|
|
170
|
+
|
|
171
|
+
For finer control, use the pieces directly:
|
|
172
|
+
|
|
173
|
+
```python
|
|
174
|
+
ncf.create(path, "tas", {"time": 3, "lon": 4}) # idempotent; missing dims created
|
|
175
|
+
ncf.write(path, "tas", data) # full write, shape must match
|
|
176
|
+
ncf.write(path, "tas", data, ((slice(0, 1), slice(None)),)) # or by slices
|
|
177
|
+
ncf.write_attr(path, "/", "history", "created today") # '/' = root attribute
|
|
178
|
+
```
|
|
179
|
+
|
|
180
|
+
## Development
|
|
181
|
+
|
|
182
|
+
```sh
|
|
183
|
+
uv sync # install dependencies
|
|
184
|
+
uv run pytest # run the test suite
|
|
185
|
+
uv run ruff check src/ tests/
|
|
186
|
+
uv run ruff format --check src/ tests/
|
|
187
|
+
uv run ty check src/ tests/
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
## License
|
|
191
|
+
|
|
192
|
+
MIT - see [LICENSE](LICENSE).
|
ncfunc-0.1.0/README.md
ADDED
|
@@ -0,0 +1,180 @@
|
|
|
1
|
+
# ncfunc
|
|
2
|
+
|
|
3
|
+
Functional-style reading and writing of NetCDF data files.
|
|
4
|
+
|
|
5
|
+
`ncfunc` wraps [netCDF4](https://github.com/Unidata/netcdf4-python) and trades
|
|
6
|
+
its open-handle, object-oriented style for small stateless functions: every
|
|
7
|
+
call opens the file, does one thing, closes it, and leaves nothing behind.
|
|
8
|
+
Along the way it decodes CF time coordinates, subsets by coordinate bounds,
|
|
9
|
+
and turns opaque netCDF4 errors into messages that say what failed, where,
|
|
10
|
+
and why - keeping the original exception chained underneath.
|
|
11
|
+
|
|
12
|
+
## Features
|
|
13
|
+
|
|
14
|
+
- **Stateless functions** - no `Dataset` handles to open, close or leak
|
|
15
|
+
- **Readable errors** - Exceptions are raised with details such as file path,
|
|
16
|
+
variable name, dimension name, etc.
|
|
17
|
+
- **Time decoding** - `read_time` decodes CF `'delta since epoch'` units to
|
|
18
|
+
[datenum](https://pypi.org/project/datenum/) serials, including fixed-length
|
|
19
|
+
calendars (`360_day`, `365_day`)
|
|
20
|
+
- **Bounds-based subsetting** - `read_within` slices variables by coordinate
|
|
21
|
+
ranges instead of index arithmetic
|
|
22
|
+
- **Cached metadata** - structure queries reuse a path-keyed cache that
|
|
23
|
+
auto-refreshes when a file's mtime changes (`DatasetMeta`)
|
|
24
|
+
- **One-shot writer** - `save()` creates dimensions, coordinates and the
|
|
25
|
+
variable in a single call, with overwrite protection
|
|
26
|
+
|
|
27
|
+
## Installation
|
|
28
|
+
|
|
29
|
+
Requires Python >= 3.10, with dependencies numpy, netCDF4 and datenum installed
|
|
30
|
+
automatically:
|
|
31
|
+
|
|
32
|
+
```sh
|
|
33
|
+
pip install ncfunc
|
|
34
|
+
# or
|
|
35
|
+
uv add ncfunc
|
|
36
|
+
```
|
|
37
|
+
|
|
38
|
+
## Quickstart
|
|
39
|
+
|
|
40
|
+
```python
|
|
41
|
+
import ncfunc as ncf
|
|
42
|
+
|
|
43
|
+
file = "tests/ersst_2022-2024.nc"
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## API overview
|
|
47
|
+
|
|
48
|
+
| function | purpose |
|
|
49
|
+
| --- | --- |
|
|
50
|
+
| `var_names(path)` | variable names |
|
|
51
|
+
| `dim_names(path, var)` | dimension names of a variable |
|
|
52
|
+
| `shape(path, var)` / `ndim(path, var)` | shape / rank of a variable |
|
|
53
|
+
| `attr_names(path, var)` / `attr_val(path, var, attr)` | attributes of a variable, or of the file with `var='/'` |
|
|
54
|
+
| `var_names_include(...)` | find variables by substring and rank |
|
|
55
|
+
| `attr_names_include(...)` | find attributes by substring |
|
|
56
|
+
| `read(path, var, subsets?)` | read a variable into `np.ndarray` |
|
|
57
|
+
| `read_time(path, ...)` | read and decode a time coordinate to datenum values |
|
|
58
|
+
| `read_within(path, var, withins, ...)` | bounds-based subset read with coordinates |
|
|
59
|
+
| `write(path, var, data, subsets?)` | write into an existing variable |
|
|
60
|
+
| `create(path, var, dim_specs, ...)` | create a variable (+ dimensions), idempotently |
|
|
61
|
+
| `save(path, data, ...)` | create + write a variable and its coordinates in one call |
|
|
62
|
+
| `write_attr(path, var, attr, value)` | set a variable or root (`'/'`) attribute |
|
|
63
|
+
| `DatasetMeta(path)` | static structural snapshot, cached per resolved path |
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
### Inspect metadata
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
>>> ncf.var_names(file)
|
|
70
|
+
('time', 'lon', 'lat', 'sst', 'ssta')
|
|
71
|
+
|
|
72
|
+
>>> ncf.shape(file, 'sst')
|
|
73
|
+
(36, 121, 240)
|
|
74
|
+
|
|
75
|
+
>>> ncf.dim_names(file, 'sst')
|
|
76
|
+
('time', 'lat', 'lon')
|
|
77
|
+
|
|
78
|
+
>>> ncf.attr_val(file, '/', 'title') # '/' selects the file's root attributes
|
|
79
|
+
'NOAA monthly ERSSTv6 (in situ only)'
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
Search helpers locate variables and attributes by substring, and insist on an
|
|
83
|
+
unambiguous match (by rank or count) before returning:
|
|
84
|
+
|
|
85
|
+
```python
|
|
86
|
+
>>> ncf.var_names_include(file, ('sst',), accept_ndims=3)
|
|
87
|
+
('sst', 'ssta')
|
|
88
|
+
|
|
89
|
+
>>> ncf.var_names_include(file, name_includes=('sst',), accept_ndims=3, accept_counts=(2,))
|
|
90
|
+
('sst', 'ssta')
|
|
91
|
+
```
|
|
92
|
+
|
|
93
|
+
### Read data
|
|
94
|
+
|
|
95
|
+
```python
|
|
96
|
+
sst = ncf.read(file, 'sst') # whole variable
|
|
97
|
+
top = ncf.read(file, 'sst', ((slice(-4, None),) * 3)) # last 4 steps of every dim
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Decode time
|
|
101
|
+
|
|
102
|
+
```python
|
|
103
|
+
>>> import datenum as dn
|
|
104
|
+
>>> t = ncf.read_time(file)
|
|
105
|
+
>>> dn.to_string(t[0]), dn.to_string(t[-1])
|
|
106
|
+
('2022-01-15 00:00:00', '2024-12-15 00:00:00')
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
The time variable, its `units` attribute and its `calendar` attribute are all
|
|
110
|
+
guessed; pass `time_name`, `unit_name`, `calendar_name` explicitly to override.
|
|
111
|
+
Month/year-based units decode via month arithmetic, day-based ones against the
|
|
112
|
+
declared calendar - including `360_day` and `365_day` fixed calendars.
|
|
113
|
+
|
|
114
|
+
### Subset by bounds, not indices
|
|
115
|
+
|
|
116
|
+
`read_within` takes one `(lower, upper)` pair per dimension of the variable
|
|
117
|
+
(`None` = unbounded), reads only what intersects, and returns both the data
|
|
118
|
+
and the bounded coordinates. Coordinates come back ascending even when stored
|
|
119
|
+
descending; the data is flipped to stay aligned:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
>>> sst, (time, lat, lon) = ncf.read_within(
|
|
123
|
+
... file,
|
|
124
|
+
... 'sst',
|
|
125
|
+
... withins=((None, None), (-30.0, 30.0), (150.0, 210.0)),
|
|
126
|
+
... )
|
|
127
|
+
>>> sst.shape, lat[0], lat[-1]
|
|
128
|
+
((36, 41, 41), -30.0, 30.0)
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
The time dimension is found by guessing a time-named coordinate; point at it
|
|
132
|
+
explicitly with `idim_time=<index>` if the guess would be wrong, or disable
|
|
133
|
+
time handling with `decode_time=False`.
|
|
134
|
+
|
|
135
|
+
### Write data
|
|
136
|
+
|
|
137
|
+
`save` writes a variable plus its dimensions in one shot. The first entry is
|
|
138
|
+
the variable, the rest are its 1-D dimensions:
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
import numpy as np
|
|
142
|
+
|
|
143
|
+
ncf.save(
|
|
144
|
+
"out.nc",
|
|
145
|
+
{
|
|
146
|
+
"tas": np.arange(12, dtype="f4").reshape(3, 4),
|
|
147
|
+
"time": np.array([0, 31, 59]),
|
|
148
|
+
"lon": np.linspace(0.5, 3.5, 4),
|
|
149
|
+
},
|
|
150
|
+
)
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
This creates `out.nc` with dimensions `time` and `lon`, coordinate variables
|
|
154
|
+
stamped with CF-ish attributes (`axis`, `units`, `standard_name`), and the
|
|
155
|
+
compressed `tas` variable. If `tas` already exists in the file, `save` asks
|
|
156
|
+
for confirmation on the terminal; `overwrite_var=True` and `overwrite_dim=True`
|
|
157
|
+
skips the question.
|
|
158
|
+
|
|
159
|
+
For finer control, use the pieces directly:
|
|
160
|
+
|
|
161
|
+
```python
|
|
162
|
+
ncf.create(path, "tas", {"time": 3, "lon": 4}) # idempotent; missing dims created
|
|
163
|
+
ncf.write(path, "tas", data) # full write, shape must match
|
|
164
|
+
ncf.write(path, "tas", data, ((slice(0, 1), slice(None)),)) # or by slices
|
|
165
|
+
ncf.write_attr(path, "/", "history", "created today") # '/' = root attribute
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
## Development
|
|
169
|
+
|
|
170
|
+
```sh
|
|
171
|
+
uv sync # install dependencies
|
|
172
|
+
uv run pytest # run the test suite
|
|
173
|
+
uv run ruff check src/ tests/
|
|
174
|
+
uv run ruff format --check src/ tests/
|
|
175
|
+
uv run ty check src/ tests/
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
## License
|
|
179
|
+
|
|
180
|
+
MIT - see [LICENSE](LICENSE).
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ncfunc"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Add your description here"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.10"
|
|
7
|
+
dependencies = [
|
|
8
|
+
"datenum>=0.1.0",
|
|
9
|
+
"netcdf4>=1.7.3",
|
|
10
|
+
"numpy>=1.24",
|
|
11
|
+
]
|
|
12
|
+
|
|
13
|
+
[[project.authors]]
|
|
14
|
+
name = "lkkbox"
|
|
15
|
+
email = "mail@mail.com"
|
|
16
|
+
|
|
17
|
+
[project.scripts]
|
|
18
|
+
ncfunc = "ncfunc:main"
|
|
19
|
+
|
|
20
|
+
[build-system]
|
|
21
|
+
requires = ["uv_build>=0.12.1,<0.13.0"]
|
|
22
|
+
build-backend = "uv_build"
|
|
23
|
+
|
|
24
|
+
[dependency-groups]
|
|
25
|
+
dev = ["pytest>=9.1.1"]
|
|
26
|
+
|
|
27
|
+
[tool.ruff.lint]
|
|
28
|
+
extend-select = [
|
|
29
|
+
"N802",
|
|
30
|
+
"N803",
|
|
31
|
+
"N806",
|
|
32
|
+
"N815",
|
|
33
|
+
"N816",
|
|
34
|
+
]
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "ncfunc"
|
|
3
|
+
version = "0.1.0"
|
|
4
|
+
description = "Add your description here"
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
authors = [
|
|
7
|
+
{ name = "lkkbox", email = "mail@mail.com" }
|
|
8
|
+
]
|
|
9
|
+
requires-python = ">=3.10"
|
|
10
|
+
dependencies = [
|
|
11
|
+
"datenum>=0.1.0",
|
|
12
|
+
"netcdf4>=1.7.3",
|
|
13
|
+
"numpy>=1.24",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
[project.scripts]
|
|
17
|
+
ncfunc = "ncfunc:main"
|
|
18
|
+
|
|
19
|
+
[build-system]
|
|
20
|
+
requires = ["uv_build>=0.12.1,<0.13.0"]
|
|
21
|
+
build-backend = "uv_build"
|
|
22
|
+
|
|
23
|
+
[dependency-groups]
|
|
24
|
+
dev = [
|
|
25
|
+
"pytest>=9.1.1",
|
|
26
|
+
]
|
|
27
|
+
|
|
28
|
+
[tool.ruff.lint]
|
|
29
|
+
extend-select = ["N802", "N803", "N806", "N815", "N816"]
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
from .core import (
|
|
2
|
+
DatasetMeta,
|
|
3
|
+
attr_names,
|
|
4
|
+
attr_names_include,
|
|
5
|
+
attr_val,
|
|
6
|
+
create,
|
|
7
|
+
dim_names,
|
|
8
|
+
ndim,
|
|
9
|
+
read,
|
|
10
|
+
read_time,
|
|
11
|
+
read_within,
|
|
12
|
+
save,
|
|
13
|
+
shape,
|
|
14
|
+
var_names,
|
|
15
|
+
var_names_include,
|
|
16
|
+
write,
|
|
17
|
+
write_attr,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
__all__ = [
|
|
21
|
+
"DatasetMeta",
|
|
22
|
+
"attr_names",
|
|
23
|
+
"attr_names_include",
|
|
24
|
+
"attr_val",
|
|
25
|
+
"create",
|
|
26
|
+
"dim_names",
|
|
27
|
+
"ndim",
|
|
28
|
+
"read",
|
|
29
|
+
"read_time",
|
|
30
|
+
"read_within",
|
|
31
|
+
"save",
|
|
32
|
+
"shape",
|
|
33
|
+
"var_names",
|
|
34
|
+
"var_names_include",
|
|
35
|
+
"write",
|
|
36
|
+
"write_attr",
|
|
37
|
+
]
|