Skip to content

Commit 979b38a

Browse files
author
Thierry RAMORASOAVINA
committed
Accept a more specific variable rule in Dictionary.add_variable_from_spec instead of a verbatim string
1 parent 8497304 commit 979b38a

5 files changed

Lines changed: 51 additions & 21 deletions

File tree

doc/samples/samples.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -93,6 +93,12 @@ Samples
9393
third_dictionary.add_variable_from_spec(name="StreetNumber", type="Numerical")
9494
third_dictionary.add_variable_from_spec(name="StreetName", type="Categorical")
9595
third_dictionary.add_variable_from_spec(name="id_city", type="Categorical")
96+
# Add a variable with a rule
97+
third_dictionary.add_variable_from_spec(
98+
name="computed",
99+
type="Numerical",
100+
rule=kh.Rule("Ceil", kh.Rule("Product", 3, kh.Rule("Random()"))),
101+
)
96102
97103
# Add the variables used in a multi-table context in the first dictionary.
98104
# They link the root dictionary to the additional ones

khiops/core/dictionary.py

Lines changed: 17 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -86,17 +86,17 @@ def _check_name(name):
8686
The Khiops core forbids a name
8787
- with a length outside the [1,128] interval
8888
- containing a simple (Unix) carriage-return (\n)
89-
- with leading and trailing spaces
89+
- with leading and trailing spaces.
9090
This function must check at least these constraints.
9191
9292
Parameters
9393
----------
9494
name : str
95-
Name to be validated
95+
Name to be validated.
9696
Raises
9797
------
9898
`ValueError`
99-
If the provided name does not comply with the formatting constraints
99+
If the provided name does not comply with the formatting constraints.
100100
"""
101101
# Check that the type of name is string or bytes
102102
if not is_string_like(name):
@@ -108,7 +108,7 @@ def _check_name(name):
108108
else:
109109
assert isinstance(name, bytes)
110110
contains_carriage_return = b"\n" in name
111-
if not len(name) <= 128 or contains_carriage_return or name != name.strip():
111+
if len(name) > 128 or contains_carriage_return or name != name.strip():
112112
raise ValueError(
113113
f"Variable name '{name}' cannot be accepted "
114114
"(invalid length or characters)"
@@ -846,19 +846,19 @@ def add_variable_from_spec(
846846
Parameters
847847
----------
848848
name : str
849-
Variable name
849+
Variable name.
850850
type : str
851-
Variable type, See `Variable`
851+
Variable type, See `Variable`.
852852
label : str, default ""
853853
Label of the variable.
854854
used : bool, default ``True``
855855
Usage status of the variable.
856856
object_type : str, optional
857-
Object type. Ignored if variable type not in ["Entity", "Table"]
857+
Object type. Ignored if variable type not in ["Entity", "Table"].
858858
structure_type : str, optional
859-
Structure type. Ignored if variable type is not "Structure"
860-
rule : str, optional
861-
Variable rule (in verbatim).
859+
Structure type. Ignored if variable type is not "Structure".
860+
rule : `Rule`, optional
861+
Variable rule.
862862
meta_data : dict, optional
863863
A Python dictionary which holds the metadata specification.
864864
The dictionary keys are str. The values can be str, bool, float or int.
@@ -870,8 +870,8 @@ def add_variable_from_spec(
870870
with the formatting constraints.
871871
- If there is already a variable with the same name.
872872
- If the given variable type is unknown.
873-
- If a native type is given 'object_type' or 'structure_type'
874-
- If the 'meta_data' is not a dictionary
873+
- If a native type is given 'object_type' or 'structure_type'.
874+
- If the 'meta_data' is not a dictionary.
875875
"""
876876
# Values and Types checks
877877
if not name:
@@ -890,12 +890,11 @@ def add_variable_from_spec(
890890
)
891891
if _is_object_type(type) and object_type is None:
892892
raise ValueError(f"'object_type' must be provided for type '{type}'")
893+
if type == "Structure" and structure_type is None:
894+
raise ValueError(f"'structure_type' must be provided for type '{type}'")
893895
if meta_data is not None:
894896
if not is_dict_like(meta_data):
895897
raise TypeError(type_error_message("meta_data", meta_data, "dict-like"))
896-
if label is not None:
897-
if not is_string_like(label):
898-
raise TypeError(type_error_message("label", label, "string-like"))
899898
if object_type is not None:
900899
if not is_string_like(object_type):
901900
raise TypeError(
@@ -907,8 +906,8 @@ def add_variable_from_spec(
907906
type_error_message("structure_type", structure_type, "string-like")
908907
)
909908
if rule is not None:
910-
if not is_string_like(rule):
911-
raise TypeError(type_error_message("rule", rule, "string-like"))
909+
if not isinstance(rule, Rule):
910+
raise TypeError(type_error_message("rule", rule, Rule))
912911

913912
# Variable initialization
914913
variable = Variable()
@@ -924,7 +923,7 @@ def add_variable_from_spec(
924923
if structure_type is not None:
925924
variable.structure_type = structure_type
926925
if rule is not None:
927-
variable.rule = Rule(verbatim=rule)
926+
variable.set_rule(rule)
928927
self.add_variable(variable)
929928

930929
def remove_variable(self, variable_name):

khiops/samples/samples.ipynb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -105,6 +105,12 @@
105105
"third_dictionary.add_variable_from_spec(name=\"StreetNumber\", type=\"Numerical\")\n",
106106
"third_dictionary.add_variable_from_spec(name=\"StreetName\", type=\"Categorical\")\n",
107107
"third_dictionary.add_variable_from_spec(name=\"id_city\", type=\"Categorical\")\n",
108+
"# Add a variable with a rule\n",
109+
"third_dictionary.add_variable_from_spec(\n",
110+
" name=\"computed\",\n",
111+
" type=\"Numerical\",\n",
112+
" rule=kh.Rule(\"Ceil\", kh.Rule(\"Product\", 3, kh.Rule(\"Random()\"))),\n",
113+
")\n",
108114
"\n",
109115
"# Add the variables used in a multi-table context in the first dictionary.\n",
110116
"# They link the root dictionary to the additional ones\n",

khiops/samples/samples.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,12 @@ def create_dictionary_domain():
107107
third_dictionary.add_variable_from_spec(name="StreetNumber", type="Numerical")
108108
third_dictionary.add_variable_from_spec(name="StreetName", type="Categorical")
109109
third_dictionary.add_variable_from_spec(name="id_city", type="Categorical")
110+
# Add a variable with a rule
111+
third_dictionary.add_variable_from_spec(
112+
name="computed",
113+
type="Numerical",
114+
rule=kh.Rule("Ceil", kh.Rule("Product", 3, kh.Rule("Random()"))),
115+
)
110116

111117
# Add the variables used in a multi-table context in the first dictionary.
112118
# They link the root dictionary to the additional ones

tests/test_core.py

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1882,8 +1882,15 @@ def test_dictionary_accessors(self):
18821882
dictionary.add_variable_from_spec(
18831883
name="fresh_one", type="Entity", object_type={}
18841884
)
1885-
# rule must be a str
1886-
with self.assertRaisesRegex(TypeError, "'rule'.*string-like"):
1885+
# a structure type must have a structure_type parameter
1886+
with self.assertRaisesRegex(
1887+
ValueError, "'structure_type' must be provided"
1888+
):
1889+
dictionary.add_variable_from_spec(
1890+
name="fresh_one", type="Structure"
1891+
)
1892+
# rule must be Rule object
1893+
with self.assertRaisesRegex(TypeError, "'rule'.*Rule"):
18871894
dictionary.add_variable_from_spec(
18881895
name="fresh_one", type="Categorical", rule={}
18891896
)
@@ -1892,17 +1899,23 @@ def test_dictionary_accessors(self):
18921899
dictionary.add_variable_from_spec(
18931900
name="fresh_one", type="Categorical", meta_data="str"
18941901
)
1895-
# successful adding (with meta-data)
1902+
# successful adding (with meta-data and rule)
18961903
dictionary.add_variable_from_spec(
18971904
name="fresh_one",
18981905
type="Categorical",
18991906
meta_data={"a": 1, "b": 2},
1907+
rule=kh.Rule("Ceil", kh.Rule("Product", 3, kh.Rule("Random()"))),
19001908
)
19011909
self.assertEqual(
19021910
2,
19031911
dictionary.get_variable("fresh_one").get_value("b"),
19041912
"Variable meta-data must be set correctly",
19051913
)
1914+
self.assertEqual(
1915+
"Ceil(Product(3, Random()))",
1916+
repr(dictionary.get_variable("fresh_one").get_rule()),
1917+
"Variable rule must be set correctly",
1918+
)
19061919

19071920
# Test Dictionary variable block accessors
19081921
# Create a simple block

0 commit comments

Comments
 (0)