Skip to content

Commit 652fd7e

Browse files
committed
Add support for reference rules
A reference rule has the form ``(Op1, Op2, ..., Opn)`` and is serialized as ``[Op1, Op2, ..., Opn]``. Its name does not matter.
1 parent 302059c commit 652fd7e

File tree

2 files changed

+67
-30
lines changed

2 files changed

+67
-30
lines changed

khiops/core/dictionary.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1581,11 +1581,6 @@ class Rule:
15811581
parenthesized block (...)
15821582
- ``operands`` is empty
15831583
1584-
It is intepreted as a reference rule if and only if:
1585-
1586-
- the first condition above does *not* apply
1587-
- the second condition above applies
1588-
15891584
operands : tuple of operands
15901585
Each operand can have one of the following types:
15911586
@@ -1596,11 +1591,10 @@ class Rule:
15961591
- ``Variable``
15971592
- ``Rule``
15981593
1599-
If no operand is specified, then the rule is:
1600-
1601-
- a standard rule if ``name`` is the verbatim representation of an
1602-
entire rule
1603-
- a reference rule if ``name`` does not satisfy the condition above
1594+
is_reference : bool, default ``False``
1595+
If set to ``True``, then the rule is serialized as a reference rule:
1596+
``Rule(Operand1, Operand2, ...)`` is serialized as
1597+
``[Operand1, Operand2, ...]``.
16041598
16051599
Attributes
16061600
----------
@@ -1615,9 +1609,15 @@ class Rule:
16151609
- float
16161610
- ``Variable``
16171611
- ``Rule``
1612+
1613+
is_reference : bool
1614+
The reference status of the rule.
1615+
1616+
.. note::
1617+
This attribute cannot be changed on a `Rule` instance.
16181618
"""
16191619

1620-
def __init__(self, name, *operands):
1620+
def __init__(self, name, *operands, is_reference=False):
16211621
"""See class docstring"""
16221622
# Check input parameters
16231623
if not is_string_like(name):
@@ -1639,12 +1639,19 @@ def __init__(self, name, *operands):
16391639
"upper-scoped Rule",
16401640
)
16411641
)
1642-
if not name:
1642+
if not isinstance(is_reference, bool):
1643+
raise TypeError(type_error_message("is_reference", is_reference, bool))
1644+
if not is_reference and not name:
16431645
raise ValueError("'name' must be a non-empty string")
16441646

16451647
# Initialize attributes
16461648
self.name = name
16471649
self.operands = operands
1650+
self._is_reference = is_reference
1651+
1652+
@property
1653+
def is_reference(self):
1654+
return self._is_reference
16481655

16491656
def __repr__(self):
16501657
stream = io.BytesIO()
@@ -1673,21 +1680,24 @@ def write(self, writer):
16731680
----------
16741681
writer : `.KhiopsOutputWriter`
16751682
Output writer.
1683+
1684+
.. note::
1685+
If ``self.is_reference`` is set, then ``self.name`` is not included in the serialization.
16761686
"""
16771687
# Check the type of the writer
16781688
if not isinstance(writer, KhiopsOutputWriter):
16791689
raise TypeError(type_error_message("writer", writer, KhiopsOutputWriter))
16801690

16811691
# Write standard rule
1682-
rule_pattern = r"^[A-Z]([a-zA-Z]*)\(.*\)"
1692+
rule_pattern = r"^[A-Z]([a-zA-Z]*)\(?.*\)?$"
16831693
rule_regex = re.compile(rule_pattern)
16841694
bytes_rule_regex = re.compile(bytes(rule_pattern, encoding="ascii"))
16851695
if self.operands:
1686-
if isinstance(self.name, str):
1687-
writer.write(f"{_format_name(self.name)}(")
1696+
if self.is_reference:
1697+
writer.write("[")
16881698
else:
1689-
assert isinstance(self.name, bytes)
1690-
writer.write(f"{_format_name(self.name).decode('ascii')}(")
1699+
writer.write(_format_name(self.name))
1700+
writer.write("(")
16911701

