umfive 0.2.2__tar.gz → 0.3.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.
Files changed (75) hide show
  1. {umfive-0.2.2/umfive.egg-info → umfive-0.3.0}/PKG-INFO +1 -1
  2. {umfive-0.2.2 → umfive-0.3.0}/pyproject.toml +1 -1
  3. {umfive-0.2.2 → umfive-0.3.0}/tests/data/cl_umfile_dump.txt +1 -1
  4. {umfive-0.2.2 → umfive-0.3.0}/tests/data/extra_data_dump.txt +2 -1
  5. {umfive-0.2.2 → umfive-0.3.0}/tests/data/test2_dump.txt +1 -1
  6. {umfive-0.2.2 → umfive-0.3.0}/tests/data/umfile_dump.txt +1 -1
  7. {umfive-0.2.2 → umfive-0.3.0}/tests/data/wgdos_packed_dump.txt +1 -1
  8. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_core/test_pyfive_interoperability.py +1 -1
  9. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_io/test_file.py +5 -0
  10. {umfive-0.2.2 → umfive-0.3.0}/umfive/__init__.py +2 -0
  11. {umfive-0.2.2 → umfive-0.3.0}/umfive/constants.py +1 -1
  12. {umfive-0.2.2 → umfive-0.3.0}/umfive/core/variables.py +0 -1
  13. {umfive-0.2.2 → umfive-0.3.0}/umfive/high_level.py +3 -2
  14. {umfive-0.2.2 → umfive-0.3.0}/umfive/stash.py +73 -56
  15. {umfive-0.2.2 → umfive-0.3.0}/umfive/variable.py +3 -3
  16. {umfive-0.2.2 → umfive-0.3.0/umfive.egg-info}/PKG-INFO +1 -1
  17. {umfive-0.2.2 → umfive-0.3.0}/.flake8 +0 -0
  18. {umfive-0.2.2 → umfive-0.3.0}/.github/workflows/build-and-deploy-wheels-on-pypi.yml +0 -0
  19. {umfive-0.2.2 → umfive-0.3.0}/.github/workflows/pytest.yml +0 -0
  20. {umfive-0.2.2 → umfive-0.3.0}/.gitignore +0 -0
  21. {umfive-0.2.2 → umfive-0.3.0}/.pre-commit-config.yaml +0 -0
  22. {umfive-0.2.2 → umfive-0.3.0}/.pydocstyle.ini +0 -0
  23. {umfive-0.2.2 → umfive-0.3.0}/LICENSE +0 -0
  24. {umfive-0.2.2 → umfive-0.3.0}/MANIFEST.in +0 -0
  25. {umfive-0.2.2 → umfive-0.3.0}/README.md +0 -0
  26. {umfive-0.2.2 → umfive-0.3.0}/environment.yml +0 -0
  27. {umfive-0.2.2 → umfive-0.3.0}/setup.cfg +0 -0
  28. {umfive-0.2.2 → umfive-0.3.0}/setup.py +0 -0
  29. {umfive-0.2.2 → umfive-0.3.0}/tests/data/aaaaoa.pmh8dec.pp +0 -0
  30. {umfive-0.2.2 → umfive-0.3.0}/tests/data/cl_umfile +0 -0
  31. {umfive-0.2.2 → umfive-0.3.0}/tests/data/extra_data.pp +0 -0
  32. {umfive-0.2.2 → umfive-0.3.0}/tests/data/test1.nc +0 -0
  33. {umfive-0.2.2 → umfive-0.3.0}/tests/data/test2-viacf.nc +0 -0
  34. {umfive-0.2.2 → umfive-0.3.0}/tests/data/test2.pp +0 -0
  35. {umfive-0.2.2 → umfive-0.3.0}/tests/data/umfile.pp +0 -0
  36. {umfive-0.2.2 → umfive-0.3.0}/tests/data/wgdos_packed.pp +0 -0
  37. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_core/test_DataVariable_api.py +0 -0
  38. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_core/test_File_api.py +0 -0
  39. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_core/test_filetype.py +0 -0
  40. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_core/test_packed_data_loading.py +0 -0
  41. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_core/test_scanner.py +0 -0
  42. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_core/test_stash_table.py +0 -0
  43. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_core/test_wgdos_extension.py +0 -0
  44. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_io/test_chunk_index.py +0 -0
  45. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_io/test_fileobj_reader.py +0 -0
  46. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_io/test_lazy_subselection.py +0 -0
  47. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_io/test_local_reader.py +0 -0
  48. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_io/test_parallel_reads.py +0 -0
  49. {umfive-0.2.2 → umfive-0.3.0}/tests/tests_io/test_umdump.py +0 -0
  50. {umfive-0.2.2 → umfive-0.3.0}/umfive/c_ext/wgdos_impl.h +0 -0
  51. {umfive-0.2.2 → umfive-0.3.0}/umfive/c_ext/wgdos_module.c +0 -0
  52. {umfive-0.2.2 → umfive-0.3.0}/umfive/core/__init__.py +0 -0
  53. {umfive-0.2.2 → umfive-0.3.0}/umfive/core/data.py +0 -0
  54. {umfive-0.2.2 → umfive-0.3.0}/umfive/core/extra_data.py +0 -0
  55. {umfive-0.2.2 → umfive-0.3.0}/umfive/core/filetype.py +0 -0
  56. {umfive-0.2.2 → umfive-0.3.0}/umfive/core/header.py +0 -0
  57. {umfive-0.2.2 → umfive-0.3.0}/umfive/core/interpret.py +0 -0
  58. {umfive-0.2.2 → umfive-0.3.0}/umfive/core/models.py +0 -0
  59. {umfive-0.2.2 → umfive-0.3.0}/umfive/core/scanner.py +0 -0
  60. {umfive-0.2.2 → umfive-0.3.0}/umfive/data/STASH_to_CF.txt +0 -0
  61. {umfive-0.2.2 → umfive-0.3.0}/umfive/data/field_codes.txt +0 -0
  62. {umfive-0.2.2 → umfive-0.3.0}/umfive/inspect.py +0 -0
  63. {umfive-0.2.2 → umfive-0.3.0}/umfive/io/__init__.py +0 -0
  64. {umfive-0.2.2 → umfive-0.3.0}/umfive/io/bytereader.py +0 -0
  65. {umfive-0.2.2 → umfive-0.3.0}/umfive/io/chunk_read.py +0 -0
  66. {umfive-0.2.2 → umfive-0.3.0}/umfive/io/fileobj.py +0 -0
  67. {umfive-0.2.2 → umfive-0.3.0}/umfive/io/local_posix_reader.py +0 -0
  68. {umfive-0.2.2 → umfive-0.3.0}/umfive/io/mock_filesystem.py +0 -0
  69. {umfive-0.2.2 → umfive-0.3.0}/umfive/umdump.py +0 -0
  70. {umfive-0.2.2 → umfive-0.3.0}/umfive/wgdos.py +0 -0
  71. {umfive-0.2.2 → umfive-0.3.0}/umfive.egg-info/SOURCES.txt +0 -0
  72. {umfive-0.2.2 → umfive-0.3.0}/umfive.egg-info/dependency_links.txt +0 -0
  73. {umfive-0.2.2 → umfive-0.3.0}/umfive.egg-info/entry_points.txt +0 -0
  74. {umfive-0.2.2 → umfive-0.3.0}/umfive.egg-info/requires.txt +0 -0
  75. {umfive-0.2.2 → umfive-0.3.0}/umfive.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: umfive
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: PP/Fields reader with pyfive-style high-level API
5
5
  Author: David Hassell, Alan Iwi, Bryan Lawrence, Valeriu Predoi - package
