Skip to content

Commit

Permalink
Merge branch 'mr/qualifier_operators' into 'master'
Browse files Browse the repository at this point in the history
Add support for new operators &, + and - on spec arguments

See merge request it/e3-core!34
  • Loading branch information
Nikokrock committed Aug 19, 2024
2 parents cf5cfb4 + 38f4efe commit 8a841e5
Show file tree
Hide file tree
Showing 3 changed files with 68 additions and 1 deletion.
39 changes: 39 additions & 0 deletions src/e3/anod/qualifier.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from __future__ import annotations
from typing import TYPE_CHECKING

if TYPE_CHECKING:
from typing import Iterable


class Qualifier(dict):

def __sub__(self, other: Iterable[str]) -> Qualifier:
"""Create a new dict qualifier with some keys filtered-out.
Examples:
{"k1": "v1", "k2": "v2"} - {"k2"} == {"k1": "v1"}
{"k1": "v1", "k2": "v2"} - {"k2": "v3"} == {"k1": "v1"}
"""
return Qualifier({k: v for k, v in self.items() if k not in other})

def __add__(self, other: dict | None) -> Qualifier:
"""Create a new dict qualifier that merges two dicts.
The operation is equivalent to pipe operator with the difference that
its priority is higher as defined by Python standard. This allows more
natural expression that mix + and - operators (both operators have the
same priority).
"""
if other is None:
return Qualifier(self)
else:
return Qualifier(self | other)

def __and__(self, other: Iterable[str]) -> Qualifier:
"""Create a new dict qualifier with the subset other of the keys.
Examples:
{"k1": "v1", "k2": "v2"} & {"k2"} == {"k2": "v2"}
{"k1": "v1", "k2": "v2"} & {"k2": "v3"} == {"k2": "v2"}
"""
return Qualifier({k: v for k, v in self.items() if k in other})
3 changes: 2 additions & 1 deletion src/e3/anod/spec.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
from e3.anod.error import AnodError, ShellError
from e3.anod import qualifier_dict_to_str, qualifier_str_to_dict
from e3.anod.qualifiers_manager import QualifiersManager
from e3.anod.qualifier import Qualifier
from e3.fs import find
from e3.os.fs import which
from e3.platform_db.knowledge_base import OS_INFO
Expand Down Expand Up @@ -353,7 +354,7 @@ def declare_qualifiers_and_components(
def args(self) -> dict[str, str | bool | frozenset[str]]:
"""Access to final qualifier values (with defaults set)."""
if self.enable_name_generator:
return self.qualifiers_manager.qualifier_values
return Qualifier(self.qualifiers_manager.qualifier_values)
else:
return self.parsed_qualifier # type: ignore

Expand Down
27 changes: 27 additions & 0 deletions tests/tests_e3/anod/test_qualifier_manager.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
from e3.anod.error import AnodError
from e3.anod.qualifier import Qualifier
from e3.anod.qualifiers_manager import (
QualifiersManager,
KeyValueDeclaration,
Expand All @@ -10,6 +11,32 @@
import pytest


def test_qualifier_operations():
qual1 = Qualifier({"key1": "v1", "key2": "v2"})
qual2 = Qualifier({"key2": "v2.2", "key3": "v3"})
qual3 = Qualifier({"key1": "v1.3", "key4": "v4"})

# Test basic addition of qualifiers
assert qual1 + qual2 == Qualifier({"key1": "v1", "key2": "v2.2", "key3": "v3"})

# Test basic filtering-out of keys
assert qual1 - qual2 == Qualifier({"key1": "v1"})
assert qual1 - {"key2"} == Qualifier({"key1": "v1"})

# Test order/priority of operators
# + and - have the same priority thus are evaluated from left to right
assert qual1 + qual2 - qual3 == Qualifier({"key2": "v2.2", "key3": "v3"})
assert qual1 + (qual2 - qual3) == Qualifier(
{"key1": "v1", "key2": "v2.2", "key3": "v3"}
)

# & has a lower priority than +
assert qual1 + qual2 + qual3 & {"key1", "key2"} == Qualifier(
{"key1": "v1.3", "key2": "v2.2"}
)
assert (qual1 + None) == qual1


# Cover Anod (e3.anod.spec.py)
def test_anod_name_generator():
# Create a dummy spec.
Expand Down

0 comments on commit 8a841e5

Please sign in to comment.