h5netcdf 1.3.0__tar.gz → 1.4.1__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.
Potentially problematic release.
This version of h5netcdf might be problematic. Click here for more details.
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/.pre-commit-config.yaml +5 -5
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/CHANGELOG.rst +24 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/PKG-INFO +24 -25
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/README.rst +22 -24
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/doc/api.rst +3 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/doc/conf.py +1 -1
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/doc/devguide.rst +2 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/doc/index.rst +1 -1
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/doc/legacyapi.rst +3 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf/__init__.py +1 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf/_version.py +2 -2
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf/attrs.py +2 -2
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf/core.py +554 -87
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf/dimensions.py +6 -9
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf/legacyapi.py +26 -5
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf/tests/test_h5netcdf.py +613 -63
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf.egg-info/PKG-INFO +24 -25
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/pyproject.toml +4 -3
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/AUTHORS.txt +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/LICENSE +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/doc/Makefile +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/doc/changelog.rst +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/doc/feature.rst +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf/tests/conftest.py +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf/tests/pytest.ini +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf/utils.py +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf.egg-info/SOURCES.txt +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf.egg-info/dependency_links.txt +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf.egg-info/requires.txt +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/h5netcdf.egg-info/top_level.txt +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/licenses/H5PY_LICENSE.txt +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/licenses/PSF_LICENSE.txt +0 -0
- {h5netcdf-1.3.0 → h5netcdf-1.4.1}/setup.cfg +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
repos:
|
|
2
2
|
- repo: https://github.com/pre-commit/pre-commit-hooks
|
|
3
|
-
rev: v4.
|
|
3
|
+
rev: v4.6.0
|
|
4
4
|
hooks:
|
|
5
5
|
- id: trailing-whitespace
|
|
6
6
|
- id: end-of-file-fixer
|
|
@@ -9,17 +9,17 @@ repos:
|
|
|
9
9
|
- id: check-yaml
|
|
10
10
|
- id: debug-statements
|
|
11
11
|
- id: mixed-line-ending
|
|
12
|
-
- repo: https://github.com/
|
|
13
|
-
rev: 'v0.0
|
|
12
|
+
- repo: https://github.com/astral-sh/ruff-pre-commit
|
|
13
|
+
rev: 'v0.5.0'
|
|
14
14
|
hooks:
|
|
15
15
|
- id: ruff
|
|
16
16
|
args: [ "--fix" ]
|
|
17
17
|
- repo: https://github.com/psf/black
|
|
18
|
-
rev:
|
|
18
|
+
rev: 24.4.2
|
|
19
19
|
hooks:
|
|
20
20
|
- id: black
|
|
21
21
|
- repo: https://github.com/adamchainz/blacken-docs
|
|
22
|
-
rev: "1.
|
|
22
|
+
rev: "1.18.0"
|
|
23
23
|
hooks:
|
|
24
24
|
- id: blacken-docs
|
|
25
25
|
additional_dependencies:
|
|
@@ -1,6 +1,30 @@
|
|
|
1
1
|
Change Log
|
|
2
2
|
----------
|
|
3
3
|
|
|
4
|
+
Version 1.4.1 (November 13th, 2024):
|
|
5
|
+
|
|
6
|
+
- Add CI run for hdf5 1.10.6, fix complex tests, fix enum/user type tests ({pull}`244`).
|
|
7
|
+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
Version 1.4.0 (October 7th, 2024):
|
|
11
|
+
|
|
12
|
+
- Add UserType class, add EnumType ({pull}`229`).
|
|
13
|
+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
14
|
+
- Refactor fillvalue and dtype handling for user types, enhance sanity checks and tests ({pull}`230`).
|
|
15
|
+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
16
|
+
- Add VLType and CompoundType, commit complex compound type to file. Align with nc-complex ({pull}`227`).
|
|
17
|
+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
18
|
+
- Update h5pyd testing.
|
|
19
|
+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
20
|
+
- CI and lint maintenance ({pull}`235`).
|
|
21
|
+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
22
|
+
- Support wrapping an h5py ``File`` object. Closing the h5netcdf file object
|
|
23
|
+
does not close the h5py file ({pull}`238`).
|
|
24
|
+
By `Thomas Kluyver <https://github.com/takluyver>`_
|
|
25
|
+
- CI and lint maintenance (format README.rst, use more f-strings, change Python 3.9 to 3.10 in CI) ({pull}`239`).
|
|
26
|
+
By `Kai Mühlbauer <https://github.com/kmuehlbauer>`_
|
|
27
|
+
|
|
4
28
|
Version 1.3.0 (November 7th, 2023):
|
|
5
29
|
|
|
6
30
|
- Add ros3 support by checking `driver`-kwarg.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.1
|
|
2
2
|
Name: h5netcdf
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.4.1
|
|
4
4
|
Summary: netCDF4 via h5py
|
|
5
5
|
Author-email: Stephan Hoyer <shoyer@gmail.com>, Kai Mühlbauer <kmuehlbauer@wradlib.org>
|
|
6
6
|
Maintainer-email: h5netcdf developers <devteam@h5netcdf.org>
|
|
@@ -45,6 +45,7 @@ Classifier: Programming Language :: Python :: 3
|
|
|
45
45
|
Classifier: Programming Language :: Python :: 3.9
|
|
46
46
|
Classifier: Programming Language :: Python :: 3.10
|
|
47
47
|
Classifier: Programming Language :: Python :: 3.11
|
|
48
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
48
49
|
Classifier: Topic :: Scientific/Engineering
|
|
49
50
|
Requires-Python: >=3.9
|
|
50
51
|
Description-Content-Type: text/x-rst
|
|
@@ -138,32 +139,32 @@ design is an adaptation of h5py to the netCDF data model. For example:
|
|
|
138
139
|
import h5netcdf
|
|
139
140
|
import numpy as np
|
|
140
141
|
|
|
141
|
-
with h5netcdf.File(
|
|
142
|
+
with h5netcdf.File("mydata.nc", "w") as f:
|
|
142
143
|
# set dimensions with a dictionary
|
|
143
|
-
f.dimensions = {
|
|
144
|
+
f.dimensions = {"x": 5}
|
|
144
145
|
# and update them with a dict-like interface
|
|
145
146
|
# f.dimensions['x'] = 5
|
|
146
147
|
# f.dimensions.update({'x': 5})
|
|
147
148
|
|
|
148
|
-
v = f.create_variable(
|
|
149
|
+
v = f.create_variable("hello", ("x",), float)
|
|
149
150
|
v[:] = np.ones(5)
|
|
150
151
|
|
|
151
152
|
# you don't need to create groups first
|
|
152
153
|
# you also don't need to create dimensions first if you supply data
|
|
153
154
|
# with the new variable
|
|
154
|
-
v = f.create_variable(
|
|
155
|
+
v = f.create_variable("/grouped/data", ("y",), data=np.arange(10))
|
|
155
156
|
|
|
156
157
|
# access and modify attributes with a dict-like interface
|
|
157
|
-
v.attrs[
|
|
158
|
+
v.attrs["foo"] = "bar"
|
|
158
159
|
|
|
159
160
|
# you can access variables and groups directly using a hierarchical
|
|
160
161
|
# keys like h5py
|
|
161
|
-
print(f[
|
|
162
|
+
print(f["/grouped/data"])
|
|
162
163
|
|
|
163
164
|
# add an unlimited dimension
|
|
164
|
-
f.dimensions[
|
|
165
|
+
f.dimensions["z"] = None
|
|
165
166
|
# explicitly resize a dimension and all variables using it
|
|
166
|
-
f.resize_dimension(
|
|
167
|
+
f.resize_dimension("z", 3)
|
|
167
168
|
|
|
168
169
|
Notes:
|
|
169
170
|
|
|
@@ -184,22 +185,23 @@ The legacy API is designed for compatibility with `netCDF4-python`_. To use it,
|
|
|
184
185
|
.. code-block:: python
|
|
185
186
|
|
|
186
187
|
import h5netcdf.legacyapi as netCDF4
|
|
188
|
+
|
|
187
189
|
# everything here would also work with this instead:
|
|
188
190
|
# import netCDF4
|
|
189
191
|
import numpy as np
|
|
190
192
|
|
|
191
|
-
with netCDF4.Dataset(
|
|
192
|
-
ds.createDimension(
|
|
193
|
-
v = ds.createVariable(
|
|
193
|
+
with netCDF4.Dataset("mydata.nc", "w") as ds:
|
|
194
|
+
ds.createDimension("x", 5)
|
|
195
|
+
v = ds.createVariable("hello", float, ("x",))
|
|
194
196
|
v[:] = np.ones(5)
|
|
195
197
|
|
|
196
|
-
g = ds.createGroup(
|
|
197
|
-
g.createDimension(
|
|
198
|
-
g.createVariable(
|
|
199
|
-
v = g[
|
|
198
|
+
g = ds.createGroup("grouped")
|
|
199
|
+
g.createDimension("y", 10)
|
|
200
|
+
g.createVariable("data", "i8", ("y",))
|
|
201
|
+
v = g["data"]
|
|
200
202
|
v[:] = np.arange(10)
|
|
201
|
-
v.foo =
|
|
202
|
-
print(ds.groups[
|
|
203
|
+
v.foo = "bar"
|
|
204
|
+
print(ds.groups["grouped"].variables["data"])
|
|
203
205
|
|
|
204
206
|
The legacy API is designed to be easy to try-out for netCDF4-python users, but it is not an
|
|
205
207
|
exact match. Here is an incomplete list of functionality we don't include:
|
|
@@ -222,9 +224,6 @@ h5py implements some features that do not (yet) result in valid netCDF files:
|
|
|
222
224
|
|
|
223
225
|
- Data types:
|
|
224
226
|
- Booleans
|
|
225
|
-
- Complex values
|
|
226
|
-
- Non-string variable length types
|
|
227
|
-
- Enum types
|
|
228
227
|
- Reference types
|
|
229
228
|
- Arbitrary filters:
|
|
230
229
|
- Scale-offset filters
|
|
@@ -239,11 +238,11 @@ when creating a file:
|
|
|
239
238
|
.. code-block:: python
|
|
240
239
|
|
|
241
240
|
# avoid the .nc extension for non-netcdf files
|
|
242
|
-
f = h5netcdf.File(
|
|
241
|
+
f = h5netcdf.File("mydata.h5", invalid_netcdf=True)
|
|
243
242
|
...
|
|
244
243
|
|
|
245
244
|
# works with the legacy API, too, though compression options are not exposed
|
|
246
|
-
ds = h5netcdf.legacyapi.Dataset(
|
|
245
|
+
ds = h5netcdf.legacyapi.Dataset("mydata.h5", invalid_netcdf=True)
|
|
247
246
|
...
|
|
248
247
|
|
|
249
248
|
In such cases the `_NCProperties` attribute will not be saved to the file or be removed
|
|
@@ -281,7 +280,7 @@ phony dimensions according to `netCDF`_ behaviour.
|
|
|
281
280
|
.. code-block:: python
|
|
282
281
|
|
|
283
282
|
# mimic netCDF-behaviour for non-netcdf files
|
|
284
|
-
f = h5netcdf.File(
|
|
283
|
+
f = h5netcdf.File("mydata.h5", mode="r", phony_dims="sort")
|
|
285
284
|
...
|
|
286
285
|
|
|
287
286
|
Note, that this iterates once over the whole group-hierarchy. This has affects
|
|
@@ -292,7 +291,7 @@ to group access time. The created phony dimension naming will differ from
|
|
|
292
291
|
|
|
293
292
|
.. code-block:: python
|
|
294
293
|
|
|
295
|
-
f = h5netcdf.File(
|
|
294
|
+
f = h5netcdf.File("mydata.h5", mode="r", phony_dims="access")
|
|
296
295
|
...
|
|
297
296
|
|
|
298
297
|
.. rubric:: Footnotes
|
|
@@ -80,32 +80,32 @@ design is an adaptation of h5py to the netCDF data model. For example:
|
|
|
80
80
|
import h5netcdf
|
|
81
81
|
import numpy as np
|
|
82
82
|
|
|
83
|
-
with h5netcdf.File(
|
|
83
|
+
with h5netcdf.File("mydata.nc", "w") as f:
|
|
84
84
|
# set dimensions with a dictionary
|
|
85
|
-
f.dimensions = {
|
|
85
|
+
f.dimensions = {"x": 5}
|
|
86
86
|
# and update them with a dict-like interface
|
|
87
87
|
# f.dimensions['x'] = 5
|
|
88
88
|
# f.dimensions.update({'x': 5})
|
|
89
89
|
|
|
90
|
-
v = f.create_variable(
|
|
90
|
+
v = f.create_variable("hello", ("x",), float)
|
|
91
91
|
v[:] = np.ones(5)
|
|
92
92
|
|
|
93
93
|
# you don't need to create groups first
|
|
94
94
|
# you also don't need to create dimensions first if you supply data
|
|
95
95
|
# with the new variable
|
|
96
|
-
v = f.create_variable(
|
|
96
|
+
v = f.create_variable("/grouped/data", ("y",), data=np.arange(10))
|
|
97
97
|
|
|
98
98
|
# access and modify attributes with a dict-like interface
|
|
99
|
-
v.attrs[
|
|
99
|
+
v.attrs["foo"] = "bar"
|
|
100
100
|
|
|
101
101
|
# you can access variables and groups directly using a hierarchical
|
|
102
102
|
# keys like h5py
|
|
103
|
-
print(f[
|
|
103
|
+
print(f["/grouped/data"])
|
|
104
104
|
|
|
105
105
|
# add an unlimited dimension
|
|
106
|
-
f.dimensions[
|
|
106
|
+
f.dimensions["z"] = None
|
|
107
107
|
# explicitly resize a dimension and all variables using it
|
|
108
|
-
f.resize_dimension(
|
|
108
|
+
f.resize_dimension("z", 3)
|
|
109
109
|
|
|
110
110
|
Notes:
|
|
111
111
|
|
|
@@ -126,22 +126,23 @@ The legacy API is designed for compatibility with `netCDF4-python`_. To use it,
|
|
|
126
126
|
.. code-block:: python
|
|
127
127
|
|
|
128
128
|
import h5netcdf.legacyapi as netCDF4
|
|
129
|
+
|
|
129
130
|
# everything here would also work with this instead:
|
|
130
131
|
# import netCDF4
|
|
131
132
|
import numpy as np
|
|
132
133
|
|
|
133
|
-
with netCDF4.Dataset(
|
|
134
|
-
ds.createDimension(
|
|
135
|
-
v = ds.createVariable(
|
|
134
|
+
with netCDF4.Dataset("mydata.nc", "w") as ds:
|
|
135
|
+
ds.createDimension("x", 5)
|
|
136
|
+
v = ds.createVariable("hello", float, ("x",))
|
|
136
137
|
v[:] = np.ones(5)
|
|
137
138
|
|
|
138
|
-
g = ds.createGroup(
|
|
139
|
-
g.createDimension(
|
|
140
|
-
g.createVariable(
|
|
141
|
-
v = g[
|
|
139
|
+
g = ds.createGroup("grouped")
|
|
140
|
+
g.createDimension("y", 10)
|
|
141
|
+
g.createVariable("data", "i8", ("y",))
|
|
142
|
+
v = g["data"]
|
|
142
143
|
v[:] = np.arange(10)
|
|
143
|
-
v.foo =
|
|
144
|
-
print(ds.groups[
|
|
144
|
+
v.foo = "bar"
|
|
145
|
+
print(ds.groups["grouped"].variables["data"])
|
|
145
146
|
|
|
146
147
|
The legacy API is designed to be easy to try-out for netCDF4-python users, but it is not an
|
|
147
148
|
exact match. Here is an incomplete list of functionality we don't include:
|
|
@@ -164,9 +165,6 @@ h5py implements some features that do not (yet) result in valid netCDF files:
|
|
|
164
165
|
|
|
165
166
|
- Data types:
|
|
166
167
|
- Booleans
|
|
167
|
-
- Complex values
|
|
168
|
-
- Non-string variable length types
|
|
169
|
-
- Enum types
|
|
170
168
|
- Reference types
|
|
171
169
|
- Arbitrary filters:
|
|
172
170
|
- Scale-offset filters
|
|
@@ -181,11 +179,11 @@ when creating a file:
|
|
|
181
179
|
.. code-block:: python
|
|
182
180
|
|
|
183
181
|
# avoid the .nc extension for non-netcdf files
|
|
184
|
-
f = h5netcdf.File(
|
|
182
|
+
f = h5netcdf.File("mydata.h5", invalid_netcdf=True)
|
|
185
183
|
...
|
|
186
184
|
|
|
187
185
|
# works with the legacy API, too, though compression options are not exposed
|
|
188
|
-
ds = h5netcdf.legacyapi.Dataset(
|
|
186
|
+
ds = h5netcdf.legacyapi.Dataset("mydata.h5", invalid_netcdf=True)
|
|
189
187
|
...
|
|
190
188
|
|
|
191
189
|
In such cases the `_NCProperties` attribute will not be saved to the file or be removed
|
|
@@ -223,7 +221,7 @@ phony dimensions according to `netCDF`_ behaviour.
|
|
|
223
221
|
.. code-block:: python
|
|
224
222
|
|
|
225
223
|
# mimic netCDF-behaviour for non-netcdf files
|
|
226
|
-
f = h5netcdf.File(
|
|
224
|
+
f = h5netcdf.File("mydata.h5", mode="r", phony_dims="sort")
|
|
227
225
|
...
|
|
228
226
|
|
|
229
227
|
Note, that this iterates once over the whole group-hierarchy. This has affects
|
|
@@ -234,7 +232,7 @@ to group access time. The created phony dimension naming will differ from
|
|
|
234
232
|
|
|
235
233
|
.. code-block:: python
|
|
236
234
|
|
|
237
|
-
f = h5netcdf.File(
|
|
235
|
+
f = h5netcdf.File("mydata.h5", mode="r", phony_dims="access")
|
|
238
236
|
...
|
|
239
237
|
|
|
240
238
|
.. rubric:: Footnotes
|
|
@@ -130,7 +130,7 @@ else:
|
|
|
130
130
|
# extract git revision
|
|
131
131
|
gh_tree_name = version_tuple[-1].split(".")[0][1:]
|
|
132
132
|
|
|
133
|
-
rel = "`{
|
|
133
|
+
rel = f"`{release} <{url}/h5netcdf/tree/{gh_tree_name}>`__"
|
|
134
134
|
|
|
135
135
|
rst_epilog = ""
|
|
136
136
|
rst_epilog += f"""
|
|
@@ -15,6 +15,7 @@ Contributors
|
|
|
15
15
|
- `Brett Naul <https://github.com/bnaul>`_
|
|
16
16
|
- `Dion Häfner <https://github.com/dionhaefner>`_
|
|
17
17
|
- `Drew Parsons <https://github.com/drew-parsons>`_
|
|
18
|
+
- `Ezequiel Cimadevilla Alvarez <https://github.com/zequihg50>`_
|
|
18
19
|
- `Frédéric Laliberté <https://github.com/laliberte>`_
|
|
19
20
|
- `Ghislain Vaillant <https://github.com/ghisvail>`_
|
|
20
21
|
- `Lion Krischer <https://github.com/krischer>`_
|
|
@@ -23,6 +24,7 @@ Contributors
|
|
|
23
24
|
- `Pierre Augier <https://github.com/paugier>`_
|
|
24
25
|
- `Ryan Grout <https://github.com/groutr>`_
|
|
25
26
|
- `Scott Henderson <https://github.com/scottyhq>`_
|
|
27
|
+
- `Thomas Kluyver <https://github.com/takluyver>`_
|
|
26
28
|
- `Tom Augspurger <https://github.com/TomAugspurger>`_
|
|
27
29
|
|
|
28
30
|
If you are interested to contribute, just let us know by creating an issue or pull request on github.
|
|
@@ -50,7 +50,7 @@ by Stephan Hoyer. The first `official` ``h5netcdf`` announcement was made by Ste
|
|
|
50
50
|
`xarray issue tracker`_ only one day later.
|
|
51
51
|
|
|
52
52
|
The library evolved constantly over the years (fixing bugs and adding enhancements)
|
|
53
|
-
and gained contributions from
|
|
53
|
+
and gained contributions from 17 other :ref:`contributors` so far. The library is widely used,
|
|
54
54
|
especially as backend within `xarray`_.
|
|
55
55
|
|
|
56
56
|
Early 2020 Kai Mühlbauer started to add contributions and after some time he volunteered
|
|
@@ -76,7 +76,7 @@ class Attributes(MutableMapping):
|
|
|
76
76
|
|
|
77
77
|
def __setitem__(self, key, value):
|
|
78
78
|
if key in _HIDDEN_ATTRS:
|
|
79
|
-
raise AttributeError("cannot write attribute with reserved name
|
|
79
|
+
raise AttributeError(f"cannot write attribute with reserved name {key!r}")
|
|
80
80
|
if hasattr(value, "dtype"):
|
|
81
81
|
dtype = value.dtype
|
|
82
82
|
else:
|
|
@@ -98,4 +98,4 @@ class Attributes(MutableMapping):
|
|
|
98
98
|
return len(self._h5attrs) - hidden_count
|
|
99
99
|
|
|
100
100
|
def __repr__(self):
|
|
101
|
-
return "\n".join(["
|
|
101
|
+
return "\n".join([f"{type(self)!r}"] + [f"{k}: {v!r}" for k, v in self.items()])
|