16921702
# Write operand, according to its type
16931703
# Variable operands have their name written only
@@ -1705,7 +1715,10 @@ def write(self, writer):
17051715
writer.write(str(operand))
17061716
if i < len(self.operands) - 1:
17071717
writer.write(", ")
1708-
writer.write(")")
1718+
if self.is_reference:
1719+
writer.write("]")
1720+
else:
1721+
writer.write(")")
17091722
# Write verbatim-given rule
17101723
elif (
17111724
isinstance(self.name, str)
@@ -1714,11 +1727,6 @@ def write(self, writer):
17141727
and bytes_rule_regex.match(self.name)
17151728
):
17161729
writer.write(self.name)
1717-
# Write rule as a reference rule
1718-
else:
1719-
writer.write("[")
1720-
writer.write(self.name)
1721-
writer.write("]")
17221730

17231731

17241732
class MetaData:

tests/test_core.py

Lines changed: 36 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,8 +1978,8 @@ def test_dictionary_accessors(self):
19781978
def test_dictionary_rule_construction(self):
19791979
"""Tests the Rule construction and serialization"""
19801980
rule_verbatims = [
1981-
"SomeRule()",
1982-
b"SomeRule()",
1981+
"SomeRule",
1982+
b"SomeRule",
19831983
'SomeRule("some_operand", 2)',
19841984
b'SomeRule("some_operand", 2)',
19851985
'SomeRule("some""operand", 2)',
@@ -2000,17 +2000,19 @@ def test_dictionary_rule_construction(self):
20002000
'SomeRule("some_operand", 2, SomeEmbeddedRule("some_other_operand", '
20012001
'SomeOtherRule("some_embedded_operand", #Missing, 3)))'
20022002
),
2003-
"[SomeReferenceRule]",
2004-
b"[SomeReferenceRule]",
2003+
'["some_reference_operand"]',
2004+
b'["some_reference_operand"]',
2005+
'["some_reference_operand", SomeReferenceVariable]',
2006+
b'["some_reference_operand", SomeReferenceVariable]',
20052007
(
20062008
b'SomeRule("som\xe9_operand", 2, '
20072009
b'SomeEmbeddedRule("som\xe9_other_operand"))'
20082010
),
20092011
]
20102012

20112013
rules = [
2012-
[kh.Rule("SomeRule()")],
2013-
[kh.Rule(b"SomeRule()")],
2014+
[kh.Rule("SomeRule")],
2015+
[kh.Rule(b"SomeRule")],
20142016
[
20152017
kh.Rule("SomeRule", "some_operand", 2),
20162018
kh.Rule('SomeRule("some_operand", 2)'),
@@ -2156,7 +2158,34 @@ def test_dictionary_rule_construction(self):
21562158
),
21572159
)
21582160
],
2159-
[kh.Rule("SomeReferenceRule")],
2161+
[kh.Rule("", "some_reference_operand", is_reference=True)],
2162+
[kh.Rule(b"", b"some_reference_operand", is_reference=True)],
2163+
[
2164+
kh.Rule(
2165+
"",
2166+
"some_reference_operand",
2167+
kh.Variable(
2168+
json_data={
2169+
"name": "SomeReferenceVariable",
2170+
"type": "Categorical",
2171+
}
2172+
),
2173+
is_reference=True,
2174+
)
2175+
],
2176+
[
2177+
kh.Rule(
2178+
b"",
2179+
b"some_reference_operand",
2180+
kh.Variable(
2181+
json_data={
2182+
"name": b"SomeReferenceVariable",
2183+
"type": "Categorical",
2184+
}
2185+
),
2186+
is_reference=True,
2187+
)
2188+
],
21602189
]
21612190

21622191
for rule_list, rule_verbatim in zip(rules, rule_verbatims):

0 commit comments

Comments
 (0)