zepben.ewb 1.0.4b1__py3-none-any.whl → 1.1.0__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.
- zepben/ewb/__init__.py +1 -0
- zepben/ewb/database/paths/ewb_data_file_paths.py +122 -167
- zepben/ewb/database/paths/local_ewb_data_file_paths.py +58 -0
- zepben/ewb/database/sqlite/common/base_database_reader.py +7 -3
- zepben/ewb/model/cim/iec61968/metering/controlled_appliance.py +2 -0
- zepben/ewb/model/cim/iec61970/base/core/identified_object.py +5 -2
- zepben/ewb/model/cim/iec61970/base/wires/regulating_cond_eq.py +2 -1
- zepben/ewb/services/common/difference.py +2 -2
- zepben/ewb/services/common/translator/base_proto2cim.py +1 -1
- zepben/ewb/services/network/network_extensions.py +5 -5
- zepben/ewb/util.py +3 -9
- {zepben_ewb-1.0.4b1.dist-info → zepben_ewb-1.1.0.dist-info}/METADATA +11 -10
- {zepben_ewb-1.0.4b1.dist-info → zepben_ewb-1.1.0.dist-info}/RECORD +16 -15
- {zepben_ewb-1.0.4b1.dist-info → zepben_ewb-1.1.0.dist-info}/WHEEL +0 -0
- {zepben_ewb-1.0.4b1.dist-info → zepben_ewb-1.1.0.dist-info}/licenses/LICENSE +0 -0
- {zepben_ewb-1.0.4b1.dist-info → zepben_ewb-1.1.0.dist-info}/top_level.txt +0 -0
zepben/ewb/__init__.py
CHANGED
|
@@ -352,6 +352,7 @@ from zepben.ewb.services.diagram.diagram_service_comparator import DiagramServic
|
|
|
352
352
|
|
|
353
353
|
from zepben.ewb.database.paths.database_type import *
|
|
354
354
|
from zepben.ewb.database.paths.ewb_data_file_paths import *
|
|
355
|
+
from zepben.ewb.database.paths.local_ewb_data_file_paths import *
|
|
355
356
|
|
|
356
357
|
from zepben.ewb.database.sql.column import *
|
|
357
358
|
from zepben.ewb.database.sqlite.tables.sqlite_table import *
|
|
@@ -1,202 +1,89 @@
|
|
|
1
|
-
# Copyright
|
|
1
|
+
# Copyright 2025 Zeppelin Bend Pty Ltd
|
|
2
2
|
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
3
3
|
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
4
|
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
5
|
|
|
6
6
|
__all__ = ['EwbDataFilePaths']
|
|
7
7
|
|
|
8
|
+
from abc import ABC, abstractmethod
|
|
8
9
|
from datetime import date, timedelta
|
|
9
10
|
from pathlib import Path
|
|
10
|
-
from typing import
|
|
11
|
+
from typing import Optional, List, Generator
|
|
11
12
|
|
|
12
13
|
from zepben.ewb import require
|
|
13
14
|
from zepben.ewb.database.paths.database_type import DatabaseType
|
|
14
15
|
|
|
15
16
|
|
|
16
|
-
class EwbDataFilePaths:
|
|
17
|
+
class EwbDataFilePaths(ABC):
|
|
17
18
|
"""Provides paths to all the various data files / folders used by EWB."""
|
|
18
19
|
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
exists: Callable[[Path], bool] = Path.exists,
|
|
24
|
-
list_files: Callable[[Path], Iterator[Path]] = Path.iterdir):
|
|
25
|
-
"""
|
|
26
|
-
:param base_dir: The root directory of the EWB data structure.
|
|
27
|
-
:param create_path: Create the root directory (and any missing parent folders) if it does not exist.
|
|
28
|
-
"""
|
|
29
|
-
self.create_directories_func = create_directories_func
|
|
30
|
-
self.is_directory = is_directory
|
|
31
|
-
self.exists = exists
|
|
32
|
-
self.list_files = list_files
|
|
33
|
-
self._base_dir = base_dir
|
|
34
|
-
|
|
35
|
-
if create_path:
|
|
36
|
-
self.create_directories_func(base_dir)
|
|
37
|
-
|
|
38
|
-
require(self.is_directory(base_dir), lambda: f"base_dir must be a directory")
|
|
39
|
-
|
|
40
|
-
@property
|
|
41
|
-
def base_dir(self):
|
|
42
|
-
"""The root directory of the EWB data structure."""
|
|
43
|
-
return self._base_dir
|
|
44
|
-
|
|
45
|
-
def customer(self, database_date: date) -> Path:
|
|
46
|
-
"""
|
|
47
|
-
Determine the path to the "customers" database for the specified date.
|
|
48
|
-
|
|
49
|
-
:param database_date: The :class:`date` to use for the "customers" database.
|
|
50
|
-
:return: The :class:`path` to the "customers" database for the specified date.
|
|
51
|
-
"""
|
|
52
|
-
return self._to_dated_path(database_date, DatabaseType.CUSTOMER.file_descriptor)
|
|
53
|
-
|
|
54
|
-
def diagram(self, database_date: date) -> Path:
|
|
55
|
-
"""
|
|
56
|
-
Determine the path to the "diagrams" database for the specified date.
|
|
57
|
-
|
|
58
|
-
:param database_date: The :class:`date` to use for the "diagrams" database.
|
|
59
|
-
:return: The :class:`path` to the "diagrams" database for the specified date.
|
|
60
|
-
"""
|
|
61
|
-
return self._to_dated_path(database_date, DatabaseType.DIAGRAM.file_descriptor)
|
|
62
|
-
|
|
63
|
-
def measurement(self, database_date: date) -> Path:
|
|
64
|
-
"""
|
|
65
|
-
Determine the path to the "measurements" database for the specified date.
|
|
66
|
-
|
|
67
|
-
:param database_date: The :class:`date` to use for the "measurements" database.
|
|
68
|
-
:return: The :class:`path` to the "measurements" database for the specified date.
|
|
69
|
-
"""
|
|
70
|
-
return self._to_dated_path(database_date, DatabaseType.MEASUREMENT.file_descriptor)
|
|
71
|
-
|
|
72
|
-
def network_model(self, database_date: date) -> Path:
|
|
73
|
-
"""
|
|
74
|
-
Determine the path to the "network model" database for the specified date.
|
|
75
|
-
|
|
76
|
-
:param database_date: The :class:`date` to use for the "network model" database.
|
|
77
|
-
:return: The :class:`path` to the "network model" database for the specified date.
|
|
78
|
-
"""
|
|
79
|
-
return self._to_dated_path(database_date, DatabaseType.NETWORK_MODEL.file_descriptor)
|
|
80
|
-
|
|
81
|
-
def tile_cache(self, database_date: date) -> Path:
|
|
82
|
-
"""
|
|
83
|
-
Determine the path to the "tile cache" database for the specified date.
|
|
84
|
-
|
|
85
|
-
:param database_date: The :class:`date` to use for the "tile cache" database.
|
|
86
|
-
:return: The :class:`path` to the "tile cache" database for the specified date.
|
|
87
|
-
"""
|
|
88
|
-
return self._to_dated_path(database_date, DatabaseType.TILE_CACHE.file_descriptor)
|
|
89
|
-
|
|
90
|
-
def energy_reading(self, database_date: date) -> Path:
|
|
91
|
-
"""
|
|
92
|
-
Determine the path to the "energy readings" database for the specified date.
|
|
93
|
-
|
|
94
|
-
:param database_date: The :class:`date` to use for the "energy readings" database.
|
|
95
|
-
:return: The :class:`path` to the "energy readings" database for the specified date.
|
|
96
|
-
"""
|
|
97
|
-
return self._to_dated_path(database_date, DatabaseType.ENERGY_READING.file_descriptor)
|
|
98
|
-
|
|
99
|
-
def energy_readings_index(self) -> Path:
|
|
100
|
-
"""
|
|
101
|
-
Determine the path to the "energy readings index" database.
|
|
102
|
-
|
|
103
|
-
:return: The :class:`path` to the "energy readings index" database.
|
|
104
|
-
"""
|
|
105
|
-
return self._base_dir.joinpath(f"{DatabaseType.ENERGY_READINGS_INDEX.file_descriptor}.sqlite")
|
|
20
|
+
VARIANTS_PATH: str = "variants"
|
|
21
|
+
"""
|
|
22
|
+
The folder containing the variants. Will be placed under the dated folder alongside the network model database.
|
|
23
|
+
"""
|
|
106
24
|
|
|
107
|
-
def
|
|
25
|
+
def resolve(self, database_type: DatabaseType, database_date: Optional[date] = None, variant: Optional[str] = None) -> Path:
|
|
108
26
|
"""
|
|
109
|
-
|
|
27
|
+
Resolves the :class:`Path` to the database file for the specified :class:`DatabaseType`, within the specified `database_date`
|
|
28
|
+
and optional `variant` when `DatabaseType.per_date` is set to true.
|
|
110
29
|
|
|
111
|
-
:
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
def weather_reading(self) -> Path:
|
|
116
|
-
"""
|
|
117
|
-
Determine the path to the "weather readings" database.
|
|
30
|
+
:param database_type: The :class:`DatabaseType` to use for the database :class:`Path`.
|
|
31
|
+
:param database_date: The :class:`date` to use for the database :class:`Path`. Required when `database_type.per_date` is true, otherwise must be `None`.
|
|
32
|
+
:param variant: The optional name of the variant containing the database.
|
|
118
33
|
|
|
119
|
-
:return: The :class:`
|
|
34
|
+
:return: The :class:`Path` to the :class:`DatabaseType` database file.
|
|
120
35
|
"""
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
:
|
|
128
|
-
|
|
129
|
-
|
|
36
|
+
if database_date is not None:
|
|
37
|
+
require(database_type.per_date, lambda: "database_type must have its per_date set to True to use this method with a database_date.")
|
|
38
|
+
if variant is not None:
|
|
39
|
+
return self.resolve_database(self._to_dated_variant_path(database_type, database_date, variant))
|
|
40
|
+
else:
|
|
41
|
+
return self.resolve_database(self._to_dated_path(database_type, database_date))
|
|
42
|
+
else:
|
|
43
|
+
require(not database_type.per_date, lambda: "database_type must have its per_date set to False to use this method without a database_date.")
|
|
44
|
+
return self.resolve_database(Path(self._database_name(database_type)))
|
|
130
45
|
|
|
46
|
+
@abstractmethod
|
|
131
47
|
def create_directories(self, database_date: date) -> Path:
|
|
132
48
|
"""
|
|
133
49
|
Create the directories required to have a valid path for the specified date.
|
|
134
50
|
|
|
135
51
|
:param database_date: The :class:`date` required in the path.
|
|
136
|
-
:return: The :class:`
|
|
137
|
-
"""
|
|
138
|
-
date_path = self._base_dir.joinpath(str(database_date))
|
|
139
|
-
if self.exists(date_path):
|
|
140
|
-
return date_path
|
|
141
|
-
else:
|
|
142
|
-
self.create_directories_func(date_path)
|
|
143
|
-
return date_path
|
|
144
|
-
|
|
145
|
-
def _to_dated_path(self, database_date: date, file: str) -> Path:
|
|
146
|
-
return self._base_dir.joinpath(str(database_date), f"{database_date}-{file}.sqlite")
|
|
147
|
-
|
|
148
|
-
def _check_exists(self, database_type: DatabaseType, database_date: date) -> bool:
|
|
52
|
+
:return: The :class:`Path` to the directory for the `database_date`.
|
|
149
53
|
"""
|
|
150
|
-
|
|
54
|
+
raise NotImplemented
|
|
151
55
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
:
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
if database_type == DatabaseType.CUSTOMER:
|
|
160
|
-
model_path = self.customer(database_date)
|
|
161
|
-
elif database_type == DatabaseType.DIAGRAM:
|
|
162
|
-
model_path = self.diagram(database_date)
|
|
163
|
-
elif database_type == DatabaseType.MEASUREMENT:
|
|
164
|
-
model_path = self.measurement(database_date)
|
|
165
|
-
elif database_type == DatabaseType.NETWORK_MODEL:
|
|
166
|
-
model_path = self.network_model(database_date)
|
|
167
|
-
elif database_type == DatabaseType.TILE_CACHE:
|
|
168
|
-
model_path = self.tile_cache(database_date)
|
|
169
|
-
elif database_type == DatabaseType.ENERGY_READING:
|
|
170
|
-
model_path = self.energy_reading(database_date)
|
|
171
|
-
else:
|
|
172
|
-
raise ValueError(
|
|
173
|
-
"INTERNAL ERROR: Should only be calling `check_exists` for `per_date` files, which should all be covered above, so go ahead and add it.")
|
|
174
|
-
return self.exists(model_path)
|
|
175
|
-
|
|
176
|
-
def find_closest(self, database_type: DatabaseType, max_days_to_search: int = 999, target_date: date = date.today(), search_forwards: bool = False) -> \
|
|
177
|
-
Optional[date]:
|
|
56
|
+
def find_closest(
|
|
57
|
+
self,
|
|
58
|
+
database_type: DatabaseType,
|
|
59
|
+
max_days_to_search: int = 999999,
|
|
60
|
+
target_date: date = date.today(),
|
|
61
|
+
search_forwards: bool = False
|
|
62
|
+
) -> Optional[date]:
|
|
178
63
|
"""
|
|
179
64
|
Find the closest date with a usable database of the specified type.
|
|
180
65
|
|
|
181
66
|
:param database_type: The type of database to search for.
|
|
182
67
|
:param max_days_to_search: The maximum number of days to search for a valid database.
|
|
183
|
-
:param target_date: The target
|
|
184
|
-
:param search_forwards: Indicates the search should also look forwards in time from `
|
|
185
|
-
|
|
68
|
+
:param target_date: The target date. Defaults to today.
|
|
69
|
+
:param search_forwards: Indicates the search should also look forwards in time from `target_date` for a valid file. Defaults to reverse search only.
|
|
70
|
+
|
|
71
|
+
:return: The closest :class:`date` to `target_date` with a valid database of `database_type` within the search parameters, or null if no valid database
|
|
72
|
+
was found.
|
|
186
73
|
"""
|
|
187
74
|
if not database_type.per_date:
|
|
188
75
|
return None
|
|
189
76
|
|
|
190
|
-
|
|
77
|
+
descendants = list(self.enumerate_descendants())
|
|
78
|
+
if self._check_exists(descendants, database_type, target_date):
|
|
191
79
|
return target_date
|
|
192
80
|
|
|
193
81
|
offset = 1
|
|
194
|
-
|
|
195
82
|
while offset <= max_days_to_search:
|
|
196
83
|
offset_days = timedelta(offset)
|
|
197
84
|
try:
|
|
198
85
|
previous_date = target_date - offset_days
|
|
199
|
-
if self._check_exists(database_type, previous_date):
|
|
86
|
+
if self._check_exists(descendants, database_type, previous_date):
|
|
200
87
|
return previous_date
|
|
201
88
|
except OverflowError:
|
|
202
89
|
pass
|
|
@@ -204,34 +91,102 @@ class EwbDataFilePaths:
|
|
|
204
91
|
if search_forwards:
|
|
205
92
|
try:
|
|
206
93
|
forward_date = target_date + offset_days
|
|
207
|
-
if self._check_exists(database_type, forward_date):
|
|
94
|
+
if self._check_exists(descendants, database_type, forward_date):
|
|
208
95
|
return forward_date
|
|
209
96
|
except OverflowError:
|
|
210
97
|
pass
|
|
98
|
+
|
|
211
99
|
offset += 1
|
|
100
|
+
|
|
212
101
|
return None
|
|
213
102
|
|
|
214
|
-
def
|
|
103
|
+
def get_available_dates_for(self, database_type: DatabaseType) -> List[date]:
|
|
104
|
+
"""
|
|
105
|
+
Find available databases specified by :class:`DatabaseType` in data path.
|
|
106
|
+
|
|
107
|
+
:param database_type: The type of database to search for.
|
|
108
|
+
|
|
109
|
+
:return: list of :class:`date`'s for which this specified :class:`DatabaseType` databases exist in the data path.
|
|
110
|
+
"""
|
|
215
111
|
if not database_type.per_date:
|
|
216
112
|
raise ValueError(
|
|
217
|
-
"INTERNAL ERROR: Should only be calling `
|
|
113
|
+
"INTERNAL ERROR: Should only be calling `get_available_dates_for` for `per_date` files, "
|
|
114
|
+
"which should all be covered above, so go ahead and add it."
|
|
115
|
+
)
|
|
218
116
|
|
|
219
117
|
to_return = list()
|
|
220
118
|
|
|
221
|
-
for
|
|
222
|
-
if self.
|
|
119
|
+
for it in self.enumerate_descendants():
|
|
120
|
+
if it.name.endswith(self._database_name(database_type)):
|
|
223
121
|
try:
|
|
224
|
-
|
|
225
|
-
if self.exists(self._to_dated_path(database_date, database_type.file_descriptor)):
|
|
226
|
-
to_return.append(database_date)
|
|
122
|
+
to_return.append(date.fromisoformat(it.parent.name))
|
|
227
123
|
except ValueError:
|
|
228
124
|
pass
|
|
125
|
+
|
|
126
|
+
return sorted(to_return)
|
|
127
|
+
|
|
128
|
+
def get_available_variants_for(self, target_date: date = date.today()) -> List[str]:
|
|
129
|
+
"""
|
|
130
|
+
Find available variants for the specified `target_date` in data path.
|
|
131
|
+
|
|
132
|
+
:param target_date: The target date. Defaults to today.
|
|
133
|
+
|
|
134
|
+
:return: list of variant names that exist in the data path for the specified `target_date`.
|
|
135
|
+
"""
|
|
136
|
+
to_return = list()
|
|
137
|
+
|
|
138
|
+
for it in self.enumerate_descendants():
|
|
139
|
+
try:
|
|
140
|
+
if (str(it.parent.name).lower() == self.VARIANTS_PATH) and (str(it.parent.parent.name) == str(target_date)):
|
|
141
|
+
to_return.append(str(it.name))
|
|
142
|
+
except ValueError:
|
|
143
|
+
pass
|
|
144
|
+
|
|
229
145
|
return sorted(to_return)
|
|
230
146
|
|
|
231
|
-
|
|
147
|
+
@abstractmethod
|
|
148
|
+
def enumerate_descendants(self) -> Generator[Path, None, None]:
|
|
149
|
+
"""
|
|
150
|
+
Lists the child items of source location.
|
|
151
|
+
|
|
152
|
+
:return: generator of child items.
|
|
153
|
+
"""
|
|
154
|
+
raise NotImplemented
|
|
155
|
+
|
|
156
|
+
@abstractmethod
|
|
157
|
+
def resolve_database(self, path: Path) -> Path:
|
|
232
158
|
"""
|
|
233
|
-
|
|
159
|
+
Resolves the database in the specified source :class:`Path`.
|
|
234
160
|
|
|
235
|
-
:
|
|
161
|
+
:param path: :class:`Path` to the source database file.
|
|
162
|
+
:return: :class:`Path` to the local database file.
|
|
236
163
|
"""
|
|
237
|
-
|
|
164
|
+
raise NotImplemented
|
|
165
|
+
|
|
166
|
+
def _check_exists(self, descendants: List[Path], database_type: DatabaseType, database_date: date) -> bool:
|
|
167
|
+
"""
|
|
168
|
+
Check if a database :class:`Path` of the specified :class:`DatabaseType` and :class:`date` exists.
|
|
169
|
+
|
|
170
|
+
:param descendants: A list of :class:`Path` representing the descendant paths.
|
|
171
|
+
:param database_type: The type of database to search for.
|
|
172
|
+
:param database_date: The date to check.
|
|
173
|
+
|
|
174
|
+
:return: True if a database of the specified `database_type` and `database_date` exits in the date path.
|
|
175
|
+
"""
|
|
176
|
+
for cp in descendants:
|
|
177
|
+
if cp.is_relative_to(self._to_dated_path(database_type, database_date)):
|
|
178
|
+
return True
|
|
179
|
+
|
|
180
|
+
return False
|
|
181
|
+
|
|
182
|
+
def _to_dated_path(self, database_type: DatabaseType, database_date: date) -> Path:
|
|
183
|
+
date_str = str(database_date)
|
|
184
|
+
return Path(date_str).joinpath(f"{date_str}-{self._database_name(database_type)}")
|
|
185
|
+
|
|
186
|
+
def _to_dated_variant_path(self, database_type: DatabaseType, database_date: date, variant: str) -> Path:
|
|
187
|
+
date_str = str(database_date)
|
|
188
|
+
return Path(date_str).joinpath(self.VARIANTS_PATH, variant, f"{date_str}-{self._database_name(database_type)}")
|
|
189
|
+
|
|
190
|
+
@staticmethod
|
|
191
|
+
def _database_name(database_type: DatabaseType) -> str:
|
|
192
|
+
return f"{database_type.file_descriptor}.sqlite"
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Copyright 2025 Zeppelin Bend Pty Ltd
|
|
2
|
+
# This Source Code Form is subject to the terms of the Mozilla Public
|
|
3
|
+
# License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
4
|
+
# file, You can obtain one at https://mozilla.org/MPL/2.0/.
|
|
5
|
+
|
|
6
|
+
__all__ = ['LocalEwbDataFilePaths']
|
|
7
|
+
|
|
8
|
+
from datetime import date
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Callable, Generator, Union
|
|
11
|
+
|
|
12
|
+
from zepben.ewb import require
|
|
13
|
+
from zepben.ewb.database.paths.ewb_data_file_paths import EwbDataFilePaths
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
class LocalEwbDataFilePaths(EwbDataFilePaths):
|
|
17
|
+
"""Provides paths to all the various data files / folders in the local file system used by EWB."""
|
|
18
|
+
|
|
19
|
+
def __init__(
|
|
20
|
+
self,
|
|
21
|
+
base_dir: Union[Path, str],
|
|
22
|
+
create_path: bool = False,
|
|
23
|
+
create_directories_func: Callable[[Path], None] = lambda it: it.mkdir(parents=True),
|
|
24
|
+
is_directory: Callable[[Path], bool] = Path.is_dir,
|
|
25
|
+
exists: Callable[[Path], bool] = Path.exists,
|
|
26
|
+
list_files: Callable[[Path], Generator[Path, None, None]] = Path.iterdir,
|
|
27
|
+
):
|
|
28
|
+
"""
|
|
29
|
+
:param base_dir: The root directory of the EWB data structure.
|
|
30
|
+
:param create_path: Create the root directory (and any missing parent folders) if it does not exist.
|
|
31
|
+
:param create_directories_func: Function for directory creation.
|
|
32
|
+
:param is_directory: Function to determine if the supplied path is a directory .
|
|
33
|
+
:param exists: Function to determine if the supplied path exists.
|
|
34
|
+
:param list_files: Function for listing directories and files under the supplied path.
|
|
35
|
+
"""
|
|
36
|
+
self._base_dir = Path(base_dir)
|
|
37
|
+
self._create_directories_func = create_directories_func
|
|
38
|
+
self._exists = exists
|
|
39
|
+
self._list_files = list_files
|
|
40
|
+
|
|
41
|
+
if create_path:
|
|
42
|
+
self._create_directories_func(base_dir)
|
|
43
|
+
|
|
44
|
+
require(is_directory(base_dir), lambda: f"base_dir must be a directory")
|
|
45
|
+
|
|
46
|
+
def create_directories(self, database_date: date) -> Path:
|
|
47
|
+
date_path = self._base_dir.joinpath(str(database_date))
|
|
48
|
+
if not self._exists(date_path):
|
|
49
|
+
self._create_directories_func(date_path)
|
|
50
|
+
|
|
51
|
+
return date_path
|
|
52
|
+
|
|
53
|
+
def enumerate_descendants(self) -> Generator[Path, None, None]:
|
|
54
|
+
for it in self._list_files(self._base_dir):
|
|
55
|
+
yield it
|
|
56
|
+
|
|
57
|
+
def resolve_database(self, path: Path) -> Path:
|
|
58
|
+
return self._base_dir.joinpath(path)
|
|
@@ -84,16 +84,20 @@ class BaseDatabaseReader(ABC):
|
|
|
84
84
|
|
|
85
85
|
return True
|
|
86
86
|
|
|
87
|
-
async def load(self) -> bool:
|
|
87
|
+
async def load(self, perform_after_read_processing: bool = True) -> bool:
|
|
88
88
|
"""
|
|
89
|
-
|
|
89
|
+
Read the database.
|
|
90
|
+
|
|
91
|
+
:param perform_after_read_processing: An optional "opt-out" control for performing the "after read processing".
|
|
92
|
+
|
|
93
|
+
:return: `True` if the database was successfully read, otherwise `False`.
|
|
90
94
|
"""
|
|
91
95
|
try:
|
|
92
96
|
if self._has_been_used:
|
|
93
97
|
raise ValueError("You can only use the database reader once.")
|
|
94
98
|
self._has_been_used = True
|
|
95
99
|
|
|
96
|
-
return self._pre_load() and self._load_from_readers() and await self._post_load()
|
|
100
|
+
return self._pre_load() and self._load_from_readers() and ((not perform_after_read_processing) or await self._post_load())
|
|
97
101
|
except Exception as e:
|
|
98
102
|
self._logger.exception(f"Unable to load database: {e}")
|
|
99
103
|
return False
|
|
@@ -14,7 +14,7 @@ from typing import Callable, Any, List, Generator, Optional, overload, TypeVar
|
|
|
14
14
|
from zepben.ewb.dataclassy import dataclass
|
|
15
15
|
from zepben.ewb.model.cim.iec61970.base.core.name import Name
|
|
16
16
|
from zepben.ewb.model.cim.iec61970.base.core.name_type import NameType
|
|
17
|
-
from zepben.ewb.util import require,
|
|
17
|
+
from zepben.ewb.util import require, nlen, ngen, safe_remove
|
|
18
18
|
|
|
19
19
|
logger = logging.getLogger(__name__)
|
|
20
20
|
|
|
@@ -30,7 +30,7 @@ class IdentifiedObject(object, metaclass=ABCMeta):
|
|
|
30
30
|
relation, however must be in snake case to keep the phases PEP compliant.
|
|
31
31
|
"""
|
|
32
32
|
|
|
33
|
-
mrid: str
|
|
33
|
+
mrid: str
|
|
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
|
|
|
@@ -46,6 +46,9 @@ class IdentifiedObject(object, metaclass=ABCMeta):
|
|
|
46
46
|
|
|
47
47
|
def __init__(self, names: Optional[List[Name]] = None, **kwargs):
|
|
48
48
|
super(IdentifiedObject, self).__init__(**kwargs)
|
|
49
|
+
if not self.mrid or not self.mrid.strip():
|
|
50
|
+
raise ValueError("You must provide an mRID for this object.")
|
|
51
|
+
|
|
49
52
|
if names:
|
|
50
53
|
for name in names:
|
|
51
54
|
self.add_name(name.type, name.name)
|
|
@@ -28,7 +28,8 @@ class RegulatingCondEq(EnergyConnection):
|
|
|
28
28
|
|
|
29
29
|
def __init__(self, regulating_control: Optional[RegulatingControl] = None, **kwargs):
|
|
30
30
|
super(RegulatingCondEq, self).__init__(**kwargs)
|
|
31
|
-
|
|
31
|
+
if regulating_control:
|
|
32
|
+
self.regulating_control = regulating_control
|
|
32
33
|
|
|
33
34
|
@property
|
|
34
35
|
def regulating_control(self):
|
|
@@ -79,7 +79,7 @@ def document_to_cim(pb: PBDocument, cim: Document, service: BaseService):
|
|
|
79
79
|
@bind_to_cim
|
|
80
80
|
@add_to_network_or_none
|
|
81
81
|
def organisation_to_cim(pb: PBOrganisation, service: BaseService) -> Optional[Organisation]:
|
|
82
|
-
cim = Organisation()
|
|
82
|
+
cim = Organisation(mrid=pb.mrid())
|
|
83
83
|
|
|
84
84
|
identified_object_to_cim(pb.io, cim, service)
|
|
85
85
|
return cim
|
|
@@ -18,7 +18,7 @@ from zepben.ewb.model.cim.iec61970.base.wires.junction import Junction
|
|
|
18
18
|
from zepben.ewb.model.cim.iec61970.base.wires.power_transformer import PowerTransformer
|
|
19
19
|
from zepben.ewb.model.cim.iec61970.base.wires.power_transformer_end import PowerTransformerEnd
|
|
20
20
|
from zepben.ewb.services.network.network_service import NetworkService
|
|
21
|
-
from zepben.ewb.util import
|
|
21
|
+
from zepben.ewb.util import generate_id
|
|
22
22
|
|
|
23
23
|
|
|
24
24
|
# !! WARNING !! #
|
|
@@ -39,7 +39,7 @@ def create_two_winding_power_transformer(network_service: NetworkService, cn1: C
|
|
|
39
39
|
_connect_two_terminal_conducting_equipment(network_service=network_service, ce=power_transformer, cn1=cn1, cn2=cn2)
|
|
40
40
|
# TODO: How to associated PowerTransformerEndInfo to a PowerTransformerInfo
|
|
41
41
|
for i in range(1, 2):
|
|
42
|
-
end = PowerTransformerEnd(power_transformer=power_transformer)
|
|
42
|
+
end = PowerTransformerEnd(f"{power_transformer.mrid}-pte{i}", power_transformer=power_transformer)
|
|
43
43
|
power_transformer.add_end(end)
|
|
44
44
|
end.terminal = power_transformer.get_terminal_by_sn(i)
|
|
45
45
|
return power_transformer
|
|
@@ -69,7 +69,7 @@ def create_breaker(network_service: NetworkService, cn1: ConnectivityNode, cn2:
|
|
|
69
69
|
def create_bus(network_service: NetworkService, **kwargs) -> Junction:
|
|
70
70
|
bus = Junction(**kwargs)
|
|
71
71
|
if 'mrid' not in kwargs:
|
|
72
|
-
bus.mrid =
|
|
72
|
+
bus.mrid = generate_id()
|
|
73
73
|
network_service.add(bus)
|
|
74
74
|
_create_terminals(ce=bus, network=network_service)
|
|
75
75
|
# TODO: Figure out how to add Voltage to Buses - Looks like we need to add topologicalNode to support the
|
|
@@ -79,7 +79,7 @@ def create_bus(network_service: NetworkService, **kwargs) -> Junction:
|
|
|
79
79
|
|
|
80
80
|
def _create_two_terminal_conducting_equipment(network_service: NetworkService, ce: ConductingEquipment, **kwargs):
|
|
81
81
|
if 'mrid' not in kwargs:
|
|
82
|
-
ce.mrid =
|
|
82
|
+
ce.mrid = generate_id()
|
|
83
83
|
network_service.add(ce)
|
|
84
84
|
_create_terminals(ce=ce, num_terms=2, network=network_service)
|
|
85
85
|
|
|
@@ -92,7 +92,7 @@ def _connect_two_terminal_conducting_equipment(network_service: NetworkService,
|
|
|
92
92
|
|
|
93
93
|
def _create_single_terminal_conducting_equipment(network_service: NetworkService, ce: ConductingEquipment, **kwargs):
|
|
94
94
|
if 'mrid' not in kwargs:
|
|
95
|
-
ce.mrid =
|
|
95
|
+
ce.mrid = generate_id()
|
|
96
96
|
network_service.add(ce)
|
|
97
97
|
_create_terminals(ce=ce, network=network_service)
|
|
98
98
|
|
zepben/ewb/util.py
CHANGED
|
@@ -15,7 +15,7 @@ __all__ = [
|
|
|
15
15
|
"is_none_or_empty",
|
|
16
16
|
"require",
|
|
17
17
|
"pb_or_none",
|
|
18
|
-
"
|
|
18
|
+
"generate_id",
|
|
19
19
|
"datetime_to_timestamp",
|
|
20
20
|
"none",
|
|
21
21
|
"classproperty",
|
|
@@ -170,14 +170,8 @@ def none(collection: Collection):
|
|
|
170
170
|
raise ValueError("none() only supports collection types")
|
|
171
171
|
|
|
172
172
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
def __init__(self):
|
|
176
|
-
super().__init__(bytes=os.urandom(16), version=4)
|
|
177
|
-
|
|
178
|
-
@staticmethod
|
|
179
|
-
def copy():
|
|
180
|
-
return str(UUID(bytes=os.urandom(16), version=4))
|
|
173
|
+
def generate_id() -> str:
|
|
174
|
+
return str(UUID(bytes=os.urandom(16), version=4))
|
|
181
175
|
|
|
182
176
|
|
|
183
177
|
class classproperty(property):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: zepben.ewb
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.1.0
|
|
4
4
|
Summary: Python SDK for interacting with the Energy Workbench platform
|
|
5
5
|
Author-email: Kurt Greaves <kurt.greaves@zepben.com>, Max Chesterfield <max.chesterfield@zepben.com>
|
|
6
6
|
License-Expression: MPL-2.0
|
|
@@ -15,17 +15,18 @@ Requires-Python: <3.13,>=3.10
|
|
|
15
15
|
Description-Content-Type: text/markdown
|
|
16
16
|
License-File: LICENSE
|
|
17
17
|
Requires-Dist: zepben.protobuf==1.0.0
|
|
18
|
-
Requires-Dist: typing_extensions==4.
|
|
19
|
-
Requires-Dist: requests
|
|
20
|
-
Requires-Dist: urllib3
|
|
21
|
-
Requires-Dist: PyJWT
|
|
18
|
+
Requires-Dist: typing_extensions==4.14.1
|
|
19
|
+
Requires-Dist: requests==2.32.5
|
|
20
|
+
Requires-Dist: urllib3==2.5.0
|
|
21
|
+
Requires-Dist: PyJWT==2.10.1
|
|
22
|
+
Requires-Dist: dataclassy==0.6.2
|
|
22
23
|
Provides-Extra: test
|
|
23
|
-
Requires-Dist: pytest
|
|
24
|
-
Requires-Dist: pytest-cov==6.
|
|
25
|
-
Requires-Dist: pytest-asyncio==
|
|
24
|
+
Requires-Dist: pytest==8.4.1; extra == "test"
|
|
25
|
+
Requires-Dist: pytest-cov==6.2.1; extra == "test"
|
|
26
|
+
Requires-Dist: pytest-asyncio==1.1.0; extra == "test"
|
|
26
27
|
Requires-Dist: pytest-timeout==2.4.0; extra == "test"
|
|
27
|
-
Requires-Dist: pytest-subtests; extra == "test"
|
|
28
|
-
Requires-Dist: hypothesis==6.
|
|
28
|
+
Requires-Dist: pytest-subtests==0.14.2; extra == "test"
|
|
29
|
+
Requires-Dist: hypothesis==6.140.3; extra == "test"
|
|
29
30
|
Requires-Dist: grpcio-testing==1.61.3; extra == "test"
|
|
30
31
|
Requires-Dist: pylint==2.14.5; extra == "test"
|
|
31
32
|
Requires-Dist: six==1.16.0; extra == "test"
|
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
zepben/ewb/__init__.py,sha256=
|
|
1
|
+
zepben/ewb/__init__.py,sha256=nPkN55KJGBRGRk7fLZAFmzaxu9Z7RR7gGAAwFWdy3lY,40580
|
|
2
2
|
zepben/ewb/exceptions.py,sha256=KLR6_5U-K4_VtKQZkKBlbOF7wlKnajQuhSiGeeNAo9U,1384
|
|
3
3
|
zepben/ewb/types.py,sha256=067jjQX6eCbgaEtlQPdSBi_w4_16unbP1f_g5NrVj_w,627
|
|
4
|
-
zepben/ewb/util.py,sha256=
|
|
4
|
+
zepben/ewb/util.py,sha256=JAa6epASTcxbu6gISzYJPjCGhckIugMd6tnVRMlSlMc,5605
|
|
5
5
|
zepben/ewb/auth/__init__.py,sha256=DUsi8JWvKMQt4xEUCHbCVPjGkEfr2MRu2JIvobYTB-M,406
|
|
6
6
|
zepben/ewb/auth/client/__init__.py,sha256=nFdcikJb3FegBko35m1xxmjMmC3cZCaqr8ohypQJQIQ,245
|
|
7
7
|
zepben/ewb/auth/client/zepben_token_fetcher.py,sha256=q1-co2LSWPwuSzzUZmNLYmjsQaCIrfSu4tOxwS_TMMk,12201
|
|
@@ -12,7 +12,8 @@ zepben/ewb/auth/common/auth_provider_config.py,sha256=-MkmrOXFgp2K-Q9f-oyaNr2Qhe
|
|
|
12
12
|
zepben/ewb/database/__init__.py,sha256=waADXEvfUG9wAN4STx5uIUHOv0UnpZLH2qU1LXgaDBc,243
|
|
13
13
|
zepben/ewb/database/paths/__init__.py,sha256=waADXEvfUG9wAN4STx5uIUHOv0UnpZLH2qU1LXgaDBc,243
|
|
14
14
|
zepben/ewb/database/paths/database_type.py,sha256=6l43Q87n3pQ4ClG9zfbp7cRSjt-Fxb01Tdrt48ZHMbk,1025
|
|
15
|
-
zepben/ewb/database/paths/ewb_data_file_paths.py,sha256=
|
|
15
|
+
zepben/ewb/database/paths/ewb_data_file_paths.py,sha256=MchDxklK9atSxOUtq28Yi4hRyilVk2GF8deMrsMdBt4,8063
|
|
16
|
+
zepben/ewb/database/paths/local_ewb_data_file_paths.py,sha256=XeOzoTvuaheD6KAM6EGW56rkiSDHIPE-x7_8iP5vQR0,2390
|
|
16
17
|
zepben/ewb/database/sql/__init__.py,sha256=8-znO960twGtcAGArLGl_ijbCB9BBv0_hUNYf1eF0Lk,243
|
|
17
18
|
zepben/ewb/database/sql/column.py,sha256=migPYL0in18cCWd3H51M-op2uqJeYqGv9KIksSiv75s,1049
|
|
18
19
|
zepben/ewb/database/sql/sql_table.py,sha256=0ADKRb_2uAz0iSz52wbwOjovctvwRte8sHBBfEGj7cU,5235
|
|
@@ -22,7 +23,7 @@ zepben/ewb/database/sqlite/common/base_cim_reader.py,sha256=RmJfeKtmvANUcam_EAVM
|
|
|
22
23
|
zepben/ewb/database/sqlite/common/base_cim_writer.py,sha256=sPYhkLlpyFt-i0B4UST2EF42i87N0V3Cb7XVaeL-WIU,8021
|
|
23
24
|
zepben/ewb/database/sqlite/common/base_collection_reader.py,sha256=yuOSWaztkJmlarCRcHtZslzYOg9UeVkNwjtuJLI6XCA,3755
|
|
24
25
|
zepben/ewb/database/sqlite/common/base_collection_writer.py,sha256=btq5hm57KnL3N4nUCoTLSstamJhFZcK8PM4WsnErm1g,2622
|
|
25
|
-
zepben/ewb/database/sqlite/common/base_database_reader.py,sha256=
|
|
26
|
+
zepben/ewb/database/sqlite/common/base_database_reader.py,sha256=q13wG7fZBuxo0UBuDrCPJ2ke0fGTt6Ap5CifjtF5new,5213
|
|
26
27
|
zepben/ewb/database/sqlite/common/base_database_tables.py,sha256=Bu-eBNs4VQENhdZiQt1o9oB2chXhm6CUrsbSNkcEwBE,5589
|
|
27
28
|
zepben/ewb/database/sqlite/common/base_database_writer.py,sha256=GStTD4J6F3PlbI1arInqwdazQqngPEaFsItzbzvj3I8,7076
|
|
28
29
|
zepben/ewb/database/sqlite/common/base_entry_writer.py,sha256=c1u1OjFKw9aB0L6kLTfoHbuKORrYYg83geBOXdUElZY,1278
|
|
@@ -366,7 +367,7 @@ zepben/ewb/model/cim/iec61968/infiec61968/infassets/streetlight_lamp_kind.py,sha
|
|
|
366
367
|
zepben/ewb/model/cim/iec61968/infiec61968/infcommon/__init__.py,sha256=waADXEvfUG9wAN4STx5uIUHOv0UnpZLH2qU1LXgaDBc,243
|
|
367
368
|
zepben/ewb/model/cim/iec61968/infiec61968/infcommon/ratio.py,sha256=1AHSbspQH822s7Pwx6oHUpFXgSaNh0rGNi9IVZJMXMc,1190
|
|
368
369
|
zepben/ewb/model/cim/iec61968/metering/__init__.py,sha256=waADXEvfUG9wAN4STx5uIUHOv0UnpZLH2qU1LXgaDBc,243
|
|
369
|
-
zepben/ewb/model/cim/iec61968/metering/controlled_appliance.py,sha256=
|
|
370
|
+
zepben/ewb/model/cim/iec61968/metering/controlled_appliance.py,sha256=3yU3yuKomb4V5BefJ5x7usVMTQOaggfVlYmL7KjqR-M,4473
|
|
370
371
|
zepben/ewb/model/cim/iec61968/metering/end_device.py,sha256=UzmPz-thDn5FeLuckKuTWCeMXlTtgltHr9t1BYdOFpw,6594
|
|
371
372
|
zepben/ewb/model/cim/iec61968/metering/end_device_function.py,sha256=AHZjuTs9TDeVX3SDhoHX2bCE6zwiUTfxVBWvA-k25aA,582
|
|
372
373
|
zepben/ewb/model/cim/iec61968/metering/end_device_function_kind.py,sha256=c0cze0jp3SgOvEE2qZqL_ye3RLLvR3UIG5mAD8Slf4U,1299
|
|
@@ -395,7 +396,7 @@ zepben/ewb/model/cim/iec61970/base/core/equipment.py,sha256=y5qhryMlYmcJfMQYc4wF
|
|
|
395
396
|
zepben/ewb/model/cim/iec61970/base/core/equipment_container.py,sha256=1GjHcISjQlh9OqgIJ3Sy5VguQvoJ1Ts_lYCkdkVnLHQ,8116
|
|
396
397
|
zepben/ewb/model/cim/iec61970/base/core/feeder.py,sha256=5gG8KopIsp1z9D3r9sCUc5y2I7oiTgJ7LF-DRhm2PT4,11368
|
|
397
398
|
zepben/ewb/model/cim/iec61970/base/core/geographical_region.py,sha256=LsOfVHuWL32zjPvgylpqiTsP9uvOeREVKgvKYMgZOOQ,3852
|
|
398
|
-
zepben/ewb/model/cim/iec61970/base/core/identified_object.py,sha256=
|
|
399
|
+
zepben/ewb/model/cim/iec61970/base/core/identified_object.py,sha256=TwY7M6zpd-Wvb8LxyHAUFJq6-lkioUtSVqxh0P689Gc,9928
|
|
399
400
|
zepben/ewb/model/cim/iec61970/base/core/name.py,sha256=Jgq664dfkYxVgYt4ThJM6g5NaJg40GW5ePZg4nVRC8Q,1285
|
|
400
401
|
zepben/ewb/model/cim/iec61970/base/core/name_type.py,sha256=N-ZCjV_ihvq4iTVBSrVYuew4Uc9gtFSJq1qElcK9jmI,7888
|
|
401
402
|
zepben/ewb/model/cim/iec61970/base/core/phase_code.py,sha256=8PWCBOSDniP_921sD8Qh30RVUTdWfWur0NvdeZLXlTI,7049
|
|
@@ -477,7 +478,7 @@ zepben/ewb/model/cim/iec61970/base/wires/protected_switch.py,sha256=yMn2MMvbViXL
|
|
|
477
478
|
zepben/ewb/model/cim/iec61970/base/wires/ratio_tap_changer.py,sha256=iYrZd8rjFfuPC-wGuYFKfNRBuHuA2Ss9ad_Gnt7qj_o,1161
|
|
478
479
|
zepben/ewb/model/cim/iec61970/base/wires/reactive_capability_curve.py,sha256=RvnW7HjAxsl3DNM9ABgzBqaoOSnbPBVwdvoIWwCMMj8,824
|
|
479
480
|
zepben/ewb/model/cim/iec61970/base/wires/recloser.py,sha256=UmL-qht9TL_VDZMUdWQ_4HeCG6dZLl_1G1ggro802VY,541
|
|
480
|
-
zepben/ewb/model/cim/iec61970/base/wires/regulating_cond_eq.py,sha256=
|
|
481
|
+
zepben/ewb/model/cim/iec61970/base/wires/regulating_cond_eq.py,sha256=ead_d22h_GieSz2soOfBhaUq_B1q3zie1lKVK9uQs_s,1827
|
|
481
482
|
zepben/ewb/model/cim/iec61970/base/wires/regulating_control.py,sha256=tyYfQHj_Fo4WJyyOglkvxg5D_D4zeB1kniH3EvcmHsk,9343
|
|
482
483
|
zepben/ewb/model/cim/iec61970/base/wires/regulating_control_mode_kind.py,sha256=qzxns3WLPo_bICQgctvPuz_667RB2gG0s51i7JXKH98,1203
|
|
483
484
|
zepben/ewb/model/cim/iec61970/base/wires/rotating_machine.py,sha256=pn8V5O5TPIhmWWX1hri27INs_iOEvQePukvjEN4A8HY,1513
|
|
@@ -502,7 +503,7 @@ zepben/ewb/services/services.py,sha256=BQxw0oscF2j-nOHVpyDsTa2h6rLoaGEBBagaBcjZT
|
|
|
502
503
|
zepben/ewb/services/common/__init__.py,sha256=yWD_2hLps_qzUFigJx1MY4Fer-UL9zQKtwuHlreYPis,956
|
|
503
504
|
zepben/ewb/services/common/base_service.py,sha256=xvfIuChJMqD-FOU6iFhxjjt4iKb9Lm3ulwMZ5wksn_4,18547
|
|
504
505
|
zepben/ewb/services/common/base_service_comparator.py,sha256=uHHBfWTSbJD3yvpb5o6cMMhXK1s4I1ygyRyTdGa-Mp4,18664
|
|
505
|
-
zepben/ewb/services/common/difference.py,sha256=
|
|
506
|
+
zepben/ewb/services/common/difference.py,sha256=KbMd6PV4_CKSHVvR9evc6EcQYD2gBHd3_bKtYu_FWzQ,1214
|
|
506
507
|
zepben/ewb/services/common/enum_mapper.py,sha256=B3FJLg5HVOc_wdFbokjKSgPudHWjUzGI6RyihzEoBvU,2323
|
|
507
508
|
zepben/ewb/services/common/reference_resolvers.py,sha256=M8QDJWtcOdrcl4-pXOg5dY9xGSFPM4KnqwKT-D9_-fM,26914
|
|
508
509
|
zepben/ewb/services/common/resolver.py,sha256=SaH5azHzq1cQsikbaf3i_ODA73rHyELyEm1s3Mu-tyw,26165
|
|
@@ -513,7 +514,7 @@ zepben/ewb/services/common/meta/metadata_translations.py,sha256=O8tW3YVrogmKEAOE
|
|
|
513
514
|
zepben/ewb/services/common/meta/service_info.py,sha256=EX1iwDv6ENS4la-hs9XQXjfKv10bM-P_WYx48xW42ik,609
|
|
514
515
|
zepben/ewb/services/common/translator/__init__.py,sha256=waADXEvfUG9wAN4STx5uIUHOv0UnpZLH2qU1LXgaDBc,243
|
|
515
516
|
zepben/ewb/services/common/translator/base_cim2proto.py,sha256=OxlXiFiZGxdinqBgbmHSOEnOZNKhJgmvg_jswDSgKkw,3860
|
|
516
|
-
zepben/ewb/services/common/translator/base_proto2cim.py,sha256=
|
|
517
|
+
zepben/ewb/services/common/translator/base_proto2cim.py,sha256=afGTsUnax3fvZTfAm014OM5dZiIlZwxLJxxGxgU02_Q,5217
|
|
517
518
|
zepben/ewb/services/common/translator/service_differences.py,sha256=ZFbGFMxTTnT4zt4zIt2BK_ikg_71vGkkmH8JhII2bMc,2913
|
|
518
519
|
zepben/ewb/services/common/translator/util.py,sha256=C7KGB5B7I3j2uSlDLtKUeQUNSFqLCqz4u9vA-TKKE34,2292
|
|
519
520
|
zepben/ewb/services/customer/__init__.py,sha256=waADXEvfUG9wAN4STx5uIUHOv0UnpZLH2qU1LXgaDBc,243
|
|
@@ -536,7 +537,7 @@ zepben/ewb/services/measurement/translator/__init__.py,sha256=IoQHJ-CYDhqiYL6WKK
|
|
|
536
537
|
zepben/ewb/services/measurement/translator/measurement_cim2proto.py,sha256=syPJC3FtXyNrJNRDc4oCLZUL0kzgyXRI7CsRmrbznhI,2114
|
|
537
538
|
zepben/ewb/services/measurement/translator/measurement_proto2cim.py,sha256=fsRXt_txPzUWDrFreZ1C1LcizUZQ-qlFq2aGADo9Q_E,2326
|
|
538
539
|
zepben/ewb/services/network/__init__.py,sha256=waADXEvfUG9wAN4STx5uIUHOv0UnpZLH2qU1LXgaDBc,243
|
|
539
|
-
zepben/ewb/services/network/network_extensions.py,sha256=
|
|
540
|
+
zepben/ewb/services/network/network_extensions.py,sha256=PGkeW2z5WNpQ8MeQIfCpTUL7ukne2uHO9R-PlBKEWyg,6127
|
|
540
541
|
zepben/ewb/services/network/network_service.py,sha256=tfmafoAK36bv_aMPL0zCagd3-RjUwGJX1MUeF5xZup4,12574
|
|
541
542
|
zepben/ewb/services/network/network_service_comparator.py,sha256=sxbseccB4l_K399rJVJxnmaOT6m4QGKlNbdTtBGbBfs,61978
|
|
542
543
|
zepben/ewb/services/network/network_state.py,sha256=PQo1xm6p4WGHzLtd4zy3nYMJ6miR3ypj7hSQx_dRgXY,837
|
|
@@ -634,8 +635,8 @@ zepben/ewb/streaming/mutations/update_network_state_client.py,sha256=e0Oma5PRT8m
|
|
|
634
635
|
zepben/ewb/streaming/mutations/update_network_state_service.py,sha256=irR-TO67QXRyBmK8PU8SzM31NKSSefZt_nQGHi5IhT8,3260
|
|
635
636
|
zepben/ewb/testing/__init__.py,sha256=waADXEvfUG9wAN4STx5uIUHOv0UnpZLH2qU1LXgaDBc,243
|
|
636
637
|
zepben/ewb/testing/test_network_builder.py,sha256=KG0o2ZHUswx3xClu-JnLs_pYIYbQ5jjtvtyZ7LI6IZ8,38092
|
|
637
|
-
zepben_ewb-1.0.
|
|
638
|
-
zepben_ewb-1.0.
|
|
639
|
-
zepben_ewb-1.0.
|
|
640
|
-
zepben_ewb-1.0.
|
|
641
|
-
zepben_ewb-1.0.
|
|
638
|
+
zepben_ewb-1.1.0.dist-info/licenses/LICENSE,sha256=aAHD66h6PQIETpkJDvg5yEObyFvXUED8u7S8dlh6K0Y,16725
|
|
639
|
+
zepben_ewb-1.1.0.dist-info/METADATA,sha256=74QEghgDPCso_MX_O1zEJDXba1F6v8VlvXop9DkWe68,3230
|
|
640
|
+
zepben_ewb-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
641
|
+
zepben_ewb-1.1.0.dist-info/top_level.txt,sha256=eVLDJiO6FGjL_Z7KdmFE-R8uf1Q07aaVLGe9Ee4kmBw,7
|
|
642
|
+
zepben_ewb-1.1.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|