zepben.ewb 1.0.0b9__py3-none-any.whl → 1.1.0b1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. zepben/ewb/auth/client/zepben_token_fetcher.py +62 -42
  2. zepben/ewb/database/sqlite/common/base_cim_reader.py +7 -7
  3. zepben/ewb/database/sqlite/common/base_database_writer.py +2 -2
  4. zepben/ewb/database/sqlite/network/network_cim_reader.py +20 -20
  5. zepben/ewb/database/sqlite/network/network_database_reader.py +4 -2
  6. zepben/ewb/database/sqlite/tables/iec61968/common/table_documents.py +5 -5
  7. zepben/ewb/database/sqlite/tables/iec61968/common/table_street_addresses.py +1 -1
  8. zepben/ewb/database/sqlite/tables/iec61968/infiec61968/infassets/table_poles.py +1 -1
  9. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_identified_objects.py +3 -3
  10. zepben/ewb/database/sqlite/tables/iec61970/base/core/table_power_system_resources.py +1 -1
  11. zepben/ewb/database/sqlite/tables/iec61970/base/meas/table_analogs.py +1 -1
  12. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_consumers.py +1 -1
  13. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_energy_sources.py +1 -1
  14. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_regulating_cond_eq.py +1 -1
  15. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_shunt_compensators.py +1 -1
  16. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_tap_changers.py +1 -1
  17. zepben/ewb/database/sqlite/tables/iec61970/base/wires/table_transformer_ends.py +1 -1
  18. zepben/ewb/model/cim/iec61968/common/document.py +5 -5
  19. zepben/ewb/model/cim/iec61968/common/street_address.py +2 -2
  20. zepben/ewb/model/cim/iec61968/common/street_detail.py +8 -7
  21. zepben/ewb/model/cim/iec61968/infiec61968/infassets/pole.py +1 -1
  22. zepben/ewb/model/cim/iec61968/metering/meter.py +4 -2
  23. zepben/ewb/model/cim/iec61968/metering/usage_point.py +1 -1
  24. zepben/ewb/model/cim/iec61970/base/core/curve.py +2 -1
  25. zepben/ewb/model/cim/iec61970/base/core/identified_object.py +8 -3
  26. zepben/ewb/model/cim/iec61970/base/core/name_type.py +2 -2
  27. zepben/ewb/model/cim/iec61970/base/core/power_system_resource.py +2 -2
  28. zepben/ewb/model/cim/iec61970/base/meas/analog.py +3 -1
  29. zepben/ewb/model/cim/iec61970/base/wires/energy_consumer.py +1 -1
  30. zepben/ewb/model/cim/iec61970/base/wires/energy_source.py +1 -1
  31. zepben/ewb/model/cim/iec61970/base/wires/regulating_cond_eq.py +1 -1
  32. zepben/ewb/model/cim/iec61970/base/wires/shunt_compensator.py +1 -1
  33. zepben/ewb/model/cim/iec61970/base/wires/synchronous_machine.py +1 -1
  34. zepben/ewb/model/cim/iec61970/base/wires/tap_changer.py +1 -1
  35. zepben/ewb/model/cim/iec61970/base/wires/transformer_end.py +1 -1
  36. zepben/ewb/model/cim/iec61970/base/wires/transformer_star_impedance.py +4 -4
  37. zepben/ewb/services/common/translator/base_cim2proto.py +21 -9
  38. zepben/ewb/services/common/translator/base_proto2cim.py +13 -8
  39. zepben/ewb/services/customer/translator/customer_cim2proto.py +10 -10
  40. zepben/ewb/services/customer/translator/customer_proto2cim.py +9 -9
  41. zepben/ewb/services/diagram/translator/diagram_cim2proto.py +8 -8
  42. zepben/ewb/services/diagram/translator/diagram_proto2cim.py +8 -8
  43. zepben/ewb/services/network/tracing/phases/phase_inferrer.py +2 -2
  44. zepben/ewb/services/network/translator/network_cim2proto.py +451 -322
  45. zepben/ewb/services/network/translator/network_proto2cim.py +305 -287
  46. {zepben_ewb-1.0.0b9.dist-info → zepben_ewb-1.1.0b1.dist-info}/METADATA +4 -6
  47. {zepben_ewb-1.0.0b9.dist-info → zepben_ewb-1.1.0b1.dist-info}/RECORD +50 -50
  48. {zepben_ewb-1.0.0b9.dist-info → zepben_ewb-1.1.0b1.dist-info}/WHEEL +0 -0
  49. {zepben_ewb-1.0.0b9.dist-info → zepben_ewb-1.1.0b1.dist-info}/licenses/LICENSE +0 -0
  50. {zepben_ewb-1.0.0b9.dist-info → zepben_ewb-1.1.0b1.dist-info}/top_level.txt +0 -0
