pyhdf5-handler 0.7__tar.gz → 0.8__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 (29) hide show
  1. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/PKG-INFO +1 -1
  2. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/Release_note.txt +7 -0
  3. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/pyhdf5_handler/__init__.py +1 -1
  4. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/pyhdf5_handler/src/hdf5_handler.py +148 -27
  5. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/pyhdf5_handler/src/object_handler.py +191 -80
  6. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/pyhdf5_handler/tutorial/hdf5_io_tests.py +57 -10
  7. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/pyproject.toml +1 -1
  8. pyhdf5_handler-0.7/hdf5_database_rejeu_202311211359_202311030000_202311031200.hdf5 +0 -0
  9. pyhdf5_handler-0.7/test.hdf5 +0 -0
  10. pyhdf5_handler-0.7/test_fichier_julie.py +0 -42
  11. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/backups/codestyle.ini.bak +0 -0
  12. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/backups/encoding.ini.bak +0 -0
  13. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/backups/vcs.ini.bak +0 -0
  14. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/backups/workspace.ini.bak +0 -0
  15. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/codestyle.ini +0 -0
  16. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/defaults/defaults-codestyle-0.2.0.ini +0 -0
  17. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/defaults/defaults-encoding-0.2.0.ini +0 -0
  18. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/defaults/defaults-vcs-0.2.0.ini +0 -0
  19. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/defaults/defaults-workspace-0.2.0.ini +0 -0
  20. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/encoding.ini +0 -0
  21. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/vcs.ini +0 -0
  22. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/.spyproject/config/workspace.ini +0 -0
  23. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/LICENSE +0 -0
  24. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/README.md +0 -0
  25. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/mycontrol.hdf5 +0 -0
  26. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/pyhdf5_handler/src/__init__.py +0 -0
  27. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/pyhdf5_handler/src/constant.py +0 -0
  28. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/pyhdf5_handler/tutorial/__init__.py +0 -0
  29. {pyhdf5_handler-0.7 → pyhdf5_handler-0.8}/pyhdf5_handler/tutorial/complementary_test.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: pyhdf5_handler
