gridappsd-python 2024.6.0__tar.gz → 2025.2.1__tar.gz
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.
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/PKG-INFO +6 -7
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/difference_builder.py +11 -7
- gridappsd_python-2025.2.1/gridappsd/field_interface/__init__.py +32 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/goss.py +8 -3
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/topics.py +24 -15
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/pyproject.toml +5 -4
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/README.md +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/__init__.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/__main__.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/app_registration.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/docker_handler.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/gridappsd.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/houses.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/json_extension.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/loghandler.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/register_app.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/simulation.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/timeseries.py +0 -0
- {gridappsd_python-2024.6.0 → gridappsd_python-2025.2.1}/gridappsd/utils.py +0 -0
|
@@ -1,25 +1,24 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.3
|
|
2
2
|
Name: gridappsd-python
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2025.2.1
|
|
4
4
|
Summary: A GridAPPS-D Python Adapter
|
|
5
|
-
Home-page: https://gridappsd.readthedocs.io
|
|
6
5
|
License: BSD-3-Clause
|
|
7
|
-
Keywords: gridappsd,grid,
|
|
6
|
+
Keywords: gridappsd,grid,activemq,powergrid,simulation,library
|
|
8
7
|
Author: C. Allwardt
|
|
9
8
|
Author-email: 3979063+craig8@users.noreply.github.com
|
|
10
|
-
Requires-Python: >=3.
|
|
9
|
+
Requires-Python: >=3.10,<4.0
|
|
11
10
|
Classifier: License :: OSI Approved :: BSD License
|
|
12
11
|
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.8
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.9
|
|
15
12
|
Classifier: Programming Language :: Python :: 3.10
|
|
16
13
|
Classifier: Programming Language :: Python :: 3.11
|
|
17
14
|
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
18
16
|
Requires-Dist: PyYAML (>=6.0,<7.0)
|
|
19
17
|
Requires-Dist: dateutils (>=0.6.7,<0.7.0)
|
|
20
18
|
Requires-Dist: pytz (>=2022.7,<2023.0)
|
|
21
19
|
Requires-Dist: requests (==2.28.2)
|
|
22
20
|
Requires-Dist: stomp-py (==6.0.0)
|
|
21
|
+
Project-URL: Homepage, https://gridappsd.readthedocs.io
|
|
23
22
|
Project-URL: Repository, https://github.com/GRIDAPPSD/gridappsd-python
|
|
24
23
|
Description-Content-Type: text/markdown
|
|
25
24
|
|
|
@@ -42,19 +42,17 @@ import calendar
|
|
|
42
42
|
from uuid import uuid4
|
|
43
43
|
import time
|
|
44
44
|
|
|
45
|
-
import pytz
|
|
46
|
-
|
|
47
45
|
|
|
48
46
|
class DifferenceBuilder(object):
|
|
49
47
|
""" Automates the building of forward and reverse cim differences
|
|
50
48
|
|
|
51
49
|
"""
|
|
52
50
|
|
|
53
|
-
def __init__(self, simulation_id):
|
|
51
|
+
def __init__(self, simulation_id: str | int | None = None):
|
|
54
52
|
|
|
55
53
|
self._simulation_id = simulation_id
|
|
56
|
-
self._forward = []
|
|
57
|
-
self._reverse = []
|
|
54
|
+
self._forward: list[dict] = []
|
|
55
|
+
self._reverse: list[dict] = []
|
|
58
56
|
|
|
59
57
|
def add_difference(self, object_id, attribute, forward_value, reverse_value):
|
|
60
58
|
""" Add forward and reverse unit for an object attribute.
|
|
@@ -67,16 +65,22 @@ class DifferenceBuilder(object):
|
|
|
67
65
|
self._reverse.append(reverse)
|
|
68
66
|
|
|
69
67
|
def clear(self):
|
|
68
|
+
""" Clear the forward and reverse differences """
|
|
70
69
|
self._forward = []
|
|
71
70
|
self._reverse = []
|
|
72
71
|
|
|
73
72
|
def get_message(self, epoch=None):
|
|
73
|
+
""" Get the message to send to the GOSS message bus
|
|
74
|
+
|
|
75
|
+
:param epoch: The epoch time to use for the message timestamp. If None, the current time (GMT) is used.
|
|
76
|
+
"""
|
|
74
77
|
if epoch is None:
|
|
75
78
|
epoch = calendar.timegm(time.gmtime())
|
|
76
79
|
msg = dict(command="update",
|
|
77
|
-
input=dict(
|
|
78
|
-
message=dict(timestamp=epoch,
|
|
80
|
+
input=dict(message=dict(timestamp=epoch,
|
|
79
81
|
difference_mrid=str(uuid4()),
|
|
80
82
|
reverse_differences=self._reverse,
|
|
81
83
|
forward_differences=self._forward)))
|
|
84
|
+
if self._simulation_id is not None:
|
|
85
|
+
msg['input']['simulation_id'] = self._simulation_id
|
|
82
86
|
return msg.copy()
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
import sys
|
|
3
|
+
|
|
4
|
+
_log = logging.getLogger(__name__)
|
|
5
|
+
|
|
6
|
+
try:
|
|
7
|
+
import warnings
|
|
8
|
+
|
|
9
|
+
import gridappsd_field_bus.field_interface.context as _context
|
|
10
|
+
import gridappsd_field_bus.field_interface.context_managers as _context_managers
|
|
11
|
+
import gridappsd_field_bus.field_interface as _field_interface
|
|
12
|
+
import gridappsd_field_bus.field_interface.agents as _agents
|
|
13
|
+
import gridappsd_field_bus.field_interface.field_proxy_forwarder as _field_proxy_forwarder
|
|
14
|
+
import gridappsd_field_bus.field_interface.gridappsd_field_bus as _gridappsd_field_bus
|
|
15
|
+
import gridappsd_field_bus.field_interface.interfaces as _interfaces
|
|
16
|
+
|
|
17
|
+
sys.modules['gridappsd.field_interface'] = _field_interface
|
|
18
|
+
sys.modules['gridappsd.field_interface.interfaces'] = _interfaces
|
|
19
|
+
sys.modules['gridappsd.field_interface.context_managers'] = _context_managers
|
|
20
|
+
sys.modules['gridappsd_.context_managers'] = _context_managers
|
|
21
|
+
sys.modules['gridappsd.field_interface.agents'] = _agents
|
|
22
|
+
sys.modules['gridappsd.field_interface.field_proxy_forwarder'] = _field_proxy_forwarder
|
|
23
|
+
sys.modules['gridappsd.field_interface.gridappsd_field_bus'] = _gridappsd_field_bus
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
warnings.warn(message="gridappsd.field_interface is deprecated and will be removed in a future release. Use gridappsd_field_bus.field_interface instead.",
|
|
30
|
+
category=DeprecationWarning)
|
|
31
|
+
except ImportError:
|
|
32
|
+
_log.error("Could not import field_interface install gridappsd-field-bus to get those functions.")
|
|
@@ -88,7 +88,8 @@ class GOSS(object):
|
|
|
88
88
|
attempt_connection=True,
|
|
89
89
|
override_threading=None,
|
|
90
90
|
stomp_log_level=logging.WARNING,
|
|
91
|
-
goss_log_level=logging.INFO
|
|
91
|
+
goss_log_level=logging.INFO,
|
|
92
|
+
use_auth_token=True):
|
|
92
93
|
|
|
93
94
|
logging.getLogger('stomp.py').setLevel(stomp_log_level)
|
|
94
95
|
logging.getLogger('goss').setLevel(goss_log_level)
|
|
@@ -97,6 +98,7 @@ class GOSS(object):
|
|
|
97
98
|
self.__pass__ = password
|
|
98
99
|
self.stomp_address = stomp_address
|
|
99
100
|
self.stomp_port = stomp_port
|
|
101
|
+
self.use_auth_token = use_auth_token
|
|
100
102
|
|
|
101
103
|
# Environmental variables should overrule the passed arguments.
|
|
102
104
|
if os.environ.get(GRIDAPPSD_ENV_ENUM.GRIDAPPSD_USER.value):
|
|
@@ -289,7 +291,7 @@ class GOSS(object):
|
|
|
289
291
|
def _make_connection(self):
|
|
290
292
|
if self._conn is None or not self._conn.is_connected():
|
|
291
293
|
_log.debug("Creating connection")
|
|
292
|
-
if not self.__token:
|
|
294
|
+
if self.use_auth_token is True and not self.__token:
|
|
293
295
|
|
|
294
296
|
# get token
|
|
295
297
|
# get initial connection
|
|
@@ -351,7 +353,10 @@ class GOSS(object):
|
|
|
351
353
|
if self._override_thread_fc is not None:
|
|
352
354
|
self._conn.transport.override_threading(self._override_thread_fc)
|
|
353
355
|
try:
|
|
354
|
-
self.
|
|
356
|
+
if self.use_auth_token and self.__token is not None:
|
|
357
|
+
self._conn.connect(self.__token, "", wait=True)
|
|
358
|
+
else:
|
|
359
|
+
self._conn.connect(self.__user__,self.__pass__, wait=True)
|
|
355
360
|
except TypeError as e:
|
|
356
361
|
_log.error("TypeError: {e}".format(e=e))
|
|
357
362
|
except NotConnectedException as e:
|
|
@@ -80,7 +80,7 @@ def platform_log_topic():
|
|
|
80
80
|
return "/topic/{}.{}".format(BASE_TOPIC_PREFIX, "platform.log")
|
|
81
81
|
|
|
82
82
|
|
|
83
|
-
def service_input_topic(service_id, simulation_id):
|
|
83
|
+
def service_input_topic(service_id: str, simulation_id: int | str | None = None):
|
|
84
84
|
""" Utility method for getting the input topic for a specific service.
|
|
85
85
|
|
|
86
86
|
The service id should be the registered service with the platform. One
|
|
@@ -95,11 +95,14 @@ def service_input_topic(service_id, simulation_id):
|
|
|
95
95
|
:return:
|
|
96
96
|
"""
|
|
97
97
|
assert service_id, "service_id cannot be empty"
|
|
98
|
-
assert simulation_id, "simulation_id cannot be empty"
|
|
99
|
-
return "{}.{}.{}.input".format(BASE_SIMULATION_TOPIC, service_id, simulation_id)
|
|
100
98
|
|
|
99
|
+
if simulation_id:
|
|
100
|
+
return f"{BASE_SIMULATION_TOPIC}.{service_id}.{simulation_id}.input"
|
|
101
101
|
|
|
102
|
-
|
|
102
|
+
return f"{BASE_SIMULATION_TOPIC}.{service_id}.input"
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def service_output_topic(service_id: str, simulation_id: int | str | None = None):
|
|
103
106
|
""" Utility method for getting the output topic for a specific service.
|
|
104
107
|
|
|
105
108
|
The service id should be the registered service with the platform. One
|
|
@@ -114,11 +117,14 @@ def service_output_topic(service_id, simulation_id):
|
|
|
114
117
|
:return:str: Topic to subscribe to for service specific output.
|
|
115
118
|
"""
|
|
116
119
|
assert service_id, "Service id cannot be empty"
|
|
117
|
-
assert simulation_id, "Simulation id cannot be empty"
|
|
118
|
-
return "{}.{}.{}.output".format(BASE_SIMULATION_TOPIC, service_id, simulation_id)
|
|
119
120
|
|
|
121
|
+
if simulation_id:
|
|
122
|
+
return f"{BASE_SIMULATION_TOPIC}.{service_id}.{simulation_id}.output"
|
|
123
|
+
|
|
124
|
+
return f"{BASE_SIMULATION_TOPIC}.{service_id}.output"
|
|
120
125
|
|
|
121
|
-
|
|
126
|
+
|
|
127
|
+
def application_input_topic(application_id: str, simulation_id: int | str | None = None):
|
|
122
128
|
""" Utility method for getting the input topic for a specific application.
|
|
123
129
|
|
|
124
130
|
The application_id should be the registered service with the platform. One
|
|
@@ -130,11 +136,14 @@ def application_input_topic(application_id, simulation_id):
|
|
|
130
136
|
:return:str: Topic to publish to for a specific application.
|
|
131
137
|
"""
|
|
132
138
|
assert application_id, "application_id cannot be empty"
|
|
133
|
-
assert simulation_id, "simulation_id cannot be empty"
|
|
134
|
-
return "{}.{}.{}.input".format(BASE_SIMULATION_TOPIC, application_id, simulation_id)
|
|
135
139
|
|
|
140
|
+
if simulation_id:
|
|
141
|
+
return f"{BASE_SIMULATION_TOPIC}.{application_id}.{simulation_id}.input"
|
|
142
|
+
|
|
143
|
+
return f"{BASE_TOPIC}.{application_id}.input"
|
|
136
144
|
|
|
137
|
-
|
|
145
|
+
|
|
146
|
+
def application_output_topic(application_id: str, simulation_id: int | str | None = None):
|
|
138
147
|
""" Utility method for getting the output topic for a specific application.
|
|
139
148
|
|
|
140
149
|
The application_id should be the registered service with the platform. One
|
|
@@ -146,11 +155,11 @@ def application_output_topic(application_id, simulation_id):
|
|
|
146
155
|
:return: str: Topic to subscribe to for application specific output.
|
|
147
156
|
"""
|
|
148
157
|
assert application_id, "application_id cannot be empty"
|
|
149
|
-
|
|
150
|
-
if simulation_id
|
|
151
|
-
return "{}.{}.output"
|
|
152
|
-
|
|
153
|
-
|
|
158
|
+
|
|
159
|
+
if simulation_id:
|
|
160
|
+
return f"{BASE_SIMULATION_TOPIC}.{application_id}.{simulation_id}.output"
|
|
161
|
+
|
|
162
|
+
return f"{BASE_TOPIC}.{application_id}.output"
|
|
154
163
|
|
|
155
164
|
|
|
156
165
|
def simulation_output_topic(simulation_id):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[tool.poetry]
|
|
2
2
|
name = "gridappsd-python"
|
|
3
|
-
version = "
|
|
3
|
+
version = "2025.02.1"
|
|
4
4
|
description = "A GridAPPS-D Python Adapter"
|
|
5
5
|
authors = [
|
|
6
6
|
"C. Allwardt <3979063+craig8@users.noreply.github.com>",
|
|
@@ -12,7 +12,7 @@ license = "BSD-3-Clause"
|
|
|
12
12
|
repository = "https://github.com/GRIDAPPSD/gridappsd-python"
|
|
13
13
|
homepage = "https://gridappsd.readthedocs.io"
|
|
14
14
|
|
|
15
|
-
keywords = ["gridappsd", "grid", "
|
|
15
|
+
keywords = ["gridappsd", "grid", "activemq", "powergrid", "simulation", "library"]
|
|
16
16
|
|
|
17
17
|
readme = "README.md"
|
|
18
18
|
|
|
@@ -29,7 +29,7 @@ gridappsd-cli = 'gridappsd.cli:_main'
|
|
|
29
29
|
|
|
30
30
|
|
|
31
31
|
[tool.poetry.dependencies]
|
|
32
|
-
python = ">=3.
|
|
32
|
+
python = ">=3.10,<4.0"
|
|
33
33
|
PyYAML = "^6.0"
|
|
34
34
|
pytz = "^2022.7"
|
|
35
35
|
dateutils = "^0.6.7"
|
|
@@ -37,13 +37,14 @@ stomp-py = "6.0.0"
|
|
|
37
37
|
requests = "2.28.2"
|
|
38
38
|
|
|
39
39
|
[tool.poetry.group.dev.dependencies]
|
|
40
|
-
pytest = "^
|
|
40
|
+
pytest = "^8.3.4"
|
|
41
41
|
pytest-html = "^3.1.1"
|
|
42
42
|
mock = "^4.0.3"
|
|
43
43
|
yapf = "^0.32.0"
|
|
44
44
|
mypy = "^1.3.0"
|
|
45
45
|
python-on-whales = "^0.60.1"
|
|
46
46
|
gitpython = "^3.1.31"
|
|
47
|
+
pre-commit = "^4.1.0"
|
|
47
48
|
|
|
48
49
|
[build-system]
|
|
49
50
|
requires = ["poetry-core>=1.2.0"]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|