Skip to content

Commit 4223c32

Browse files
Validation (#14)
* access to property kind by uuid and better validation * bugfix : obj_ prefix is now printed for resqml201 objects
1 parent 923d4c0 commit 4223c32

File tree

7 files changed

+269
-49
lines changed

7 files changed

+269
-49
lines changed

energyml-utils/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ This package supports read/write in xml/json the following packages :
4040
- WITSMl : 2.0, 2.1
4141
- PRODML : 2.0, 2.2
4242

43-
/!\\ By default, these package are not installed and are published independently.
43+
/!\\ By default, these packages are not installed and are published independently.
4444
You can install only the versions you need by adding the following lines in the .toml file :
4545
```toml
4646
energyml-common2-0 = "^1.12.0"

energyml-utils/example/main.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -486,10 +486,13 @@ def test_dor_conversion():
486486
# test_get_projected_uom()
487487
# test_crs()
488488
# test_dor_conversion()
489-
print(get_obj_uri(tr, "coucou"))
489+
# print(get_obj_uri(tr, "coucou"))
490490

491491
tr201 = Tr20(
492492
citation=tr_cit,
493493
uuid=gen_uuid(),
494494
)
495-
print(get_obj_uri(tr201, "coucou"))
495+
# print(get_obj_uri(tr201, "coucou"))
496+
497+
print(get_usable_class(tr))
498+
print(get_usable_class(tr201))

energyml-utils/src/energyml/utils/data/datasets_io.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@
5252
# HDF5
5353
if __H5PY_MODULE_EXISTS__:
5454

55-
def h5_list_datasets(h5_file_path):
55+
def h5_list_datasets(h5_file_path: Union[BytesIO, str]) -> List[str]:
5656
"""
5757
List all datasets in an HDF5 file.
5858
:param h5_file_path: Path to the HDF5 file
@@ -93,28 +93,31 @@ def extract_h5_datasets(
9393
:param h5_datasets_paths:
9494
:return:
9595
"""
96+
if h5_datasets_paths is None:
97+
h5_datasets_paths = h5_list_datasets(input_h5)
9698
if len(h5_datasets_paths) > 0:
97-
with h5py.File(output_h5, "w") as f_dest:
99+
with h5py.File(output_h5, "a") as f_dest:
98100
with h5py.File(input_h5, "r") as f_src:
99101
for dataset in h5_datasets_paths:
100102
f_dest.create_dataset(dataset, data=f_src[dataset])
101103

102104
@dataclass
103105
class HDF5FileWriter:
106+
104107
def write_array(
105108
self,
106109
target: Union[str, BytesIO, bytes],
107-
array: Union[list, np.array],
110+
array: Union[list, np.ndarray],
108111
path_in_external_file: str,
109-
dtype: Optional = None,
112+
dtype: Optional[np.dtype] = None,
110113
):
111114
if isinstance(array, list):
112115
array = np.asarray(array)
113116
print("writing array", target)
114117
with h5py.File(target, "a") as f:
115118
# print(array.dtype, h5py.string_dtype(), array.dtype == 'O')
116119
# print("\t", dtype or (h5py.string_dtype() if array.dtype == '0' else array.dtype))
117-
if array.dtype == "O":
120+
if isinstance(array, np.ndarray) and array.dtype == "O":
118121
array = np.asarray([s.encode() if isinstance(s, str) else s for s in array])
119122
np.void(array)
120123
dset = f.create_dataset(path_in_external_file, array.shape, dtype or array.dtype)

energyml-utils/src/energyml/utils/epc.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -627,6 +627,21 @@ def update_prop_kind_dict_cache():
627627
__CACHE_PROP_KIND_DICT__[prop["Uuid"]] = read_energyml_json_str(json.dumps(prop))[0]
628628

629629

630+
def get_property_kind_by_uuid(uuid: str) -> Optional[Any]:
631+
"""
632+
Get a property kind by its uuid.
633+
:param uuid: the uuid of the property kind
634+
:return: the property kind or None if not found
635+
"""
636+
if len(__CACHE_PROP_KIND_DICT__) == 0:
637+
# update the cache to check if it is a
638+
try:
639+
update_prop_kind_dict_cache()
640+
except FileNotFoundError as e:
641+
logging.error(f"Failed to parse propertykind dict {e}")
642+
return __CACHE_PROP_KIND_DICT__.get(uuid, None)
643+
644+
630645
def as_dor(obj_or_identifier: Any, dor_qualified_type: str = "eml23.DataObjectReference"):
631646
"""
632647
Create an DOR from an object to target the latter.

energyml-utils/src/energyml/utils/introspection.py

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1167,6 +1167,45 @@ def get_direct_dor_list(obj: Any) -> List[Any]:
11671167
return search_attribute_matching_type(obj, "DataObjectreference")
11681168

11691169

1170+
def get_obj_usable_class(o: Any) -> Optional[type]:
1171+
"""Used only for resqml201 that has classes Obj_TriangulatedSetRepresentation and TriangulatedSetRepresentation for example.
1172+
This function will return Obj_TriangulatedSetRepresentation class
1173+
"""
1174+
1175+
if o is not None:
1176+
if not isinstance(o, type):
1177+
o = type(o)
1178+
if isinstance(o, type):
1179+
if o.__bases__ is not None:
1180+
for bc in o.__bases__:
1181+
# print(bc)
1182+
if bc.__name__.lower() == f"obj{get_obj_type(o).lower()}":
1183+
return bc
1184+
return o if isinstance(o, type) else None
1185+
return None
1186+
1187+
1188+
def as_obj_prefixed_class_if_possible(o: Any) -> Any:
1189+
"""Used only for resqml201 that has classes Obj_TriangulatedSetRepresentation and TriangulatedSetRepresentation for example.
1190+
This function will return an instance of Obj_TriangulatedSetRepresentation if possible
1191+
"""
1192+
if o is not None:
1193+
if not isinstance(o, type):
1194+
o_type = type(o)
1195+
if o_type.__bases__ is not None:
1196+
for bc in o_type.__bases__:
1197+
# print(bc)
1198+
if bc.__name__.lower() == f"obj{get_obj_type(o_type).lower()}":
1199+
try:
1200+
return bc(**o.__dict__)
1201+
except Exception as e:
1202+
logging.error(f"Failed to convert {o} to {bc}")
1203+
logging.error(e)
1204+
return o
1205+
return o
1206+
return None
1207+
1208+
11701209
def get_data_object_type(cls: Union[type, Any], print_dev_version=True, nb_max_version_digits=2):
11711210
return get_class_pkg(cls) + "." + get_class_pkg_version(cls, print_dev_version, nb_max_version_digits)
11721211

@@ -1515,3 +1554,81 @@ def _random_value_from_class(
15151554

15161555
logging.error(f"@_random_value_from_class Not supported object type generation {cls}")
15171556
return None
1557+
1558+
1559+
if __name__ == "__main__":
1560+
1561+
from energyml.eml.v2_3.commonv2 import *
1562+
from energyml.eml.v2_0.commonv2 import Citation as Cit201
1563+
from energyml.resqml.v2_0_1.resqmlv2 import TriangulatedSetRepresentation as Tr20, ObjTriangulatedSetRepresentation
1564+
from energyml.resqml.v2_2.resqmlv2 import (
1565+
TriangulatedSetRepresentation,
1566+
FaultInterpretation,
1567+
)
1568+
from .serialization import *
1569+
1570+
fi_cit = Citation(
1571+
title="An interpretation",
1572+
originator="Valentin",
1573+
creation=epoch_to_date(epoch()),
1574+
editor="test",
1575+
format="Geosiris",
1576+
last_update=epoch_to_date(epoch()),
1577+
)
1578+
1579+
fi = FaultInterpretation(
1580+
citation=fi_cit,
1581+
uuid=gen_uuid(),
1582+
object_version="0",
1583+
)
1584+
1585+
tr_cit = Citation(
1586+
title="--",
1587+
# title="test title",
1588+
originator="Valentin",
1589+
creation=epoch_to_date(epoch()),
1590+
editor="test",
1591+
format="Geosiris",
1592+
last_update=epoch_to_date(epoch()),
1593+
)
1594+
1595+
tr_cit201 = Cit201(
1596+
title="--",
1597+
# title="test title",
1598+
originator="Valentin",
1599+
# creation=str(epoch_to_date(epoch()))
1600+
editor="test",
1601+
format="Geosiris",
1602+
# last_update=str(epoch_to_date(epoch())),
1603+
)
1604+
dor = DataObjectReference(
1605+
uuid=fi.uuid,
1606+
title="a DOR title",
1607+
object_version="0",
1608+
qualified_type="a wrong qualified type",
1609+
)
1610+
tr = TriangulatedSetRepresentation(
1611+
citation=tr_cit,
1612+
uuid=gen_uuid(),
1613+
represented_object=dor,
1614+
)
1615+
1616+
tr201 = Tr20(
1617+
citation=tr_cit201,
1618+
uuid=gen_uuid(),
1619+
)
1620+
tr201_bis = ObjTriangulatedSetRepresentation(
1621+
citation=tr_cit201,
1622+
uuid=gen_uuid(),
1623+
)
1624+
# print(get_obj_uri(tr201, "coucou"))
1625+
1626+
print(get_obj_usable_class(tr))
1627+
print(get_obj_usable_class(tr201))
1628+
1629+
print(serialize_xml(tr201_bis))
1630+
print(serialize_xml(tr201))
1631+
print(serialize_json(tr201))
1632+
print(serialize_xml(as_obj_prefixed_class_if_possible(tr201)))
1633+
print("--> ", serialize_json(tr))
1634+
# print(serialize_xml((get_usable_class(tr201))(tr201)))

energyml-utils/src/energyml/utils/serialization.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525

2626
from .exception import UnknownTypeFromQualifiedType, NotParsableType
2727
from .introspection import (
28+
as_obj_prefixed_class_if_possible,
2829
get_class_from_name,
2930
get_energyml_class_in_related_dev_pkg,
3031
get_class_from_content_type,
@@ -254,6 +255,7 @@ def read_energyml_json_file(
254255

255256

256257
def serialize_xml(obj) -> str:
258+
obj = as_obj_prefixed_class_if_possible(obj)
257259
context = XmlContext(
258260
# element_name_generator=text.camel_case,
259261
# attribute_name_generator=text.kebab_case
@@ -264,6 +266,7 @@ def serialize_xml(obj) -> str:
264266

265267

266268
def serialize_json(obj, json_version: JSON_VERSION = JSON_VERSION.OSDU_OFFICIAL) -> str:
269+
obj = as_obj_prefixed_class_if_possible(obj)
267270
if json_version == JSON_VERSION.XSDATA:
268271
context = XmlContext(
269272
# element_name_generator=text.camel_case,

0 commit comments

Comments
 (0)