@@ -76,7 +76,8 @@ class Curve(IdentifiedObject):
76
76
  require(all([it.x_value != x for it in self.data]),
77
77
  lambda: f"Unable to add datapoint to {self}. x_value {x} is invalid, as data with same x_value already exist in this Curve.")
78
78
 
79
- self._data = self._data or []
79
+ if self._data is None:
80
+ self._data = []
80
81
  self._data.append(CurveData(x, y1, y2, y3))
81
82
  self._data.sort(key=lambda it: it.x_value)
82
83
 
@@ -34,14 +34,16 @@ class IdentifiedObject(object, metaclass=ABCMeta):
34
34
  """Master resource identifier issued by a model authority. The mRID is unique within an exchange context.
35
35
  Global uniqueness is easily achieved by using a UUID, as specified in RFC 4122, for the mRID. The use of UUID is strongly recommended."""
36
36
 
37
- name: str = ""
37
+ name: Optional[str] = None
38
38
  """The name is any free human readable and possibly non unique text naming the object."""
39
39
 
40
- description: str = ""
40
+ description: Optional[str] = None
41
41
  """a free human readable text describing or naming the object. It may be non unique and may not correlate to a naming hierarchy."""
42
42
 
43
43
  _names: Optional[List[Name]] = None
44
44
 
45
+ # TODO: Missing num_diagram_objects: int = None def has_diagram_objects(self): return (self.num_diagram_objects or 0) > 0
46
+
45
47
  def __init__(self, names: Optional[List[Name]] = None, **kwargs):
46
48
  super(IdentifiedObject, self).__init__(**kwargs)
47
49
  if names:
@@ -49,7 +51,10 @@ class IdentifiedObject(object, metaclass=ABCMeta):
49
51
  self.add_name(name.type, name.name)
50
52
 
51
53
  def __str__(self):
52
- return f"{self.__class__.__name__}{{{'|'.join(a for a in (str(self.mrid), str(self.name)) if a)}}}"
54
+ class_name = f'{self.__class__.__name__}'
55
+ if self.name:
56
+ return f'{class_name}{{{self.mrid}|{self.name}}}'
57
+ return f'{class_name}{{{self.mrid}}}'
53
58
 
54
59
  @property
55
60
  def names(self) -> Generator[Name, None, None]:
@@ -7,7 +7,7 @@ from __future__ import annotations
7
7
 
8
8
  __all__ = ["NameType"]
9
9
 
10
- from typing import Dict, List, Generator, overload, TYPE_CHECKING, Callable
10
+ from typing import Dict, List, Generator, overload, TYPE_CHECKING, Callable, Optional
11
11
 
12
12
  from zepben.ewb.dataclassy import dataclass
13
13
  from zepben.ewb.model.cim.iec61970.base.core.name import Name
@@ -30,7 +30,7 @@ class NameType:
30
30
  name: str
31
31
  """Name of the name type."""
32
32
 
33
- description: str = ""
33
+ description: Optional[str] = None
34
34
  """Description of the name type."""
35
35
 
36
36
  _names_index: Dict[str, Name] = dict()
@@ -32,7 +32,7 @@ class PowerSystemResource(IdentifiedObject):
32
32
  asset_info: Optional[AssetInfo] = None
33
33
  """A subclass of `zepben.ewb.model.cim.iec61968.assets.asset_info.AssetInfo` providing information about the asset associated with this PowerSystemResource."""
34
34
 
35
- num_controls: int = 0
35
+ num_controls: Optional[int] = None
36
36
  """Number of Control's known to associate with this [PowerSystemResource]"""
37
37
 
38
38
  _assets: Optional[List[Asset]] = None
@@ -48,7 +48,7 @@ class PowerSystemResource(IdentifiedObject):
48
48
  """
49
49
  * :return: True if this [PowerSystemResource] has at least 1 Control associated with it, false otherwise.
50
50
  """
