MCPcopy Create free account
hub / github.com/IfcOpenShell/IfcOpenShell / coerce_value

Function coerce_value

src/ifcedit/ifcedit/coerce.py:28–119  ·  view source on GitHub ↗

Convert a CLI string argument to the proper Python type based on a type hint. Args: value_str: The raw string from the CLI. type_hint: The type annotation from the function signature. model: The main open IFC model, needed to resolve entity instance references by ID.

(
    value_str: str,
    type_hint,
    model: ifcopenshell.file | None = None,
    lookup_file: ifcopenshell.file | None = None,
)

Source from the content-addressed store, hash-verified

26
27
28def coerce_value(
29 value_str: str,
30 type_hint,
31 model: ifcopenshell.file | None = None,
32 lookup_file: ifcopenshell.file | None = None,
33):
34 """Convert a CLI string argument to the proper Python type based on a type hint.
35
36 Args:
37 value_str: The raw string from the CLI.
38 type_hint: The type annotation from the function signature.
39 model: The main open IFC model, needed to resolve entity instance references by ID.
40 lookup_file: Override file for entity resolution (e.g. a library file for
41 project.append_asset). When provided, entity IDs are looked up here instead
42 of in model.
43
44 Returns:
45 The converted Python value.
46
47 Raises:
48 ValueError: If the value cannot be converted.
49 TypeError: If the type hint is not supported.
50 """
51 # When a library file has been opened, entity IDs are resolved from it, not the main model.
52 effective_lookup = lookup_file if lookup_file is not None else model
53
54 if type_hint is None:
55 return value_str
56
57 origin = typing.get_origin(type_hint)
58 args = typing.get_args(type_hint)
59
60 # Union / Optional
61 if origin is typing.Union:
62 non_none_types = [a for a in args if a is not type(None)]
63 if value_str.lower() == "none":
64 if type(None) in args:
65 return None
66 # Try each non-None type in order
67 for t in non_none_types:
68 try:
69 return coerce_value(value_str, t, model, lookup_file)
70 except (ValueError, TypeError):
71 continue
72 raise ValueError(f"Cannot convert '{value_str}' to any of {non_none_types}")
73
74 # Literal
75 if origin is typing.Literal:
76 allowed = args
77 if value_str in [str(a) for a in allowed]:
78 # return the actual literal value with proper type
79 for a in allowed:
80 if str(a) == value_str:
81 return a
82 raise ValueError(f"'{value_str}' is not one of: {', '.join(repr(a) for a in allowed)}")
83
84 # list types
85 if origin is list:

Callers 15

test_plain_stringMethod · 0.90
test_empty_stringMethod · 0.90
test_plain_intMethod · 0.90
test_hash_prefixMethod · 0.90
test_negativeMethod · 0.90
test_plain_floatMethod · 0.90
test_integer_as_floatMethod · 0.90
test_true_valuesMethod · 0.90
test_false_valuesMethod · 0.90
test_optional_stringMethod · 0.90
test_optional_noneMethod · 0.90
test_optional_intMethod · 0.90

Calls 9

_is_entity_typeFunction · 0.85
_coerce_entity_listFunction · 0.85
_split_listFunction · 0.85
_floatify_numeric_listsFunction · 0.85
_coerce_entityFunction · 0.85
lowerMethod · 0.80
openMethod · 0.80
typeFunction · 0.50
joinMethod · 0.45

Tested by 15

test_plain_stringMethod · 0.72
test_empty_stringMethod · 0.72
test_plain_intMethod · 0.72
test_hash_prefixMethod · 0.72
test_negativeMethod · 0.72
test_plain_floatMethod · 0.72
test_integer_as_floatMethod · 0.72
test_true_valuesMethod · 0.72
test_false_valuesMethod · 0.72
test_optional_stringMethod · 0.72
test_optional_noneMethod · 0.72
test_optional_intMethod · 0.72