6
6
  License: MIT
@@ -8,7 +8,7 @@ build-backend = "setuptools.build_meta"
8
8
 
9
9
  [project]
10
10
  name = "umfive"
11
- version = "0.2.2"
11
+ version = "0.3.0"
12
12
  description = "PP/Fields reader with pyfive-style high-level API"
13
13
  license = {text = "MIT"}
14
14
  readme = "README.md"
@@ -1,6 +1,6 @@
1
1
  <umfive.File: tests/data/cl_umfile, 49 data variables, 37 metadata variables>
2
2
  Attributes:
3
- Conventions: 'CF-1.14'
3
+ Conventions: 'CF-1.13'
4
4
  Data variables:
5
5
  <umfive.DataVariable: UM_m01s00i001_vn405, shape=(12, 37, 48), dimensions=(time, latitude, longitude)>
6
6
  Attributes:
@@ -1,6 +1,6 @@
1
1
  <umfive.File: tests/data/extra_data.pp, 1 data variable, 10 metadata variables>
2
2
  Attributes:
3
- Conventions: 'CF-1.14'
3
+ Conventions: 'CF-1.13'
4
4
  Data variables:
5
5
  <umfive.DataVariable: UM_m01s03i236_vn405, shape=(1, 1, 100, 3), dimensions=(dimension1, height, time, site)>