51
- return self.num_controls > 0
51
+ return nlen(self.num_controls) > 0
52
52
 
53
53
  def num_assets(self) -> int:
54
54
  """
@@ -5,12 +5,14 @@
5
5
 
6
6
  __all__ = ["Analog"]
7
7
 
8
+ from typing import Optional
9
+
8
10
  from zepben.ewb.model.cim.iec61970.base.meas.measurement import Measurement
9
11
 
10
12
 
11
13
  class Analog(Measurement):
12
14
  """Analog represents an analog Measurement."""
13
15
 
14
- positive_flow_in: bool = False
16
+ positive_flow_in: Optional[bool] = None
15
17
  """If true then this measurement is an active power, reactive power or current with the convention that a positive value measured at the
16
18
  Terminal means power is flowing into the related PowerSystemResource."""
@@ -26,7 +26,7 @@ class EnergyConsumer(EnergyConnection):
26
26
  customer_count: Optional[int] = None
27
27
  """Number of individual customers represented by this demand."""
28
28
 
29
- grounded: bool = False
29
+ grounded: Optional[bool] = None
30
30
  """Used for Yn and Zn connections. True if the neutral is solidly grounded."""
31
31
 
32
32
  phase_connection: PhaseShuntConnectionKind = PhaseShuntConnectionKind.D
@@ -69,7 +69,7 @@ class EnergySource(EnergyConnection):
69
69
  xn: Optional[float] = None
70
70
  """Negative sequence Thevenin reactance."""
71
71
 
72
- is_external_grid: bool = False
72
+ is_external_grid: Optional[bool] = None
73
73
  """
74
74
  True if this energy source represents the higher-level power grid connection to an external grid
75
75
  that normally is modelled as the slack bus for power flow calculations.
@@ -21,7 +21,7 @@ class RegulatingCondEq(EnergyConnection):
21
21
  de-energized. Note that zero-impedance branches can potentially be modeled by other equipment types.
22
22
  """
23
23
 
24
- control_enabled: bool = True
24
+ control_enabled: Optional[bool] = None
25
25
  """Specifies the regulation status of the equipment. True is regulating, false is not regulating."""
26
26
 
27
27
  _regulating_control: Optional[RegulatingControl] = None
@@ -20,7 +20,7 @@ class ShuntCompensator(RegulatingCondEq):
20
20
  is an individual capacitor or reactor. A negative value for reactivePerSection indicates that the compensator is
21
21
  a reactor. ShuntCompensator is a single terminal device. Ground is implied.
22
22
  """
23
- grounded: bool = False
23
+ grounded: Optional[bool] = None
24
24
  """Used for Yn and Zn connections. True if the neutral is solidly grounded. nom_u : The voltage at which the nominal reactive power may be calculated.
25
25
  This should normally be within 10% of the voltage at which the capacitor is connected to the network."""
26
26
 
@@ -29,7 +29,7 @@ class SynchronousMachine(RotatingMachine):
29
29
  condenser_p: Optional[int] = None
30
30
  """Active power consumed (watts) when in condenser mode operation."""
31
31
 
32
- earthing: bool = False
32
+ earthing: Optional[bool] = None
33
33
  """Indicates whether the generator is earthed. Used for short circuit data exchange according to IEC 60909."""
34
34
 
35
35
  earthing_star_point_r: Optional[float] = None
@@ -19,7 +19,7 @@ class TapChanger(PowerSystemResource):
19
19
  Mechanism for changing transformer winding tap positions.
20
20
  """
21
21
 
22
- control_enabled: bool = True
22
+ control_enabled: Optional[bool] = None
23
23
  """Specifies the regulation status of the equipment. True is regulating, false is not regulating."""
24
24
 
25
25
  neutral_u: Optional[int] = None
@@ -24,7 +24,7 @@ class TransformerEnd(IdentifiedObject):
24
24
  In earlier CIM versions, the TransformerWinding class served a similar purpose, but this class is more flexible
25
25
  because it associates to terminal but is not a specialization of ConductingEquipment.
26
26
  """
27
- grounded: bool = False
27
+ grounded: Optional[bool] = None
28
28
  """(for Yn and Zn connections) True if the neutral is solidly grounded."""
29
29
 
30
30
  r_ground: Optional[float] = None