3
- Version: 0.7
3
+ Version: 0.8
4
4
  Summary: A Python library to read and write data to HDF5 format. This library is based on the h5py (https://docs.h5py.org/en/stable/index.html) and has been developed by Maxime Jay-Allemand at Hydris hydrologie (https://www.hydris-hydrologie.fr/)
5
5
  Project-URL: Homepage, https://codeberg.org/maximejay/pyhdf5_handler
6
6
  Project-URL: Issues, https://codeberg.org/maximejay/pyhdf5_handler/issues
@@ -1,3 +1,10 @@
1
+ v0.8 : 19-06-2026
2
+ - relase 0.8
3
+ - Add support for pd.DataFrame()
4
+ - improve function map_dict_to_object
5
+ - Fix : return in hdf5_dataset_creator after parsing an unknown object
6
+ - Add function to map a dictionary to an object with a given structure
7
+
1
8
  v0.7 : 12-03-2026
2
9
  - Exclude some python object when parsing a dict or an object. For instance Geopandas and shapely are excluded, because pyhdf5_handler crash when handled these complex python object. Other module can be exclude using the global variable EXCLUDE_PYTHON_OBJ.
3
10
  - Fix: Max recursion counter was set to zeros at the begining of the recursive function.
@@ -4,6 +4,6 @@
4
4
 
5
5
  from .src.hdf5_handler import close_all_hdf5_file, open_hdf5, add_hdf5_sub_group, hdf5_dataset_creator, save_dict_to_hdf5, save_dict_to_hdf5file, save_object_to_hdf5file, read_hdf5file_as_dict, read_hdf5_as_dict, hdf5_read_dataset, get_hdf5file_attribute, get_hdf5file_dataset, get_hdf5file_item, get_hdf5_item, search_in_hdf5file, search_in_hdf5, hdf5file_view, hdf5file_ls, hdf5_ls, hdf5_view
6
6
 
7
- from .src.object_handler import generate_dict_structure, generate_object_structure, read_object_as_dict
7
+ from .src.object_handler import generate_dict_structure, generate_object_structure, read_object_as_dict, map_dict_to_object
8
8
 
9
9
  from .src.constant import EXCLUDE_PYTHON_OBJ
@@ -99,7 +99,9 @@ def open_hdf5(path, read_only=False, replace=False, wait_time=0):
99
99
  print(f"File {path} does not exist.")
100
100
  return f
101
101
  else:
102
- print(f"The file {path} is unvailable, waiting {wait}/{wait_time}s")
102
+ print(
103
+ f"The file {path} is unvailable, waiting {wait}/{wait_time}s"
104
+ )
103
105
 
104
106
  wait = wait + 1
105
107
 
@@ -216,13 +218,19 @@ def _dump_object_to_hdf5_from_dict_attribute(hdf5, instance, dict_attr):
216
218
  sub_instance = instance
217
219
 
218
220
  if isinstance(value, dict):
219
- _dump_object_to_hdf5_from_dict_attribute(hdf5[attr], sub_instance, value)
221
+ _dump_object_to_hdf5_from_dict_attribute(
222
+ hdf5[attr], sub_instance, value
223
+ )
220
224
 
221
225
  elif isinstance(value, list):
222
- _dump_object_to_hdf5_from_list_attribute(hdf5[attr], sub_instance, value)
226
+ _dump_object_to_hdf5_from_list_attribute(
227
+ hdf5[attr], sub_instance, value
228
+ )
223
229
 
224
230
  elif isinstance(value, str):
225
- _dump_object_to_hdf5_from_str_attribute(hdf5[attr], sub_instance, value)
231
+ _dump_object_to_hdf5_from_str_attribute(
232
+ hdf5[attr], sub_instance, value
233
+ )
226
234
 
227
235
  else:
228
236
 
@@ -392,6 +400,25 @@ def _hdf5_handle_DatetimeIndex(name: str, value: pd.DatetimeIndex):
392
400
  return dataset
393
401
 
394
402
 
403
+ def _hdf5_handle_PandaDataFrame(
404
+ hdf5: h5py.File, name: str, value: pd.DataFrame
405
+ ):
406
+
407
+ hdf5 = add_hdf5_sub_group(hdf5, subgroup=name)
408
+ hdf5_data = hdf5[name]
409
+
410
+ hdf5_data = add_hdf5_sub_group(hdf5_data, subgroup="pd_DataFrame")
411
+ hdf5_data = hdf5_data["pd_DataFrame"]
412
+
413
+ keys = _hdf5_handle_array("columns", np.array(list(value.columns)))
414
+ _hdf5_create_dataset(hdf5_data, keys)
415
+
416
+ dataset = _hdf5_handle_array("array", value.to_numpy())
417
+ _hdf5_create_dataset(hdf5_data, dataset)
418
+
419
+ return
420
+
421
+
395
422
  def _hdf5_handle_list(name: str, value: list | tuple):
396
423
 
397
424
  arr = np.array(value)
@@ -415,16 +442,18 @@ def _hdf5_handle_exclude_obj(name: str, value: list | tuple):
415
442
 
416
443
  return dataset
417
444
 
445
+
418
446
  def _hdf5_skip_cls(value):
419
-
447
+
420
448
  type_str = str(type(value))
421
- module_name = type_str.split("'")[1].split('.')[0]
422
-
449
+ module_name = type_str.split("'")[1].split(".")[0]
450
+
423
451
  if module_name in constant.EXCLUDE_PYTHON_OBJ:
424
452
  return True
425
453
  else:
426
454
  return False
427
455
 
456
+
428
457
  def _hdf5_handle_array(name: str, value: np.ndarray):
429
458
 
430
459
  dtype_attr = type(value)
@@ -503,10 +532,10 @@ def hdf5_dataset_creator(hdf5: h5py.File, name: str, value):
503
532
  value to write in the hdf5
504
533
 
505
534
  """
506
-
535
+
507
536
  if _hdf5_skip_cls(value):
508
537
  dataset = _hdf5_handle_exclude_obj(name, value)
509
-
538
+
510
539
  elif isinstance(value, str):
511
540
  dataset = _hdf5_handle_str(name, value)
512
541
 
@@ -522,6 +551,12 @@ def hdf5_dataset_creator(hdf5: h5py.File, name: str, value):
522
551
  elif isinstance(value, pd.DatetimeIndex):
523
552
  dataset = _hdf5_handle_DatetimeIndex(name, value)
524
553
 
554
+ # TODO : To be tested
555
+ elif isinstance(value, pd.DataFrame):
556
+
557
+ _hdf5_handle_PandaDataFrame(hdf5, name, value)
558
+ return
559
+
525
560
  elif isinstance(value, list):
526
561
  dataset = _hdf5_handle_list(name, value)
527
562
 
@@ -544,6 +579,8 @@ def hdf5_dataset_creator(hdf5: h5py.File, name: str, value):
544
579
 
545
580
  save_dict_to_hdf5(hdf5[name], newdict)
546
581
 
582
+ return
583
+
547
584
  _hdf5_create_dataset(hdf5, dataset)
548
585
 
549
586
 
@@ -601,6 +638,34 @@ def _dump_ndarray_to_hdf5(hdf5, value):
601
638
  )
602
639
 
603
640
 
641
+ def _read_pd_dataframe(hdf5):
642
+ """
643
+ read a pandas dataframe data structure from hdf5 file
644
+
645
+ Parameters
646
+ ----------
647
+
648
+ hdf5 : h5py.File
649
+ an hdf5 object at the roots of the ndarray datastructure
650
+
651
+ Return
652
+ ------
653
+
654
+ pd.DataFrame : the pandas dataframe
655
+
656
+ """
657
+
658
+ if "pd_DataFrame" in list(hdf5.keys()):
659
+ columns = hdf5["pd_DataFrame/columns"][:]
660
+ array = hdf5["pd_DataFrame/array"][:]
661
+
662
+ newdict = {}
663
+ for i, col in enumerate(columns):
664
+ newdict.update({col.decode(): array[:, i]})
665
+
666
+ return pd.DataFrame(newdict)
667
+
668
+
604
669
  def _read_ndarray_datastructure(hdf5):
605
670
  """
606
671
  read a ndarray data structure from hdf5 file
@@ -855,7 +920,11 @@ def save_object_to_hdf5file(
855
920
 
856
921
 
857
922
  def read_hdf5file_as_dict(
858
- path_to_hdf5, location="./", wait_time=0, read_attrs=True, read_dataset_attrs=False
923
+ path_to_hdf5,
924
+ location="./",
925
+ wait_time=0,
926
+ read_attrs=True,
927
+ read_dataset_attrs=False,
859
928
  ):
860
929
  """
861
930
 
@@ -897,7 +966,9 @@ def read_hdf5file_as_dict(
897
966
  return None
898
967
 
899
968
  dictionary = read_hdf5_as_dict(
900
- hdf5[location], read_attrs=read_attrs, read_dataset_attrs=read_dataset_attrs
969
+ hdf5[location],
970
+ read_attrs=read_attrs,
971
+ read_dataset_attrs=read_dataset_attrs,
901
972
  )
902
973
 
903
974
  hdf5.close()
@@ -936,7 +1007,9 @@ def read_hdf5_as_dict(hdf5, read_attrs=True, read_dataset_attrs=False):
936
1007
 
937
1008
  """
938
1009
 
939
- if not isinstance(hdf5, (h5py.File, h5py.Group, h5py.Dataset, h5py.Datatype)):
1010
+ if not isinstance(
1011
+ hdf5, (h5py.File, h5py.Group, h5py.Dataset, h5py.Datatype)
1012
+ ):
940
1013
  print("Error: input arg is not an instance of hdf5.File()")
941
1014
  return {}
942
1015
 
@@ -949,7 +1022,12 @@ def read_hdf5_as_dict(hdf5, read_attrs=True, read_dataset_attrs=False):
949
1022
  if key == "ndarray_ds":
950
1023
 
951
1024
  # dictionary.update({key: _read_ndarray_datastructure(hdf5)})
952
- return _read_ndarray_datastructure(hdf5)
1025
+ values = _read_ndarray_datastructure(hdf5)
1026
+ dictionary.update({key: values})
1027
+
1028
+ elif key == "pd_DataFrame":
1029
+ values = _read_pd_dataframe(hdf5)
1030
+ dictionary.update({key: values})
953
1031
 
954
1032
  else:
955
1033
 
@@ -970,14 +1048,17 @@ def read_hdf5_as_dict(hdf5, read_attrs=True, read_dataset_attrs=False):
970
1048
  list_attribute = []
971
1049
  if read_attrs or read_dataset_attrs:
972
1050
  tmp_list_attribute = list(hdf5.attrs.keys())
973
- hdf5_item_matching_attributes = ["_" + element for element in list(hdf5.keys())]
1051
+ hdf5_item_matching_attributes = [
1052
+ "_" + element for element in list(hdf5.keys())
1053
+ ]
974
1054
 
975
1055
  if read_attrs:
976
1056
 
977
1057
  list_attribute.extend(
978
1058
  list(
979
1059
  filter(
980
- lambda l: l not in hdf5_item_matching_attributes, tmp_list_attribute
1060
+ lambda l: l not in hdf5_item_matching_attributes,
1061
+ tmp_list_attribute,
981
1062
  )
982
1063
  )
983
1064
  )
@@ -985,7 +1066,12 @@ def read_hdf5_as_dict(hdf5, read_attrs=True, read_dataset_attrs=False):
985
1066
  if read_dataset_attrs:
986
1067
 
987
1068
  list_attribute.extend(
988
- list(filter(lambda l: l in hdf5_item_matching_attributes, tmp_list_attribute))
1069
+ list(
1070
+ filter(
1071
+ lambda l: l in hdf5_item_matching_attributes,
1072
+ tmp_list_attribute,
1073
+ )
1074
+ )
989
1075
  )
990
1076
 
991
1077
  for key in list_attribute:
@@ -1094,7 +1180,11 @@ def hdf5_read_dataset(item, expected_type=None):
1094
1180
 
1095
1181
  values = None
1096
1182
 
1097
- elif expected_type in (str(pd.Timestamp), str(np.datetime64), str(datetime.datetime)):
1183
+ elif expected_type in (
1184
+ str(pd.Timestamp),
1185
+ str(np.datetime64),
1186
+ str(datetime.datetime),
1187
+ ):
1098
1188
 
1099
1189
  if expected_type == str(pd.Timestamp):
1100
1190
  values = pd.Timestamp(item[0].decode())
@@ -1178,7 +1268,9 @@ def get_hdf5file_attribute(
1178
1268
  return return_attribute
1179
1269
 
1180
1270
 
1181
- def get_hdf5file_dataset(path_to_hdf5=str(), location="./", dataset=None, wait_time=0):
1271
+ def get_hdf5file_dataset(
1272
+ path_to_hdf5=str(), location="./", dataset=None, wait_time=0
1273
+ ):
1182
1274
  """
1183
1275
  Get the value of an attribute in the hdf5file
1184
1276
 
@@ -1230,7 +1322,11 @@ def get_hdf5file_dataset(path_to_hdf5=str(), location="./", dataset=None, wait_t
1230
1322
 
1231
1323
 
1232
1324
  def get_hdf5file_item(
1233
- path_to_hdf5=str(), location="./", item=None, wait_time=0, search_attrs=False
1325
+ path_to_hdf5=str(),
1326
+ location="./",
1327
+ item=None,
1328
+ wait_time=0,
1329
+ search_attrs=False,
1234
1330
  ):
1235
1331
  """
1236
1332
 
@@ -1273,7 +1369,10 @@ def get_hdf5file_item(
1273
1369
  return None
1274
1370
 
1275
1371
  hdf5_item = get_hdf5_item(
1276
- hdf5_instance=hdf5, location=location, item=item, search_attrs=search_attrs
1372
+ hdf5_instance=hdf5,
1373
+ location=location,
1374
+ item=item,
1375
+ search_attrs=search_attrs,
1277
1376
  )
1278
1377
 
1279
1378
  hdf5.close()
@@ -1281,7 +1380,9 @@ def get_hdf5file_item(
1281
1380
  return hdf5_item
1282
1381
 
1283
1382
 
1284
- def get_hdf5_item(hdf5_instance=None, location="./", item=None, search_attrs=False):
1383
+ def get_hdf5_item(
1384
+ hdf5_instance=None, location="./", item=None, search_attrs=False
1385
+ ):
1285
1386
  """
1286
1387
 
1287
1388
  Get a custom item in an hdf5file
@@ -1349,6 +1450,10 @@ def get_hdf5_item(hdf5_instance=None, location="./", item=None, search_attrs=Fal
1349
1450
 
1350
1451
  return _read_ndarray_datastructure(hdf5)
1351
1452
 
1453
+ elif item == "pd_DataFrame":
1454
+
1455
+ return _read_pd_dataframe(hdf5)
1456
+
1352
1457
  else:
1353
1458
 
1354
1459
  returned_dict = read_hdf5_as_dict(hdf5_item)
@@ -1420,7 +1525,9 @@ def search_in_hdf5file(
1420
1525
  if hdf5 is None:
1421
1526
  return None
1422
1527
 
1423
- results = search_in_hdf5(hdf5, key, location=location, search_attrs=search_attrs)
1528
+ results = search_in_hdf5(
1529
+ hdf5, key, location=location, search_attrs=search_attrs
1530
+ )
1424
1531
 
1425
1532
  hdf5.close()
1426
1533
 
@@ -1542,7 +1649,12 @@ def search_in_hdf5(hdf5_base, key=None, location="./", search_attrs=False):
1542
1649
  values = item[:]
1543
1650
 
1544
1651
  result.append(
1545
- {"path": location, "key": key, "datatype": "dataset", "value": values}
1652
+ {
1653
+ "path": location,
1654
+ "key": key,
1655
+ "datatype": "dataset",
1656
+ "value": values,
1657
+ }
1546
1658
  )
1547
1659
 
1548
1660
  return result
@@ -1774,14 +1886,17 @@ def hdf5_view(
1774
1886
  list_attribute = []
1775
1887
  if list_attrs or list_dataset_attrs:
1776
1888
  tmp_list_attribute = list(hdf5.attrs.keys())
1777
- list_keys_matching_attributes = ["_" + element for element in list(hdf5.keys())]
1889
+ list_keys_matching_attributes = [
1890
+ "_" + element for element in list(hdf5.keys())
1891
+ ]
1778
1892
 
1779
1893
  if list_attrs:
1780
1894
 
1781
1895
  list_attribute.extend(
1782
1896
  list(
1783
1897
  filter(
1784
- lambda l: l not in list_keys_matching_attributes, tmp_list_attribute
1898
+ lambda l: l not in list_keys_matching_attributes,
1899
+ tmp_list_attribute,
1785
1900
  )
1786
1901
  )
1787
1902
  )
@@ -1789,14 +1904,20 @@ def hdf5_view(
1789
1904
  if list_dataset_attrs:
1790
1905
 
1791
1906
  list_attribute.extend(
1792
- list(filter(lambda l: l in list_keys_matching_attributes, tmp_list_attribute))
1907
+ list(
1908
+ filter(
1909
+ lambda l: l in list_keys_matching_attributes,
1910
+ tmp_list_attribute,
1911
+ )
1912
+ )
1793
1913
  )
1794
1914
 
1795
1915
  for key in list_attribute:
1796
1916
  values = hdf5.attrs[key]
1797
1917
  sub_location = os.path.join(location, key)
1798
1918
  if isinstance(
1799
- values, (int, float, np.int64, np.float64, np.int32, np.float32, np.bool)
1919
+ values,
1920
+ (int, float, np.int64, np.float64, np.int32, np.float32, np.bool),
1800
1921
  ):
1801
1922
  result.append(
1802
1923
  f"{level_base}| {sub_location}, attribute, type={type(hdf5.attrs[key])}, value={values}"
@@ -1,4 +1,3 @@
1
-
2
1
  from __future__ import annotations
3
2
 
4
3
  import numpy as np
@@ -9,44 +8,62 @@ from ..src import constant
9
8
 
10
9
 
11
10
  def _isinstance_pandas(value):
12
- pandas_classes = [getattr(pd, item) for item in dir(pd) if isinstance(getattr(pd, item), type)]
11
+ pandas_classes = [
12
+ getattr(pd, item)
13
+ for item in dir(pd)
14
+ if isinstance(getattr(pd, item), type)
15
+ ]
13
16
  for cls in pandas_classes:
14
17
  if isinstance(value, cls):
15
18
  return True
16
19
  return False
17
20
 
21
+
18
22
  def _isinstance_numpy(value):
19
- numpy_classes = [getattr(np, item) for item in dir(np) if isinstance(getattr(np, item), type)]
23
+ numpy_classes = [
24
+ getattr(np, item)
25
+ for item in dir(np)
26
+ if isinstance(getattr(np, item), type)
27
+ ]
20
28
  for cls in numpy_classes:
21
29
  if isinstance(value, cls):
22
30
  return True
23
31
  return False
24
32
 
33
+
25
34
  def _isinstance_datetime(value):
26
- datetime_classes = [getattr(datetime, item) for item in dir(datetime) if isinstance(getattr(datetime, item), type)]
35
+ datetime_classes = [
36
+ getattr(datetime, item)
37
+ for item in dir(datetime)
38
+ if isinstance(getattr(datetime, item), type)
39
+ ]
27
40
  for cls in datetime_classes:
28
41
  if isinstance(value, cls):
29
42
  return True
30
43
  return False
31
44
 
45
+
32
46
  def _isinstance_exclude_obj(value):
33
-
47
+
34
48
  type_str = str(type(value))
35
- module_name = type_str.split("'")[1].split('.')[0]
36
-
49
+ module_name = type_str.split("'")[1].split(".")[0]
50
+
37
51
  if module_name in constant.EXCLUDE_PYTHON_OBJ:
38
52
  return True
39
53
  else:
40
54
  return False
41
55
 
42
- def generate_dict_structure(dictionary,recursion_counter=0,recursion_limit=100,include_method=True):
56
+
57
+ def generate_dict_structure(
58
+ dictionary, recursion_counter=0, recursion_limit=100, include_method=True
59
+ ):
43
60
  """
44
-
61
+
45
62
  this function create a full dictionnary containing all the structure of an dictionnary in order to save it to an hdf5
46
63
 
47
64
  Parameters
48
65
  ----------
49
-
66
+
50
67
  instance : python dictionary
51
68
  a custom dictionary.
52
69
  recursion_limit : int
@@ -58,70 +75,148 @@ def generate_dict_structure(dictionary,recursion_counter=0,recursion_limit=100,i
58
75
 
59
76
  Returns
60
77
  -------
61
-
78
+
62
79
  list or dict :
63
80
  A list or dictionary matching the structure of the python object.
64
-
81
+
65
82
  """
66
- key_data={}
83
+ key_data = {}
67
84
  key_list = list()
68
- recursion_counter=0
69
- for attr,value in dictionary.items():
70
-
85
+ recursion_counter = 0
86
+ for attr, value in dictionary.items():
87
+
71
88
  try:
72
89
  if _isinstance_exclude_obj(value):
73
90
  next(attrs)
74
- elif isinstance(value,dict):
75
- subkey_data=generate_dict_structure(value)
76
- if len(subkey_data)>0:
77
- key_data.update({attr:subkey_data})
78
-
91
+ elif isinstance(value, dict):
92
+ subkey_data = generate_dict_structure(value)
93
+ if len(subkey_data) > 0:
94
+ key_data.update({attr: subkey_data})
95
+
79
96
  elif isinstance(value, (list, tuple, numbers.Number, str)):
80
97
  key_list.append(attr)
81
-
98
+
82
99
  elif _isinstance_pandas(value):
83
100
  key_list.append(attr)
84
-
101
+
85
102
  elif _isinstance_datetime(value):
86
103
  key_list.append(attr)
87
-
104
+
88
105
  elif _isinstance_numpy(value):
89
106
  key_list.append(attr)
90
-
107
+
91
108
  elif type(value) == "method":
92
109
  if include_method:
93
110
  key_list.append(attr)
94
111
  else:
95
112
  next(attr)
96
113
  else:
97
-
98
- recursion_counter = recursion_counter+1
99
-
114
+
115
+ recursion_counter = recursion_counter + 1
116
+
100
117
  if recursion_counter > recursion_limit:
101
- print(f"recursion counter exceed the limit of {recursion_limit}... return")
118
+ print(
119
+ f"recursion counter exceed the limit of {recursion_limit}... return"
120
+ )
102
121
  return
103
-
104
- subkey_data = generate_object_structure(value,recursion_counter=recursion_counter,recursion_limit=recursion_limit,include_method=include_method)
122
+
123
+ subkey_data = generate_object_structure(
124
+ value,
125
+ recursion_counter=recursion_counter,
126
+ recursion_limit=recursion_limit,
127
+ include_method=include_method,
128
+ )
105
129
  if len(subkey_data) > 0:
106
130
  key_data.update({attr: subkey_data})
107
131
 
108
132
  except:
109
133
  pass
110
-
134
+
111
135
  for attr, value in key_data.items():
112
136
  key_list.append({attr: value})
113
-
137
+
114
138
  return key_list
115
139
 
116
140
 
117
- def generate_object_structure(instance,recursion_counter=0,recursion_limit=100,include_method=True):
141
+ def generate_object_from_dictionary(dictionary):
142
+
143
+ class Object:
144
+ def __init__(self):
145
+ pass
146
+
147
+ obj = Object()
148
+
149
+ if isinstance(dictionary, dict):
150
+ for attr, value in dictionary.items():
151
+
152
+ if isinstance(value, (dict, list, tuple)):
153
+ setattr(obj, attr, generate_object_from_dictionary(value))
154
+ else:
155
+ setattr(obj, attr, value)
156
+ elif isinstance(dictionary, (list, tuple)):
157
+ return dictionary
158
+ # for attr in dictionary:
159
+ # setattr(obj, attr, None)
160
+
161
+ return obj
162
+
163
+
164
+ def map_dict_to_object(structure, dictionary, obj):
165
+ """
166
+ Map a dictionary to an object knowing its structure.
167
+ Structure must be generated with generate_dict_structure or generate_object_structure. If the object or an attribute of this object is
168
+ None, a empty object is created to be able to set new attribute.
118
169
  """
119
-
170
+
171
+ class Object:
172
+ def __init__(self):
173
+ pass
174
+
175
+ if obj is None:
176
+ obj = Object()
177
+
178
+ if isinstance(structure, dict):
179
+
180
+ for attr, value in structure.items():
181
+ if isinstance(value, (dict, list, tuple)):
182
+
183
+ if not hasattr(obj, attr):
184
+ setattr(obj, str(attr), Object())
185
+ else:
186
+ if getattr(obj, attr) is None:
187
+ setattr(obj, str(attr), Object())
188
+
189
+ map_dict_to_object(value, dictionary[attr], getattr(obj, attr))
190
+ else:
191
+ v = None
192
+ if attr in dictionary.keys():
193
+ v = dictionary[attr]
194
+
195
+ setattr(obj, str(attr), v)
196
+
197
+ elif isinstance(structure, (list, tuple)):
198
+
199
+ for attr in structure:
200
+ if isinstance(attr, (dict, list, tuple)):
201
+ map_dict_to_object(attr, dictionary, obj)
202
+ else:
203
+ v = None
204
+ if attr in dictionary.keys():
205
+ v = dictionary[attr]
206
+
207
+ setattr(obj, str(attr), v)
208
+
209
+
210
+ def generate_object_structure(
211
+ instance, recursion_counter=0, recursion_limit=100, include_method=True
212
+ ):
213
+ """
214
+
120
215
  this function create a full dictionnary containing all the structure of an object in order to save it to an hdf5
121
216
 
122
217
  Parameters
123
218
  ----------
124
-
219
+
125
220
  instance : object
126
221
  a custom python object.
127
222
  recursion_limit : int
@@ -133,36 +228,36 @@ def generate_object_structure(instance,recursion_counter=0,recursion_limit=100,i
133
228
 
134
229
  Returns
135
230
  -------
136
-
231
+
137
232
  list or dict :
138
233
  A list or dictionary matching the structure of the python object.
139
-
234
+
140
235
  """
141
236
  key_data = {}
142
237
  key_list = list()
143
238
  return_list = False
144
- #recursion_counter += 1
239
+ # recursion_counter += 1
145
240
  for attr in dir(instance):
146
-
241
+
147
242
  if not attr.startswith("_") and not attr in ["from_handle", "copy"]:
148
-
243
+
149
244
  try:
150
245
  value = getattr(instance, attr)
151
-
246
+
152
247
  if _isinstance_exclude_obj(value):
153
248
  next(attr)
154
-
249
+
155
250
  elif isinstance(value, (list, tuple)):
156
251
  key_list.append(attr)
157
252
  return_list = True
158
-
253
+
159
254
  elif _isinstance_numpy(value):
160
255
  key_list.append(attr)
161
256
  return_list = True
162
-
257
+
163
258
  elif isinstance(value, dict):
164
-
165
- depp_key_data=generate_dict_structure(value)
259
+
260
+ depp_key_data = generate_dict_structure(value)
166
261
  if len(depp_key_data) > 0:
167
262
  key_data.update({attr: depp_key_data})
168
263
 
@@ -180,24 +275,35 @@ def generate_object_structure(instance,recursion_counter=0,recursion_limit=100,i
180
275
  return_list = True
181
276
  else:
182
277
  next(attr)
183
-
278
+
184
279
  elif _isinstance_pandas(value):
185
280
  key_list.append(attr)
186
281
  return_list = True
187
-
282
+
188
283
  elif _isinstance_datetime(value):
189
284
  key_list.append(attr)
190
285
  return_list = True
191
-
286
+
287
+ # ~ elif value is None:
288
+ # ~ key_list.append(attr)
289
+ # ~ return_list = True
290
+
192
291
  else:
193
-
194
- recursion_counter = recursion_counter+1
195
-
292
+
293
+ recursion_counter = recursion_counter + 1
294
+
196
295
  if recursion_counter > recursion_limit:
197
- print(f"recursion counter exceed the limit of {recursion_limit}... return")
296
+ print(
297
+ f"recursion counter exceed the limit of {recursion_limit}... return"
298
+ )
198
299
  return
199
-
200
- depp_key_data = generate_object_structure(value, recursion_counter=recursion_counter,recursion_limit=recursion_limit,include_method=include_method)
300
+
301
+ depp_key_data = generate_object_structure(
302
+ value,
303
+ recursion_counter=recursion_counter,
304
+ recursion_limit=recursion_limit,
305
+ include_method=include_method,
306
+ )
201
307
 
202
308
  if len(depp_key_data) > 0:
203
309
  key_data.update({attr: depp_key_data})
@@ -217,14 +323,14 @@ def generate_object_structure(instance,recursion_counter=0,recursion_limit=100,i
217
323
  return key_data
218
324
 
219
325
 
220
- def read_object_as_dict(instance, recursion_counter=0,recursion_limit=100):
326
+ def read_object_as_dict(instance, recursion_counter=0, recursion_limit=100):
221
327
  """
222
-
328
+
223
329
  create a dictionary from a custom python object
224
330
 
225
331
  Parameters
226
332
  ----------
227
-
333
+
228
334
  instance : object
229
335
  an custom python object
230
336
  recursion_limit : int
@@ -234,35 +340,35 @@ def read_object_as_dict(instance, recursion_counter=0,recursion_limit=100):
234
340
 
235
341
  Return
236
342
  ------
237
-
343
+
238
344
  key_data: dict
239
345
  an dictionary containing all keys and atributes of the object
240
-
346
+
241
347
  """
242
348
  key_data = {}
243
- #recursion_counter = 0
349
+ # recursion_counter = 0
244
350
  for attr in dir(instance):
245
- #print(attr)
351
+ # print(attr)
246
352
  if not attr.startswith("_") and not attr in ["from_handle", "copy"]:
247
353
  try:
248
354
  value = getattr(instance, attr)
249
-
355
+
250
356
  if _isinstance_exclude_obj(value):
251
357
  next(attr)
252
-
358
+
253
359
  elif isinstance(value, (list, tuple)):
254
-
360
+
255
361
  if isinstance(value, list):
256
- value = np.array(value).astype('U')
362
+ value = np.array(value).astype("U")
257
363
 
258
364
  if value.dtype == "object" or value.dtype.char == "U":
259
365
  value = value.astype("U")
260
-
366
+
261
367
  key_data.update({attr: value})
262
-
368
+
263
369
  elif isinstance(value, dict):
264
370
  key_data.update({attr: value})
265
-
371
+
266
372
  elif isinstance(value, numbers.Number):
267
373
  key_data.update({attr: value})
268
374
 
@@ -271,33 +377,38 @@ def read_object_as_dict(instance, recursion_counter=0,recursion_limit=100):
271
377
 
272
378
  elif type(value) == "method":
273
379
  next(attr)
274
-
380
+
275
381
  elif _isinstance_pandas(value):
276
382
  if value.dtype == "object" or value.dtype.char == "U":
277
383
  value = value.astype("U")
278
384
  key_data.update({attr: value})
279
-
385
+
280
386
  elif _isinstance_datetime(value):
281
387
  if value.dtype == "object" or value.dtype.char == "U":
282
388
  value = value.astype("U")
283
389
  key_data.update({attr: value})
284
-
390
+
285
391
  elif _isinstance_numpy(value):
286
392
  if value.dtype == "object" or value.dtype.char == "U":
287
393
  value = value.astype("U")
288
394
  key_data.update({attr: value})
289
395
 
290
396
  else:
291
-
292
- recursion_counter = recursion_counter+1
293
-
397
+
398
+ recursion_counter = recursion_counter + 1
399
+
294
400
  if recursion_counter > recursion_limit:
295
- print(f"recursion counter exceed the limit of {recursion_limit}... return")
401
+ print(
402
+ f"recursion counter exceed the limit of {recursion_limit}... return"
403
+ )
296
404
  return
297
-
405
+
298
406
  depp_key_data = read_object_as_dict(
299
- value, recursion_counter=recursion_counter,recursion_limit=recursion_limit)
300
-
407
+ value,
408
+ recursion_counter=recursion_counter,
409
+ recursion_limit=recursion_limit,
410
+ )
411
+
301
412
  if len(depp_key_data) > 0:
302
413
  key_data.update({attr: depp_key_data})
303
414
 
@@ -22,7 +22,9 @@ if __name__ == "__main__":
22
22
  hdf5, "timestamp_numpy", np.datetime64("2019-09-22T17:38:30")
23
23
  )
24
24
  pyhdf5_handler.hdf5_dataset_creator(
25
- hdf5, "timestamp_datetime", datetime.datetime.fromisoformat("2019-09-22T17:38:30")
25
+ hdf5,
26
+ "timestamp_datetime",
27
+ datetime.datetime.fromisoformat("2019-09-22T17:38:30"),
26
28
  )
27
29
  pyhdf5_handler.hdf5_dataset_creator(
28
30
  hdf5, "timestamp_pandas", pd.Timestamp("2019-09-22T17:38:30")
@@ -33,7 +35,10 @@ if __name__ == "__main__":
33
35
  pyhdf5_handler.hdf5_dataset_creator(
34
36
  hdf5,
35
37
  "list_date_numpy",
36
- [np.datetime64("2019-09-22 17:38:30"), np.datetime64("2019-09-22 18:38:30")],
38
+ [
39
+ np.datetime64("2019-09-22 17:38:30"),
40
+ np.datetime64("2019-09-22 18:38:30"),
41
+ ],
37
42
  )
38
43
  pyhdf5_handler.hdf5_dataset_creator(
39
44
  hdf5,
@@ -46,10 +51,28 @@ if __name__ == "__main__":
46
51
  pyhdf5_handler.hdf5_dataset_creator(
47
52
  hdf5,
48
53
  "list_date_pandas",
49
- [pd.Timestamp("2019-09-22 17:38:30"), pd.Timestamp("2019-09-22 17:38:30")],
54
+ [
55
+ pd.Timestamp("2019-09-22 17:38:30"),
56
+ pd.Timestamp("2019-09-22 17:38:30"),
57
+ ],
58
+ )
59
+ pyhdf5_handler.hdf5_dataset_creator(
60
+ hdf5,
61
+ "list_date_range_pandas",
62
+ pd.date_range(start="1/1/2018", end="1/08/2018"),
50
63
  )
64
+
51
65
  pyhdf5_handler.hdf5_dataset_creator(
52
- hdf5, "list_date_range_pandas", pd.date_range(start="1/1/2018", end="1/08/2018")
66
+ hdf5,
67
+ "panda_dataframe_onecolumn",
68
+ pd.DataFrame({"column1": np.array([1, 2, 3])}),
69
+ )
70
+ pyhdf5_handler.hdf5_dataset_creator(
71
+ hdf5,
72
+ "panda_dataframe",
73
+ pd.DataFrame(
74
+ {"column1": np.array([1, 2, 3]), "column2": np.array([4, 5, 6])}
75
+ ),
53
76
  )
54
77
 
55
78
  # write a python dictionary in the hdf5 database
@@ -88,7 +111,9 @@ if __name__ == "__main__":
88
111
  data = pyhdf5_handler.read_hdf5_as_dict(hdf5, read_attrs=True)
89
112
 
90
113
  # read a specific item
91
- pyhdf5_handler.hdf5_read_dataset(item=hdf5["str"], expected_type=hdf5.attrs["_str"])
114
+ pyhdf5_handler.hdf5_read_dataset(
115
+ item=hdf5["str"], expected_type=hdf5.attrs["_str"]
116
+ )
92
117
  pyhdf5_handler.hdf5_read_dataset(
93
118
  item=hdf5["numpy_numbers"], expected_type=hdf5.attrs["_numpy_numbers"]
94
119
  )
@@ -96,7 +121,18 @@ if __name__ == "__main__":
96
121
  item=hdf5["numbers"], expected_type=hdf5.attrs["_numbers"]
97
122
  )
98
123
  pyhdf5_handler.hdf5_read_dataset(
99
- item=hdf5["list_date_numpy"], expected_type=hdf5.attrs["_list_date_numpy"]
124
+ item=hdf5["list_date_numpy"],
125
+ expected_type=hdf5.attrs["_list_date_numpy"],
126
+ )
127
+
128
+ # getting specific item
129
+ pyhdf5_handler.get_hdf5_item(
130
+ hdf5_instance=hdf5,
131
+ location="./panda_dataframe",
132
+ )
133
+ pyhdf5_handler.get_hdf5_item(
134
+ hdf5_instance=hdf5,
135
+ location="./structured_array",
100
136
  )
101
137
 
102
138
  # close the hdf5
@@ -106,7 +142,9 @@ if __name__ == "__main__":
106
142
  pyhdf5_handler.hdf5file_ls("./test.hdf5")
107
143
  pyhdf5_handler.hdf5file_ls("./test.hdf5", location="structured_array")
108
144
 
109
- data = pyhdf5_handler.read_hdf5file_as_dict("./test.hdf5", read_attrs=False)
145
+ data = pyhdf5_handler.read_hdf5file_as_dict(
146
+ "./test.hdf5", read_attrs=False
147
+ )
110
148
 
111
149
  pyhdf5_handler.save_dict_to_hdf5file("./test.hdf5", data)
112
150
 
@@ -154,15 +192,24 @@ if __name__ == "__main__":
154
192
  )
155
193
 
156
194
  pyhdf5_handler.get_hdf5file_item(
157
- path_to_hdf5="./test.hdf5", location="./", item="list_mixte", search_attrs=False
195
+ path_to_hdf5="./test.hdf5",
196
+ location="./",
197
+ item="list_mixte",
198
+ search_attrs=False,
158
199
  )
159
200
 
160
201
  pyhdf5_handler.get_hdf5file_item(
161
- path_to_hdf5="./test.hdf5", location="./", item="attribute", search_attrs=True
202
+ path_to_hdf5="./test.hdf5",
203
+ location="./",
204
+ item="attribute",
205
+ search_attrs=True,
162
206
  )
163
207
 
164
208
  pyhdf5_handler.get_hdf5file_attribute(
165
- path_to_hdf5="./test.hdf5", location="./", attribute="_list_num", wait_time=0
209
+ path_to_hdf5="./test.hdf5",
210
+ location="./",
211
+ attribute="_list_num",
212
+ wait_time=0,
166
213
  )
167
214
 
168
215
  pyhdf5_handler.get_hdf5file_attribute(
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "pyhdf5_handler"
7
- version = "0.7"
7
+ version = "0.8"
8
8
  authors = [
9
9
  { name="Maxime Jay-Allemand", email="maxime.jay.allemand@hydris-hydrologie.fr" },
10
10
  ]
Binary file
@@ -1,42 +0,0 @@
1
- import pyhdf5_handler
2
- import numpy as np
3
-
4
- #states
5
- pyhdf5_handler.hdf5file_view("202309010300_states.hdf5")
6
-
7
- res=pyhdf5_handler.read_hdf5file_as_dict("202309010300_states.hdf5")
8
- res.keys()
9
- res["202309010300"].keys()
10
- res["202309010300"]["keys"][0].decode()
11
- res["202309010300"]["keys"][:].astype("str")
12
-
13
- states=res["202309010300"]["values"]
14
-
15
- states=pyhdf5_handler.get_hdf5file_item("202309010300_states.hdf5",location="./202309010300",item="values")
16
-
17
- search=pyhdf5_handler.search_in_hdf5file("202309010300_states.hdf5","values")
18
- res=search[0]
19
- res.keys()
20
- res["path"]
21
- res["key"]
22
- res["datatype"]
23
- res["value"]
24
-
25
- #prévis ensemble:
26
- pyhdf5_handler.hdf5file_view("20230901030000_qens.hdf5")
27
-
28
- res=pyhdf5_handler.read_hdf5file_as_dict("20230901030000_qens.hdf5")
29
-
30
- res.keys()
31
- res["20230901030000"].keys()
32
- Q=res["20230901030000"]["member0"]
33
-
34
- Q=pyhdf5_handler.get_hdf5file_item("20230901030000_qens.hdf5",location="./20230901030000",item="member8")
35
-
36
- search=pyhdf5_handler.search_in_hdf5file("20230901030000_qens.hdf5","member8")
37
- res=search[0]
38
- res.keys()
39
- res["path"]
40
- res["key"]
41
- res["datatype"]
42
- res["value"]
File without changes
File without changes