6
6
  Attributes:
@@ -228,6 +228,7 @@
228
228
  <umfive.Variable: region, shape=(3,), dimensions=(site)>
229
229
  Attributes:
230
230
  DIMENSION_LIST: (('site',),)
231
+ standard_name: 'region'
231
232
  Data str608:
232
233
  ['Northern Hemisphere', 'Southern Hemisphere',
233
234
  'Global']
@@ -1,6 +1,6 @@
1
1
  <umfive.File: tests/data/test2.pp, 1 data variable, 9 metadata variables>
2
2
  Attributes:
3
- Conventions: 'CF-1.14'
3
+ Conventions: 'CF-1.13'
4
4
  Data variables:
5
5
  <umfive.DataVariable: UM_m01s15i201_vn405, shape=(3, 5, 110, 106), dimensions=(time, air_pressure, grid_latitude, grid_longitude)>
6
6
  Attributes:
@@ -1,6 +1,6 @@
1
1
  <umfive.File: tests/data/umfile.pp, 1 data variable, 7 metadata variables>
2
2
  Attributes:
3
- Conventions: 'CF-1.14'
3
+ Conventions: 'CF-1.13'
4
4
  Data variables:
5
5
  <umfive.DataVariable: UM_m01s00i001_vn405, shape=(3, 73, 96), dimensions=(time, latitude, longitude)>
6
6
  Attributes:
@@ -1,6 +1,6 @@
1
1
  <umfive.File: tests/data/wgdos_packed.pp, 1 data variable, 7 metadata variables>
2
2
  Attributes:
3
- Conventions: 'CF-1.14'
3
+ Conventions: 'CF-1.13'
4
4
  Data variables:
5
5
  <umfive.DataVariable: UM_m01s30i201_vn1100, shape=(1, 1, 145, 192), dimensions=(time, air_pressure, latitude, longitude)>
6
6
  Attributes:
@@ -10,7 +10,7 @@ def test_pyfive_resistration():
10
10
  assert isinstance(f, pyfive.File)
11
11
 
12
12
  for var in f.values():
13
- assert isinstance(var, pyfive.Dataset)
13
+ isinstance(var, pyfive.Dataset)
14
14
 
15
15
 
16
16
  def test_umfive_file_exposes_pyfive_root_members():
@@ -17,6 +17,7 @@ import umfive
17
17
  ],
18
18
  )
19
19
  def test_file(dataset, suffix):
20
+ """Test umfive.File with various input files."""
20
21
  # Build the file paths dynamically based on parameters
21
22
  input_file = f"tests/data/{dataset}{suffix}"
22
23
  dump_file = f"tests/data/{dataset}_dump.txt"
@@ -31,6 +32,7 @@ def test_file(dataset, suffix):
31
32
 
32
33
 
33
34
  def test_File_with_builtin_open_as_input():
35
+ """Test umfive.File with open file handle 'filename' argument."""
34
36
  with open("tests/data/test2.pp", "rb") as fh:
35
37
  f = umfive.File(fh)
36
38
  assert (
@@ -40,6 +42,7 @@ def test_File_with_builtin_open_as_input():
40
42
 
41
43
 
42
44
  def test_File_with_bytesio_as_input():
45
+ """Test umfive.File with BytesIO 'filename' argument."""
43
46
  path = Path("tests/data/test2.pp")
44
47
  raw = BytesIO(path.read_bytes())
45
48
  f = umfive.File(raw)
@@ -54,10 +57,12 @@ def test_File_with_bytesio_as_input():
54
57
  [[], {}, (), None, 0, 3.14, True],
55
58
  )
56
59
  def test_File_with_invalid_input(filename):
60
+ """Test umfive.File with bad 'filename' type."""
57
61
  with pytest.raises(ValueError):
58
62
  umfive.File(filename)
59
63
 
60
64
 
61
65
  def test_File_with_directory_input():
66
+ """Test umfive.File with 'filename' pointing to a directory."""
62
67
  with pytest.raises(IsADirectoryError):
63
68
  umfive.File("tests/data")
@@ -2,3 +2,5 @@ from .high_level import File
2
2
  from .variable import DataVariable, DimensionScale, Variable
