Skip to content

Commit dcd1db6

Browse files
JulienBortolussiAdaliaiss
authored andcommitted
Fix test_only qualifiers in the name generator.
The 'test_only' qualifiers were not handle correctly by the QualifiersManager.
1 parent 97823d8 commit dcd1db6

File tree

3 files changed

+115
-8
lines changed

3 files changed

+115
-8
lines changed

src/e3/anod/qualifiers_manager.py

Lines changed: 55 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,9 @@ def declare_component(
351351
self.raw_component_decls[name] = required_qualifier_configuration
352352

353353
def __force_default_values(
354-
self, qualifier_dict: dict[str, str]
354+
self,
355+
qualifier_dict: dict[str, str],
356+
ignore_test_only: bool = False,
355357
) -> dict[str, str | bool]:
356358
"""Force the default value of the qualifiers.
357359
@@ -366,6 +368,8 @@ def __force_default_values(
366368
367369
:param qualifier_dict: The dictionary of qualifiers for which the default
368370
values are required.
371+
:param ignore_test_only: If set to True, the qualifier marked as test_only are
372+
completely ignored
369373
"""
370374
if not self.is_declaration_phase_finished:
371375
raise AnodError(
@@ -379,6 +383,10 @@ def __force_default_values(
379383

380384
# Add the required default values
381385
for qualifier_name, qualifier in self.qualifier_decls.items():
386+
# Ignore test_only qualifier if needed
387+
if qualifier["test_only"] and ignore_test_only:
388+
continue
389+
382390
if qualifier["type"] == self.__KEY_VALUE_QUALIFIER:
383391
if qualifier_name not in qualifier_dict:
384392
# The qualifier must have a default. This is checked by
@@ -398,7 +406,9 @@ def __force_default_values(
398406
return qualifier_dict_with_default
399407

400408
def __check_qualifier_consistency(
401-
self, qualifier_configuration: dict[str, str]
409+
self,
410+
qualifier_configuration: dict[str, str],
411+
ignore_test_only: bool = False,
402412
) -> None:
403413
"""Check that the qualifiers are compliant with their declarations.
404414
@@ -409,6 +419,8 @@ def __check_qualifier_consistency(
409419
410420
:param qualifier_configuration: A dictionary of qualifiers to be checked.
411421
The key are the qualifiers names and the values the qualifier values.
422+
:param ignore_test_only: If set to True, the qualifier marked as test_only are
423+
completely ignored
412424
"""
413425
# The declaration phase must be finished to ensure the consistency of the result
414426
if not self.is_declaration_phase_finished:
@@ -427,6 +439,10 @@ def __check_qualifier_consistency(
427439

428440
qualifier = self.qualifier_decls[qualifier_name]
429441

442+
# Ignore the test_only qualifier if needed
443+
if ignore_test_only and qualifier["test_only"]:
444+
continue
445+
430446
# If the qualifier is test_only and the current anod kind is not test,
431447
# raise an error.
432448
if qualifier["test_only"] and self.anod_instance.kind != "test":
@@ -465,6 +481,12 @@ def __check_qualifier_consistency(
465481

466482
# Make sure all the declared qualifiers are stated
467483
for qualifier_name, qualifier in self.qualifier_decls.items():
484+
# Ignore test_only qualifier if needed
485+
if qualifier["test_only"] and (
486+
ignore_test_only or self.anod_instance.kind != "test"
487+
):
488+
continue
489+
468490
if qualifier["type"] == self.__KEY_VALUE_QUALIFIER:
469491
if qualifier_name not in qualifier_configuration:
470492
# The qualifier must have a default otherwise it would not have
@@ -530,12 +552,24 @@ def __end_declaration_phase(self) -> None:
530552
# Add some context informations to the errors raised by
531553
# __check_qualifier_consistency to ease the debugging process.
532554
try:
533-
self.__check_qualifier_consistency(qualifier_dict)
555+
self.__check_qualifier_consistency(
556+
qualifier_dict,
557+
ignore_test_only=True,
558+
)
534559
except AnodError as e:
535560
raise AnodError(f'In component "{component}": {str(e)}') from e
536561

562+
# Make sure no test_only qualifier is used in a component definition
563+
for q in qualifier_dict:
564+
if self.qualifier_decls[q]["test_only"]:
565+
raise AnodError(
566+
f'In component "{component}": The qualifier "{q}" is'
567+
" test_only and cannot be used to define a component"
568+
)
569+
537570
qualifier_dict_with_default_values = self.__force_default_values(
538-
qualifier_dict
571+
qualifier_dict,
572+
ignore_test_only=True,
539573
)
540574

541575
qualifier_configuration = self.__qualifier_config_repr(
@@ -577,7 +611,9 @@ def parse(self, user_qualifiers: dict[str, str]) -> None:
577611
self.__check_qualifier_consistency(user_qualifiers)
578612

579613
# Add the default values
580-
self.qualifier_values = self.__force_default_values(user_qualifiers)
614+
self.qualifier_values = self.__force_default_values(
615+
user_qualifiers, ignore_test_only=self.anod_instance.kind != "test"
616+
)
581617

582618
def __get_parsed_qualifiers(self) -> dict[str, str | bool]:
583619
"""Return the parsed qualifier dictionary.
@@ -619,6 +655,12 @@ def __generate_qualifier_part(
619655
# Assuming that the qualifier has been declared.
620656
# In practice, this is checked by build_space_name before it call this function.
621657
qualifier = self.qualifier_decls[qualifier_name]
658+
659+
# If the qualifier is test_only and the anod kind is not test then the
660+
# qualifier is ignored.
661+
if qualifier["test_only"] and self.anod_instance.kind != "test":
662+
return ""
663+
622664
qualifier_value = parsed_qualifiers[qualifier_name]
623665

624666
# Hold the part of the suffix induced by the qualifier.
@@ -675,10 +717,17 @@ def component(self) -> str | None:
675717
"declaration phase"
676718
)
677719

720+
# Remove the test_only qualifier as they are not used for the component
721+
qualifier_configuration = {
722+
q: v
723+
for q, v in self.__get_parsed_qualifiers().items()
724+
if not self.qualifier_decls[q]["test_only"]
725+
}
726+
678727
# This ensured by __end_declaration_phase
679728
assert self.component_names is not None
680729
return self.component_names.get(
681-
self.__qualifier_config_repr(self.__get_parsed_qualifiers())
730+
self.__qualifier_config_repr(qualifier_configuration)
682731
)
683732

684733
@property

src/e3/anod/spec.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -248,8 +248,6 @@ def __init__(
248248
self.qualifiers_manager = QualifiersManager(self)
249249
self.declare_qualifiers_and_components(self.qualifiers_manager)
250250
self.qualifiers_manager.parse(self.parsed_qualifier)
251-
else:
252-
self.qualifier_manager = None
253251

254252
# UID of the spec instance
255253
self.uid = ".".join(

tests/tests_e3/anod/test_qualifier_manager.py

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -345,6 +345,30 @@ class AnodDummy(Anod):
345345
"The parse method must be called first to generate qualifiers values"
346346
)
347347

348+
# Use a test_only qualifier in a component
349+
class TestInComp(Anod):
350+
enable_name_generator = True
351+
base_name = "dummy"
352+
353+
def declare_qualifiers_and_components(self, qm):
354+
qm.declare_tag_qualifier(
355+
name="foo",
356+
description="foo",
357+
test_only=True,
358+
)
359+
360+
qm.declare_component(
361+
"bar",
362+
{"foo": ""},
363+
)
364+
365+
with pytest.raises(AnodError) as err:
366+
TestInComp(qualifier="", kind="build")
367+
assert str(err.value) == (
368+
'In component "bar": The qualifier "foo" is test_only and cannot be used to '
369+
"define a component"
370+
)
371+
348372

349373
def test_qualifiers_manager():
350374
class Simple(Anod):
@@ -472,6 +496,42 @@ def declare_qualifiers_and_components(self, qualifiers_manager):
472496
'The key-value qualifier "version" must be passed with a value'
473497
)
474498

499+
# test_only qualifier
500+
class AnodTestOnly(Anod):
501+
enable_name_generator = True
502+
base_name = "my_spec"
503+
504+
def declare_qualifiers_and_components(self, qualifiers_manager):
505+
qualifiers_manager.declare_key_value_qualifier(
506+
name="foo",
507+
description="foo",
508+
test_only=True,
509+
)
510+
511+
qualifiers_manager.declare_tag_qualifier(
512+
name="bar",
513+
description="foo",
514+
)
515+
516+
qualifiers_manager.declare_component(
517+
"baz",
518+
{},
519+
)
520+
521+
anod_component_4 = AnodTestOnly(qualifier="", kind="build")
522+
assert anod_component_4.build_space_name == "baz"
523+
assert anod_component_4.component == "baz"
524+
525+
anod_component_5 = AnodTestOnly(qualifier="bar", kind="build")
526+
assert anod_component_5.build_space_name == "my_spec_bar"
527+
assert anod_component_5.component is None
528+
assert anod_component_5.get_qualifier("bar")
529+
530+
anod_component_6 = AnodTestOnly(qualifier="foo=bar", kind="test")
531+
assert anod_component_6.build_space_name == "my_spec_foo-bar_test"
532+
assert anod_component_6.component == "baz"
533+
assert not anod_component_6.get_qualifier("bar")
534+
475535
# Unit test
476536

477537
# Call parse twice

0 commit comments

Comments
 (0)