Skip to content

Commit

Permalink
feat: Implement dict-like access for OpaqueExpression
Browse files Browse the repository at this point in the history
  • Loading branch information
Wuestengecko committed Dec 20, 2024
1 parent d8ecdde commit 3c95ef0
Show file tree
Hide file tree
Showing 2 changed files with 83 additions and 7 deletions.
80 changes: 76 additions & 4 deletions capellambse/metamodel/information/datavalue.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@
# SPDX-License-Identifier: Apache-2.0
from __future__ import annotations

import collections.abc as cabc
import enum
import types
import typing as t
import warnings

import capellambse.model as m
from capellambse import helpers

from .. import capellacore, modellingcore
from .. import namespaces as ns
Expand Down Expand Up @@ -226,11 +229,80 @@ class UnaryExpression(AbstractExpressionValue):


class OpaqueExpression(
capellacore.CapellaElement, modellingcore.ValueSpecification
capellacore.CapellaElement,
modellingcore.ValueSpecification,
cabc.MutableMapping[str, str],
):
# TODO reimplement specification stuff
bodies = m.StringPOD("bodies")
languages = m.StringPOD("languages")
bodies = m.MultiStringPOD("bodies")
languages = m.MultiStringPOD("languages")

_aliases = types.MappingProxyType({"LinkedText": "capella:linkedText"})
_linked_text = frozenset({"capella:linkedText"})

def __getitem__(self, k: str, /) -> str:
if len(self.bodies) != len(self.languages):
raise TypeError(
"Cannot map: 'languages' and 'bodies' have different sizes"
)

k = self._aliases.get(k, k)
try:
i = self.languages.index(k)
except ValueError:
raise KeyError(k) from None
return self.bodies[i]

def __setitem__(self, k: str, v: str, /) -> None:
if len(self.bodies) != len(self.languages):
raise TypeError(
"Cannot map: 'languages' and 'bodies' have different sizes"
)

k = self._aliases.get(k, k)
if k in self._linked_text:
v = helpers.escape_linked_text(self._model._loader, v)
try:
i = self.languages.index(k)
except ValueError:
self.languages.append(k)
self.bodies.append(v)
else:
self.bodies[i] = v

def __delitem__(self, k: str, /) -> None:
if len(self.bodies) != len(self.languages):
raise TypeError(
"Cannot map: 'languages' and 'bodies' have different sizes"
)

k = self._aliases.get(k, k)
try:
i = self.languages.index(k)
except ValueError:
raise KeyError(k) from None

del self.languages[i]
del self.bodies[i]

def __iter__(self) -> cabc.Iterator[str]:
if len(self.bodies) != len(self.languages):
raise TypeError(
"Cannot map: 'languages' and 'bodies' have different sizes"
)

yield from self.languages

def __len__(self) -> int:
blen = len(self.bodies)
if blen != len(self.languages):
raise TypeError(
"Cannot map: 'languages' and 'bodies' have different sizes"
)

return blen

def __str__(self) -> str:
return next(iter(self.values()))


if t.TYPE_CHECKING:
Expand Down
10 changes: 7 additions & 3 deletions tests/test_decl.py
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ def test_promises_are_resolved_during_the_second_attempt(
) -> None:
PHYS_COMPONENT = "b327d900-abd2-4138-a111-9ff0684739d8"
cmp = model.by_uuid(PHYS_COMPONENT)
assert isinstance(cmp, mm.pa.PhysicalComponent)
previous_ports = len(cmp.ports)
yml = f"""\
- parent: !uuid {PHYS_COMPONENT}
Expand All @@ -318,15 +319,18 @@ def test_promises_are_resolved_during_the_second_attempt(
- parent: !uuid {PHYS_COMPONENT}
extend:
exchanges:
- source: !promise first-port
- _type: FunctionalExchange
source: !promise first-port
target: !promise second-port
promise_id: my_exchange
- parent: !uuid {PHYS_COMPONENT}
extend:
ports:
- name: First port
- _type: PhysicalPort
name: First port
promise_id: first-port
- name: Second port
- _type: PhysicalPort
name: Second port
promise_id: second-port
"""

Expand Down

0 comments on commit 3c95ef0

Please sign in to comment.