3
3
  from .stash import load_stash_table, stash_records, stash_table
4
4
  from .io import ByteReader, FileObjReader, LocalPosixReader
5
+
6
+ __version__ = "0.3.0"
@@ -1,7 +1,7 @@
1
1
  from sys import float_info
2
2
 
3
3
  # The value of the CF "Conventions" attribute.
4
- CF_CONVENTIONS = "CF-1.14"
4
+ CF_CONVENTIONS = "CF-1.13"
5
5
 
6
6
  # Sizes (in words) of the lookup header
7
7
  N_INT_HDR = 45
@@ -47,7 +47,6 @@ from .data import (
47
47
  read_record_array,
48
48
  )
49
49
  from .interpret import get_type
50
- from .models import RecordInfo
51
50
 
52
51
 
53
52
  def _float_key(val):
@@ -2465,6 +2465,7 @@ class DataVariableMetadata:
2465
2465
  ac = Variable(
2466
2466
  name="region",
2467
2467
  data=array,
2468
+ attrs={"standard_name": "region"},
2468
2469
  DIMENSION_LIST=((self._axis[axis],),),
2469
2470
  )
2470
2471
  aux_ncvar = self.add_to_variables(ac)
@@ -2923,7 +2924,7 @@ class DataVariableMetadata:
2923
2924
  # Let external callers treat File as pyfive-like File
2924
2925
  try:
2925
2926
  import pyfive
2927
+
2928
+ pyfive.File.register(File)
2926
2929
  except Exception: # pragma: no cover
2927
2930
  pass
2928
- else:
2929
- pyfive.File.register(File)
@@ -99,7 +99,7 @@ def _parse_cf_extra(value):
99
99
  return out
100
100
 
101
101
 
102
- def load_stash_table(table=None, delimiter="!", merge=True):
102
+ def load_stash_table(table=None, delimiter="!", merge=True, reset=False):
103
103
  """Load a STASH to standard name conversion table from a file.
104
104
 
105
105
  This used when reading PP and UM fields files.
@@ -132,12 +132,10 @@ def load_stash_table(table=None, delimiter="!", merge=True):
132
132
 
133
133
  :Parameters:
134
134
 
135
- table: `str`, optional
136
- Use the conversion table at this file location. By default
137
- the table in ``data/STASH_to_CF.txt`` will be used.
138
-
139
- Setting *table* to `None` will reset the table, removing
140
- any modifications that have previously been made.
135
+ table: `str` or `None`, optional
136
+ Use the conversion table at this file location. If `None`
137
+ (the default) the table in ``data/STASH_to_CF.txt`` will be
138
+ used.
141
139
 
142
140
  delimiter: `str`, optional
143
141
  The delimiter of the table columns. By default, ``!`` is
@@ -150,8 +148,9 @@ def load_stash_table(table=None, delimiter="!", merge=True):
150
148
  into the existing table, overwriting any entries which
151
149
  already exist.
152
150
 
153
- If *table* is `None` then *merge* is taken as False,
154
- regardless of its given value.
151
+ reset: `bool`, optional
152
+ If True then clear all entries and re-load the default
153
+ table.
155
154
 
156
155
  :Returns:
157
156
 
@@ -166,60 +165,71 @@ def load_stash_table(table=None, delimiter="!", merge=True):
166
165
  >>> load_stash_table('my_table4.txt', merge=False)
167
166
 
168
167
  """
168
+ if reset:
169
+ table = None
170
+ merge = False
171
+ _stash_table.clear()
172
+
169
173
  if table is None:
170
174
  # Use the default STASH table
171
175
  if _default_stash_table:
172
- # The default STASH table has already been loaded
173
- return
176
+ # Use the existing default tables
177
+ read_table = False
178
+ store_default = False
179
+ else:
180
+ read_table = True
181
+ store_default = True
174
182
 
175
- default = True
176
- merge = False
177
183
  table_path = files(__package__).joinpath("data/STASH_to_CF.txt")
178
184
  else:
179
185
  # User supplied table
180
- default = False
186
+ read_table = True
187
+ store_default = False
181
188
  table_path = PosixPath(table)
182
189
 
183
190
  stash2sn = {}
