Skip to content

Commit 694e6dd

Browse files
Dev 05 25 (#13)
* adding type tips in random data generation if type not found * bugfix for h5 dataset reading * including json property dict
1 parent 50e977e commit 694e6dd

File tree

6 files changed

+80686
-36
lines changed

6 files changed

+80686
-36
lines changed

energyml-utils/example/main.py

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
from energyml.eml.v2_3.commonv2 import *
88
from energyml.eml.v2_3.commonv2 import AbstractObject
99
from energyml.resqml.v2_0_1.resqmlv2 import DoubleHdf5Array
10+
from energyml.resqml.v2_0_1.resqmlv2 import TriangulatedSetRepresentation as Tr20
1011
from energyml.resqml.v2_2.resqmlv2 import (
1112
TriangulatedSetRepresentation,
1213
FaultInterpretation,
@@ -484,4 +485,11 @@ def test_dor_conversion():
484485
# class_field()
485486
# test_get_projected_uom()
486487
# test_crs()
487-
test_dor_conversion()
488+
# test_dor_conversion()
489+
print(get_obj_uri(tr, "coucou"))
490+
491+
tr201 = Tr20(
492+
citation=tr_cit,
493+
uuid=gen_uuid(),
494+
)
495+
print(get_obj_uri(tr201, "coucou"))

energyml-utils/example/tools.py

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,13 @@
88

99
from src.energyml.utils.constants import get_property_kind_dict_path_as_xml
1010
from src.energyml.utils.data.datasets_io import CSVFileReader, HDF5FileWriter, ParquetFileWriter, DATFileReader
11-
from src.energyml.utils.data.mesh import MeshFileFormat, export_multiple_data
11+
from src.energyml.utils.data.mesh import MeshFileFormat, export_multiple_data, export_obj, read_mesh_object
1212
from src.energyml.utils.epc import Epc, gen_energyml_object_path
1313
from src.energyml.utils.introspection import (
1414
get_class_from_simple_name,
15+
get_module_name_and_type_from_content_or_qualified_type,
1516
random_value_from_class,
17+
search_class_in_module_from_partial_name,
1618
set_attribute_from_path,
1719
get_object_attribute,
1820
get_qualified_type_from_class,
@@ -294,6 +296,14 @@ def generate_data():
294296
except NameError:
295297
obj_class = get_class_from_qualified_type(args.type)
296298

299+
if obj_class is None:
300+
print("Class not found, please check the type name.")
301+
print("Possible types are :")
302+
module_name, object_type = get_module_name_and_type_from_content_or_qualified_type(args.type)
303+
for cn in search_class_in_module_from_partial_name(module_name, object_type):
304+
print(f" - {cn.__name__}")
305+
return
306+
297307
obj = random_value_from_class(obj_class)
298308
if args.file_format.lower() == "xml":
299309
print(serialize_xml(obj))
@@ -524,3 +534,26 @@ def describe_as_csv():
524534
out.write("\n")
525535

526536
print("Finished")
537+
538+
539+
# def export_wavefront():
540+
# parser = argparse.ArgumentParser()
541+
# parser.add_argument("--epc", "-f", type=str, help="Epc file path")
542+
# parser.add_argument("--output", "-o", type=str, help="Output folder path")
543+
# parser.add_argument("--uuid", "-u", type=str, help="The uuids of representations to extract", nargs="+")
544+
545+
# args = parser.parse_args()
546+
547+
# epc = Epc.read_file(args.epc)
548+
# for uuid in args.uuid:
549+
# obj = epc.get_object_by_uuid(uuid)[0]
550+
551+
# mesh = read_mesh_object(
552+
# energyml_object=obj,
553+
# workspace=epc,
554+
# )
555+
556+
# if obj is not None:
557+
# fname = gen_energyml_object_path(obj)
558+
# with open(os.path.join(args.output, fname + ".obj"), "w") as f:
559+
# export_obj(mesh_list=mesh, out=f) # Assuming the object can be serialized to XML

energyml-utils/pyproject.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,10 @@ keywords = ["energyml", "resqml", "witsml", "prodml"]
3838
packages = [
3939
{ include = "energyml", from = "src" },
4040
]
41+
include = [
42+
"src/energyml/utils/rc/*.xml",
43+
"src/energyml/utils/rc/*.json"
44+
]
4145
#exclude = [
4246
# "src/energyml/main.py"
4347
#]

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

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

55+
def h5_list_datasets(h5_file_path):
56+
"""
57+
List all datasets in an HDF5 file.
58+
:param h5_file_path: Path to the HDF5 file
59+
:return: List of dataset names in the HDF5 file
60+
"""
61+
res = []
62+
with h5py.File(h5_file_path, "r") as f:
63+
# Function to print the names of all datasets
64+
def list_datasets(name, obj):
65+
if isinstance(obj, h5py.Dataset): # Check if the object is a dataset
66+
res.append(name)
67+
68+
# Visit all items in the HDF5 file and apply the list function
69+
f.visititems(list_datasets)
70+
return res
71+
5572
@dataclass
5673
class HDF5FileReader(DatasetReader):
5774
def read_array(self, source: Union[BytesIO, str], path_in_external_file: str) -> Optional[List[Any]]:
@@ -481,10 +498,8 @@ def get_external_file_path_from_external_path(
481498

482499
def get_external_file_path_possibilities_from_folder(file_raw_path: str, folder_path: str) -> List[str]:
483500
external_path_respect = file_raw_path
484-
external_path_rematch = (
485-
f"{folder_path + '/' if folder_path is not None and len(folder_path) else ''}{os.path.basename(file_raw_path)}"
486-
)
487-
external_path_no_folder = f"{os.path.basename(file_raw_path)}"
501+
external_path_rematch = f"{folder_path + '/' if folder_path is not None and len(folder_path) else ''}{os.path.basename(file_raw_path or '')}"
502+
external_path_no_folder = f"{os.path.basename(file_raw_path)}" if file_raw_path is not None else ""
488503

489504
return [
490505
external_path_respect,
@@ -542,7 +557,8 @@ def read_external_dataset_array(
542557
break # stop after the first read success
543558
except MissingExtraInstallation as mei:
544559
raise mei
545-
except OSError as e:
560+
except Exception as e:
561+
logging.debug(f"Failed to read external file {s} for {path_in_obj} with path {path_in_external} : {e}")
546562
pass
547563
if not succeed:
548564
raise Exception(f"Failed to read external file. Paths tried : {sources}")

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

Lines changed: 49 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -97,6 +97,24 @@ def find_class_in_module(module_name, class_name):
9797
return None
9898

9999

100+
def search_class_in_module_from_partial_name(module_name: str, class_partial_name: str) -> Optional[List[type]]:
101+
"""
102+
Search a class in a module using a partial name.
103+
:param module_name: The name of the module to search in.
104+
:param class_partial_name: The partial name of the class to search for.
105+
:return: A list of classes that match the partial name.
106+
107+
"""
108+
try:
109+
module = import_module(module_name)
110+
classes = get_module_classes_from_name(module_name)
111+
matching_classes = [cls for cls_name, cls in classes if class_partial_name.lower() in cls_name.lower()]
112+
return matching_classes
113+
except ImportError as e:
114+
logging.error(f"Module '{module_name}' not found: {e}")
115+
return None
116+
117+
100118
def get_class_methods(cls: Union[type, Any]) -> List[str]:
101119
"""
102120
Returns the list of the methods names for a specific class.
@@ -196,44 +214,32 @@ def get_energyml_class_in_related_dev_pkg(cls: type):
196214
return res
197215

198216

199-
def get_class_from_qualified_type(qualified_type: str) -> Optional[type]:
200-
return get_class_from_content_type(qualified_type)
201-
202-
203-
def get_class_from_content_type(content_type: str) -> Optional[type]:
217+
def get_module_name_and_type_from_content_or_qualified_type(cqt: str) -> Tuple[str, str]:
204218
"""
205-
Return a :class:`type` object matching with the content-type :param:`content_type`.
206-
:param content_type:
207-
:return:
219+
Return a tuple (module_name, type) from a content-type or qualified-type string.
208220
"""
209221
ct = None
210222
try:
211-
ct = parse_content_type(content_type)
223+
ct = parse_content_type(cqt)
212224
except AttributeError:
213225
pass
214226
if ct is None:
215227
try:
216-
ct = parse_qualified_type(content_type)
228+
ct = parse_qualified_type(cqt)
217229
except AttributeError:
218230
pass
219231

220232
domain = ct.group("domain")
221233
if domain is None:
222234
# logging.debug(f"\tdomain {domain} xmlDomain {ct.group('xmlDomain')} ")
223235
domain = "opc"
236+
224237
if domain == "opc":
225238
xml_domain = ct.group("xmlDomain")
226239
if "." in xml_domain:
227240
xml_domain = xml_domain[xml_domain.rindex(".") + 1 :]
228-
# Don't know what to do with http://schemas.f2i-consulting.com/package/2014/metadata/extended-core-properties
229-
# if "extended" in xml_domain:
230-
# xml_domain = xml_domain.replace("extended", "")
231-
# if xml_domain.startswith("-"):
232-
# xml_domain = xml_domain[1:]
233-
#
234241
opc_type = pascal_case(xml_domain).replace("-", "")
235-
# logging.debug("\tenergyml.opc.opc." + opc_type)
236-
return get_class_from_name("energyml.opc.opc." + opc_type)
242+
return ("energyml.opc.opc", opc_type)
237243
else:
238244
domain = ct.group("domain")
239245
obj_type = ct.group("type")
@@ -246,10 +252,21 @@ def get_class_from_content_type(content_type: str) -> Optional[type]:
246252
if domain.lower() == "resqml" and version_num.startswith("2_0"):
247253
version_num = "2_0_1"
248254

249-
# logging.debug(get_module_name(domain, version_num)
250-
# + "."
251-
# + obj_type)
252-
return get_class_from_name(get_module_name(domain, version_num) + "." + obj_type)
255+
return (get_module_name(domain, version_num), obj_type)
256+
257+
258+
def get_class_from_qualified_type(qualified_type: str) -> Optional[type]:
259+
return get_class_from_content_type(qualified_type)
260+
261+
262+
def get_class_from_content_type(content_type: str) -> Optional[type]:
263+
"""
264+
Return a :class:`type` object matching with the content-type :param:`content_type`.
265+
:param content_type:
266+
:return:
267+
"""
268+
module_name, object_type = get_module_name_and_type_from_content_or_qualified_type(content_type)
269+
return get_class_from_name(module_name + "." + object_type)
253270

254271

255272
def get_module_name(domain: str, domain_version: str):
@@ -1078,7 +1095,7 @@ def get_obj_pkg_pkgv_type_uuid_version(
10781095

10791096
if ct is not None:
10801097
ct_match = parse_content_type(ct)
1081-
logging.debug("ct : ", ct_match)
1098+
logging.debug("ct : %S", ct_match)
10821099
if ct_match is not None:
10831100
pkg = ct_match.group("domain")
10841101
pkg_v = ct_match.group("domainVersion")
@@ -1087,7 +1104,7 @@ def get_obj_pkg_pkgv_type_uuid_version(
10871104
try:
10881105
qt = get_object_attribute_no_verif(obj, "qualified_type")
10891106
qt_match = parse_qualified_type(qt)
1090-
logging.debug("qt : ", qt, obj.__dict__, qt_match)
1107+
logging.debug("qt : %s %s", qt, obj.__dict__, qt_match)
10911108
if qt_match is not None:
10921109
pkg = qt_match.group("domain")
10931110
pkg_v = qt_match.group("domainVersion")
@@ -1392,11 +1409,14 @@ def random_value_from_class(cls: type):
13921409
if not is_primitive(cls):
13931410
# import_related_module(cls.__module__)
13941411
energyml_module_context = get_related_energyml_modules_name(cls)
1395-
return _random_value_from_class(
1396-
cls=cls,
1397-
energyml_module_context=energyml_module_context,
1398-
attribute_name=None,
1399-
)
1412+
if cls is not None:
1413+
return _random_value_from_class(
1414+
cls=cls,
1415+
energyml_module_context=energyml_module_context,
1416+
attribute_name=None,
1417+
)
1418+
else:
1419+
return None
14001420

14011421

14021422
def _random_value_from_class(

0 commit comments

Comments
 (0)