@@ -21,16 +21,16 @@ class TransformerStarImpedance(IdentifiedObject):
21
21
  For transmission networks use PowerTransformerEnd impedances (r, r0, x, x0, b, b0, g and g0).
22
22
  """
23
23
 
24
- r: Optional[float] = 0.0
24
+ r: Optional[float] = None
25
25
  """ r : Resistance of the transformer end. Unit: Ohms """
26
26
 
27
- r0: Optional[float] = 0.0
27
+ r0: Optional[float] = None
28
28
  """ r0 : Zero sequence series resistance of the transformer end. Unit: Ohms"""
29
29
 
30
- x: Optional[float] = 0.0
30
+ x: Optional[float] = None
31
31
  """ x : Positive sequence series reactance of the transformer end. Unit: Ohms"""
32
32
 
33
- x0: Optional[float] = 0.0
33
+ x0: Optional[float] = None
34
34
  """ x0 : Zero sequence series reactance of the transformer end. Unit: Ohms"""
35
35
 
36
36
  transformer_end_info: Optional['TransformerEndInfo'] = None
@@ -6,10 +6,11 @@
6
6
  __all__ = ["identified_object_to_pb", "document_to_pb", "organisation_role_to_pb", "organisation_to_pb"]
7
7
 
8
8
  import inspect
9
- from typing import ParamSpec, TypeVar, Callable
9
+ from typing import ParamSpec, TypeVar, Callable, Generator
10
10
 
11
11
  # noinspection PyPackageRequirements,PyUnresolvedReferences
12
12
  from google.protobuf.timestamp_pb2 import Timestamp as PBTimestamp
13
+ from google.protobuf.struct_pb2 import NullValue
13
14
  from zepben.protobuf.cim.iec61968.common.Document_pb2 import Document as PBDocument
14
15
  from zepben.protobuf.cim.iec61968.common.OrganisationRole_pb2 import OrganisationRole as PBOrganisationRole
15
16
  from zepben.protobuf.cim.iec61968.common.Organisation_pb2 import Organisation as PBOrganisation
@@ -38,6 +39,11 @@ def bind_to_pb(func: Callable[P, R]) -> Callable[P, R]:
38
39
  inspect.get_annotations(func, eval_str=True)[func.__code__.co_varnames[0]].to_pb = func
39
40
  return func
40
41
 
42
+
43
+ def set_or_null(**kwargs):
44
+ return {f'{k}{"Null" if v is None else "Set"}': v if v is not None else NullValue.NULL_VALUE for k, v in kwargs.items()}
45
+
46
+
41
47
  ###################
42
48
  # IEC61968 Common #
43
49
  ###################
@@ -51,12 +57,14 @@ def document_to_pb(cim: Document) -> PBDocument:
51
57
 
52
58
  return PBDocument(
53
59
  io=identified_object_to_pb(cim),
54
- title=cim.title,
55
60
  createdDateTime=timestamp,
56
- authorName=cim.author_name,
57
- type=cim.type,
58
- status=cim.status,
59
- comment=cim.comment
61
+ **set_or_null(
62
+ title=cim.title,
63
+ authorName=cim.author_name,
64
+ type=cim.type,
65
+ status=cim.status,
66
+ comment=cim.comment
67
+ )
60
68
  )
61
69
 
62
70
 
@@ -81,8 +89,10 @@ def organisation_role_to_pb(cim: OrganisationRole) -> PBOrganisationRole:
81
89
  def identified_object_to_pb(cim: IdentifiedObject) -> PBIdentifiedObject:
82
90
  return PBIdentifiedObject(
83
91
  mRID=str(cim.mrid),
84
- name=cim.name,
85
- description=cim.description,
92
+ **set_or_null(
93
+ name=cim.name,
94
+ description=cim.description
95
+ ),
86
96
  names=[name_to_pb(name) for name in cim.names]
87
97
  )
88
98
 
@@ -99,5 +109,7 @@ def name_to_pb(cim: Name) -> PBName:
99
109
  def name_type_to_pb(cim: NameType) -> PBNameType:
100
110
  return PBNameType(
101
111
  name=cim.name,
102
- description=cim.description
112
+ **set_or_null(
113
+ description=cim.description
114
+ )
103
115
  )
@@ -54,6 +54,11 @@ def bind_to_cim(func: Callable[P, R]) -> Callable[P, R]:
54
54
  inspect.get_annotations(func, eval_str=True)[func.__code__.co_varnames[0]].to_cim = func
55
55
  return func
56
56
 
57
+ T = TypeVar("T")
58
+
59
+ def get_nullable(pb: Message, field: str) -> Optional[T]:
60
+ return getattr(pb, f'{field}Set') if pb.HasField(f'{field}Set') else None
61
+
57
62
 
58
63
  ###################
59
64
  # IEC61968 Common #
@@ -61,12 +66,12 @@ def bind_to_cim(func: Callable[P, R]) -> Callable[P, R]:
61
66
 
62
67
  @bind_to_cim
63
68
  def document_to_cim(pb: PBDocument, cim: Document, service: BaseService):
64
- cim.title = pb.title
69
+ cim.title = get_nullable(pb, 'title')
65
70
  cim.created_date_time = pb.createdDateTime.ToDatetime() if pb.HasField("createdDateTime") else None
66
- cim.author_name = pb.authorName
67
- cim.type = pb.type
68
- cim.status = pb.status
69
- cim.comment = pb.comment
71
+ cim.author_name = get_nullable(pb, 'authorName')
72
+ cim.type = get_nullable(pb, 'type')
73
+ cim.status = get_nullable(pb, 'status')
74
+ cim.comment = get_nullable(pb, 'comment')
70
75
 
71
76
  identified_object_to_cim(pb.io, cim, service)
72
77
 
@@ -94,8 +99,8 @@ def organisation_role_to_cim(pb: PBOrganisationRole, cim: OrganisationRole, serv
94
99
  @bind_to_cim
95
100
  def identified_object_to_cim(pb: PBIdentifiedObject, cim: IdentifiedObject, service: BaseService):
96
101
  cim.mrid = pb.mRID
97
- cim.name = pb.name
98
- cim.description = pb.description
102
+ cim.name = get_nullable(pb, 'name')
103
+ cim.description = get_nullable(pb, 'description')
99
104
  [cim.add_name(name_to_cim(name, cim, service).type, name.name) for name in pb.names]
100
105
 
101
106
 
@@ -120,7 +125,7 @@ def name_type_to_cim(pb: PBNameType, service: BaseService):
120
125
  nt = NameType(pb.name)
121
126
  service.add_name_type(nt)
122
127
 
123
- nt.description = pb.description
128
+ nt.description = get_nullable(pb, 'description')
124
129
  return nt
125
130
 
126
131
 
@@ -16,7 +16,7 @@ from zepben.ewb.model.cim.iec61968.customers.customer import Customer
16
16
  from zepben.ewb.model.cim.iec61968.customers.customer_agreement import CustomerAgreement
17
17
  from zepben.ewb.model.cim.iec61968.customers.pricing_structure import PricingStructure
18
18
  from zepben.ewb.model.cim.iec61968.customers.tariff import Tariff
19
- from zepben.ewb.services.common.translator.base_cim2proto import document_to_pb, organisation_role_to_pb
19
+ from zepben.ewb.services.common.translator.base_cim2proto import document_to_pb, organisation_role_to_pb, set_or_null, bind_to_pb
20
20
  from zepben.ewb.services.common.translator.util import mrid_or_empty
21
21
  # noinspection PyProtectedMember
22
22
  from zepben.ewb.services.customer.translator.customer_enum_mappers import _map_customer_kind
@@ -26,6 +26,7 @@ from zepben.ewb.services.customer.translator.customer_enum_mappers import _map_c
26
26
  # IEC61968 Common #
27
27
  ###################
28
28
 
29
+ @bind_to_pb
29
30
  def agreement_to_pb(cim: Agreement) -> PBAgreement:
30
31
  return PBAgreement(doc=document_to_pb(cim))
31
32
 
@@ -34,17 +35,21 @@ def agreement_to_pb(cim: Agreement) -> PBAgreement:
34
35
  # IEC61968 Customers #
35
36
  ######################
36
37
 
38
+ @bind_to_pb
37
39
  def customer_to_pb(cim: Customer) -> PBCustomer:
38
40
  customer = PBCustomer(
39
41
  kind=_map_customer_kind.to_pb(cim.kind),
40
- specialNeed=cim.special_need,
41
- customerAgreementMRIDs=[str(io.mrid) for io in cim.agreements]
42
+ customerAgreementMRIDs=[str(io.mrid) for io in cim.agreements],
43
+ **set_or_null(
44
+ specialNeed=cim.special_need,
45
+ )
42
46
  )
43
47
 
44
48
  getattr(customer, 'or').CopyFrom(organisation_role_to_pb(cim))
45
49
  return customer
46
50
 
47
51
 
52
+ @bind_to_pb
48
53
  def customer_agreement_to_pb(cim: CustomerAgreement) -> PBCustomerAgreement:
49
54
  return PBCustomerAgreement(
50
55
  agr=agreement_to_pb(cim),
@@ -53,6 +58,7 @@ def customer_agreement_to_pb(cim: CustomerAgreement) -> PBCustomerAgreement:
53
58
  )
54
59
 
55
60
 
61
+ @bind_to_pb
56
62
  def pricing_structure_to_pb(cim: PricingStructure) -> PBPricingStructure:
57
63
  return PBPricingStructure(
58
64
  doc=document_to_pb(cim),
@@ -60,12 +66,6 @@ def pricing_structure_to_pb(cim: PricingStructure) -> PBPricingStructure:
60
66
  )
61
67
 
62
68
 
69
+ @bind_to_pb
63
70
  def tariff_to_pb(cim: Tariff) -> PBTariff:
64
71
  return PBTariff(doc=document_to_pb(cim))
65
-
66
-
67
- Agreement.to_pb = agreement_to_pb
68
- Customer.to_pb = customer_to_pb
69
- CustomerAgreement.to_pb = customer_agreement_to_pb
70
- PricingStructure.to_pb = pricing_structure_to_pb
71
- Tariff.to_pb = tariff_to_pb
@@ -16,12 +16,13 @@ from zepben.protobuf.cim.iec61968.customers.PricingStructure_pb2 import PricingS
16
16
  from zepben.protobuf.cim.iec61968.customers.Tariff_pb2 import Tariff as PBTariff
17
17
 
18
18
  import zepben.ewb.services.common.resolver as resolver
19
- from zepben.ewb import organisation_role_to_cim, document_to_cim, BaseService, CustomerKind
19
+ from zepben.ewb import organisation_role_to_cim, document_to_cim, BaseService, CustomerKind, bind_to_cim
20
20
  from zepben.ewb.model.cim.iec61968.common.agreement import Agreement
21
21
  from zepben.ewb.model.cim.iec61968.customers.customer import Customer
22
22
  from zepben.ewb.model.cim.iec61968.customers.customer_agreement import CustomerAgreement
23
23
  from zepben.ewb.model.cim.iec61968.customers.pricing_structure import PricingStructure
24
24
  from zepben.ewb.model.cim.iec61968.customers.tariff import Tariff
25
+ from zepben.ewb.services.common.translator.base_proto2cim import get_nullable
25
26
  from zepben.ewb.services.customer.customers import CustomerService
26
27
 
27
28
 
@@ -29,6 +30,7 @@ from zepben.ewb.services.customer.customers import CustomerService
29
30
  # IEC61968 Common #
30
31
  ###################
31
32
 
33
+ @bind_to_cim
32
34
  def agreement_to_cim(pb: PBAgreement, cim: Agreement, service: BaseService):
33
35
  document_to_cim(pb.doc, cim, service)
34
36
 
@@ -37,11 +39,13 @@ def agreement_to_cim(pb: PBAgreement, cim: Agreement, service: BaseService):
37
39
  # IEC61968 Customers #
38
40
  ######################
39
41
 
42
+ @bind_to_cim
40
43
  def customer_to_cim(pb: PBCustomer, service: CustomerService) -> Optional[Customer]:
41
44
  cim = Customer(
42
45
  mrid=pb.mrid(),
43
46
  kind=CustomerKind(pb.kind),
44
- special_need=pb.specialNeed if pb.specialNeed else None
47
+ # TODO: missing num_end_devices from jvm sdk
48
+ special_need=get_nullable(pb, 'specialNeed')
45
49
  )
46
50
 
47
51
  for mrid in pb.customerAgreementMRIDs:
@@ -51,6 +55,7 @@ def customer_to_cim(pb: PBCustomer, service: CustomerService) -> Optional[Custom
51
55
  return cim if service.add(cim) else None
52
56
 
53
57
 
58
+ @bind_to_cim
54
59
  def customer_agreement_to_cim(pb: PBCustomerAgreement, service: CustomerService) -> Optional[CustomerAgreement]:
55
60
  cim = CustomerAgreement(mrid=pb.mrid())
56
61
 
@@ -62,6 +67,7 @@ def customer_agreement_to_cim(pb: PBCustomerAgreement, service: CustomerService)
62
67
  return cim if service.add(cim) else None
63
68
 
64
69
 
70
+ @bind_to_cim
65
71
  def pricing_structure_to_cim(pb: PBPricingStructure, service: CustomerService) -> Optional[PricingStructure]:
66
72
  cim = PricingStructure(mrid=pb.mrid())
67
73
 
@@ -72,16 +78,10 @@ def pricing_structure_to_cim(pb: PBPricingStructure, service: CustomerService) -
72
78
  return cim if service.add(cim) else None
73
79
 
74
80
 
81
+ @bind_to_cim
75
82
  def tariff_to_cim(pb: PBTariff, service: CustomerService) -> Optional[Tariff]:
76
83
  # noinspection PyArgumentList
77
84
  cim = Tariff(mrid=pb.mrid())
78
85
 
79
86
  document_to_cim(pb.doc, cim, service)
80
87
  return cim if service.add(cim) else None
81
-
82
-
83
- PBAgreement.to_cim = agreement_to_cim
84
- PBCustomer.to_cim = customer_to_cim
85
- PBCustomerAgreement.to_cim = customer_agreement_to_cim
86
- PBPricingStructure.to_cim = pricing_structure_to_cim
87
- PBTariff.to_cim = tariff_to_cim
@@ -12,7 +12,7 @@ from zepben.protobuf.cim.iec61970.base.diagramlayout.Diagram_pb2 import Diagram
12
12
  from zepben.ewb.model.cim.iec61970.base.diagramlayout.diagram import Diagram
13
13
  from zepben.ewb.model.cim.iec61970.base.diagramlayout.diagram_object import DiagramObject
14
14
  from zepben.ewb.model.cim.iec61970.base.diagramlayout.diagram_object_point import DiagramObjectPoint
15
- from zepben.ewb.services.common.translator.base_cim2proto import identified_object_to_pb
15
+ from zepben.ewb.services.common.translator.base_cim2proto import identified_object_to_pb, set_or_null, bind_to_pb
16
16
  from zepben.ewb.services.common.translator.util import mrid_or_empty
17
17
  # noinspection PyProtectedMember
18
18
  from zepben.ewb.services.diagram.translator.diagram_enum_mappers import _map_diagram_style, _map_orientation_kind
@@ -22,6 +22,7 @@ from zepben.ewb.services.diagram.translator.diagram_enum_mappers import _map_dia
22
22
  # IEC61970 Base Diagram Layout #
23
23
  ################################
24
24
 
25
+ @bind_to_pb
25
26
  def diagram_to_pb(cim: Diagram) -> PBDiagram:
26
27
  return PBDiagram(
27
28
  io=identified_object_to_pb(cim),
@@ -31,21 +32,20 @@ def diagram_to_pb(cim: Diagram) -> PBDiagram:
31
32
  )
32
33
 
33
34
 
35
+ @bind_to_pb
34
36
  def diagram_object_to_pb(cim: DiagramObject) -> PBDiagramObject:
35
37
  return PBDiagramObject(
36
38
  io=identified_object_to_pb(cim),
37
39
  diagramMRID=mrid_or_empty(cim.diagram),
38
40
  identifiedObjectMRID=cim.identified_object_mrid,
39
- diagramObjectStyle=cim.style,
41
+ diagramObjectPoints=[diagram_object_point_to_pb(io) for io in cim.points],
40
42
  rotation=cim.rotation,
41
- diagramObjectPoints=[diagram_object_point_to_pb(io) for io in cim.points]
43
+ **set_or_null(
44
+ diagramObjectStyle=cim.style,
45
+ )
42
46
  )
43
47
 
44
48
 
49
+ @bind_to_pb
45
50
  def diagram_object_point_to_pb(cim: DiagramObjectPoint) -> PBDiagramObjectPoint:
46
51
  return PBDiagramObjectPoint(xPosition=cim.x_position, yPosition=cim.y_position)
47
-
48
-
49
- Diagram.to_pb = diagram_to_pb
50
- DiagramObject.to_pb = diagram_object_to_pb
51
- DiagramObjectPoint.to_pb = diagram_object_point_to_pb
@@ -10,10 +10,11 @@ from zepben.protobuf.cim.iec61970.base.diagramlayout.DiagramObject_pb2 import Di
10
10
  from zepben.protobuf.cim.iec61970.base.diagramlayout.Diagram_pb2 import Diagram as PBDiagram
11
11
 
12
12
  import zepben.ewb.services.common.resolver as resolver
13
- from zepben.ewb import identified_object_to_cim, OrientationKind, DiagramStyle
13
+ from zepben.ewb import identified_object_to_cim, OrientationKind, DiagramStyle, add_to_network_or_none, bind_to_cim
14
14
  from zepben.ewb.model.cim.iec61970.base.diagramlayout.diagram import Diagram
15
15
  from zepben.ewb.model.cim.iec61970.base.diagramlayout.diagram_object import DiagramObject
16
16
  from zepben.ewb.model.cim.iec61970.base.diagramlayout.diagram_object_point import DiagramObjectPoint
17
+ from zepben.ewb.services.common.translator.base_proto2cim import get_nullable
17
18
  from zepben.ewb.services.diagram.diagrams import DiagramService
18
19
 
19
20
 
@@ -21,6 +22,8 @@ from zepben.ewb.services.diagram.diagrams import DiagramService
21
22
  # IEC61970 Base Diagram Layout #
22
23
  ################################
23
24
 
25
+ @bind_to_cim
26
+ @add_to_network_or_none
24
27
  def diagram_to_cim(pb: PBDiagram, service: DiagramService):
25
28
  cim = Diagram(
26
29
  mrid=pb.mrid(),
@@ -32,14 +35,15 @@ def diagram_to_cim(pb: PBDiagram, service: DiagramService):
32
35
  service.resolve_or_defer_reference(resolver.diagram_objects(cim), mrid)
33
36
 
34
37
  identified_object_to_cim(pb.io, cim, service)
35
- return cim if service.add(cim) else None
38
+ return cim
36
39
 
37
40
 
41
+ @bind_to_cim
38
42
  def diagram_object_to_cim(pb: PBDiagramObject, service: DiagramService):
39
43
  cim = DiagramObject(
40
44
  mrid=pb.mrid(),
41
45
  identified_object_mrid=pb.identifiedObjectMRID if pb.identifiedObjectMRID else None,
42
- style=pb.diagramObjectStyle if pb.diagramObjectStyle else None,
46
+ style=get_nullable(pb, 'diagramObjectStyle'),
43
47
  rotation=pb.rotation,
44
48
  )
45
49
 
@@ -51,11 +55,7 @@ def diagram_object_to_cim(pb: PBDiagramObject, service: DiagramService):
51
55
  return cim if service.add_diagram_object(cim) else None
52
56
 
53
57
 
58
+ @bind_to_cim
54
59
  def diagram_object_point_to_cim(pb: PBDiagramObjectPoint) -> DiagramObjectPoint:
55
60
  # noinspection PyArgumentList
56
61
  return DiagramObjectPoint(pb.xPosition, pb.yPosition)
57
-
58
-
59
- PBDiagram.to_cim = diagram_to_cim
60
- PBDiagramObject.to_cim = diagram_object_to_cim
61
- PBDiagramObjectPoint.to_cim = diagram_object_point_to_cim
@@ -36,9 +36,9 @@ class PhaseInferrer:
36
36
  @property
37
37
  def description(self) -> str:
38
38
  if self.suspect:
39
- _inner_desc = f"phases for '{self.conducting_equipment.name}' [{self.conducting_equipment.mrid}] which may not be correct. The phases were inferred"
39
+ _inner_desc = f"phases for '{str(self.conducting_equipment)}' which may not be correct. The phases were inferred"
40
40
  else:
41
- _inner_desc = f"phase for '{self.conducting_equipment.name}' [{self.conducting_equipment.mrid}] which should be correct. The phase was inferred"
41
+ _inner_desc = f"phase for '{str(self.conducting_equipment)}' which should be correct. The phase was inferred"
42
42
  return (f'Inferred missing {_inner_desc} due to a disconnected nominal phase because of an '
43
43
  f'upstream error in the source data. Phasing information for the upstream equipment should be fixed in the source system.')
44
44