184
-
185
- with table_path.open("r", encoding="utf-8") as handle:
186
- rows = list(
187
- csv.reader(handle, delimiter=delimiter, skipinitialspace=True)
188
- )
189
-
190
- for row in rows:
191
- if not row or row[0].startswith("#"):
192
- continue
193
-
194
- # Normalize to expected width.
195
- if len(row) < 9:
196
- row = row + [""] * (9 - len(row))
197
-
198
- key = (int(row[_MODEL]), int(row[_STASH]))
199
- name = row[_NAME]
200
- units = row[_UNITS] or None
201
- valid_from = _parse_version(row[_VALID_FROM])
202
- valid_to = _parse_version(row[_VALID_TO])
203
- standard_name = row[_STANDARD_NAME] or None
204
- cf_info = _parse_cf_extra(row[_CF_EXTRA])
205
- pp_extra = row[_PP_EXTRA].rstrip()
206
-
207
- entry = (
208
- name,
209
- units,
210
- valid_from,
211
- valid_to,
212
- standard_name,
213
- cf_info,
214
- pp_extra,
215
- )
216
-
217
- if key in stash2sn:
218
- stash2sn[key] += (entry,)
219
- else:
220
- stash2sn[key] = (entry,)
221
-
222
- if default:
191
+ if read_table:
192
+ with table_path.open("r", encoding="utf-8") as handle:
193
+ rows = list(
194
+ csv.reader(handle, delimiter=delimiter, skipinitialspace=True)
195
+ )
196
+
197
+ for row in rows:
198
+ if not row or row[0].startswith("#"):
199
+ continue
200
+
201
+ # Normalize to expected width.
202
+ if len(row) < 9:
203
+ row = row + [""] * (9 - len(row))
204
+
205
+ key = (int(row[_MODEL]), int(row[_STASH]))
206
+ name = row[_NAME]
207
+ units = row[_UNITS] or None
208
+ valid_from = _parse_version(row[_VALID_FROM])
209
+ valid_to = _parse_version(row[_VALID_TO])
210
+ standard_name = row[_STANDARD_NAME] or None
211
+ cf_info = _parse_cf_extra(row[_CF_EXTRA])
212
+ pp_extra = row[_PP_EXTRA].rstrip()
213
+
214
+ entry = (
215
+ name,
216
+ units,
217
+ valid_from,
218
+ valid_to,
219
+ standard_name,
220
+ cf_info,
221
+ pp_extra,
222
+ )
223
+
224
+ if key in stash2sn:
225
+ stash2sn[key] += (entry,)
226
+ else:
227
+ stash2sn[key] = (entry,)
228
+
229
+ if reset:
230
+ stash2sn = _default_stash_table
231
+
232
+ if store_default:
223
233
  # Store the default STASH table
224
234
  _default_stash_table.update(stash2sn)
225
235
 
@@ -229,19 +239,26 @@ def load_stash_table(table=None, delimiter="!", merge=True):
229
239
  _stash_table.update(stash2sn)
230
240
 
231
241
 
232
- def stash_table():
242
+ def stash_table(reset=False):
233
243
  """Return a copy of the current STASH table.
234
244
 
235
245
  .. seealso:: `load_stash_table`, `stash_record`
236
246
 
247
+ :Parameters:
248
+
249
+ reset: `bool`, optional
250
+ If True then clear all entries, re-load the default
251
+ table, and return it.
252
+
237
253
  :Returns:
238
254
 
239
255
  `dict`
240
256
  The currently loaded STASH table.
241
257
 
242
258
  """
243
- if not _stash_table:
244
- load_stash_table()
259
+
260
+ if reset or not _default_stash_table:
261
+ load_stash_table(reset=reset)
245
262
 
246
263
  return _stash_table.copy()
247
264
 
@@ -1211,9 +1211,9 @@ class DataVariable(_Mixin):
1211
1211
  # Let external callers treat variable classes as pyfive-like Datasets
1212
1212
  try:
1213
1213
  import pyfive
1214
- except Exception: # pragma: no cover
1215
- pass
1216
- else:
1214
+
1217
1215
  pyfive.Dataset.register(DataVariable)
1218
1216
  pyfive.Dataset.register(DimensionScale)
1219
1217
  pyfive.Dataset.register(Variable)
1218
+ except Exception: # pragma: no cover
1219
+ pass
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: umfive
3
- Version: 0.2.2
3
+ Version: 0.3.0
4
4
  Summary: PP/Fields reader with pyfive-style high-level API
5
5
  Author: David Hassell, Alan Iwi, Bryan Lawrence, Valeriu Predoi - package
6
6
  License: MIT
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