gridappsd-python 2026.2.1a1__py3-none-any.whl → 2026.2.1a2__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.
- gridappsd/app_registration.py +35 -10
- gridappsd/goss.py +47 -53
- gridappsd/gridappsd.py +20 -13
- gridappsd/simulation.py +23 -19
- gridappsd/timeseries.py +16 -22
- {gridappsd_python-2026.2.1a1.dist-info → gridappsd_python-2026.2.1a2.dist-info}/METADATA +1 -1
- {gridappsd_python-2026.2.1a1.dist-info → gridappsd_python-2026.2.1a2.dist-info}/RECORD +9 -9
- {gridappsd_python-2026.2.1a1.dist-info → gridappsd_python-2026.2.1a2.dist-info}/WHEEL +0 -0
- {gridappsd_python-2026.2.1a1.dist-info → gridappsd_python-2026.2.1a2.dist-info}/entry_points.txt +0 -0
gridappsd/app_registration.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# import json
|
|
2
2
|
import logging
|
|
3
3
|
import os
|
|
4
|
+
from enum import Enum
|
|
4
5
|
from queue import Queue
|
|
5
6
|
import time
|
|
6
7
|
import subprocess
|
|
@@ -14,6 +15,30 @@ from . import utils, json_extension as json
|
|
|
14
15
|
|
|
15
16
|
_log = logging.getLogger(__name__)
|
|
16
17
|
|
|
18
|
+
GRIDAPPSD_APPLICATION_STATUS = "GRIDAPPSD_APPLICATION_STATUS"
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class ApplicationStatusEnum(Enum):
|
|
22
|
+
"""Values this module writes to the GRIDAPPSD_APPLICATION_STATUS environment variable.
|
|
23
|
+
|
|
24
|
+
This is a distinct enum from gridappsd.utils.ProcessStatusEnum: this module's
|
|
25
|
+
STOPPED value has no equivalent in ProcessStatusEnum (which has CLOSED
|
|
26
|
+
instead), so reusing that enum here would either drop STOPPED or introduce
|
|
27
|
+
a mismatch between the value written and the value a reader expects.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
STARTING = "STARTING"
|
|
31
|
+
STOPPING = "STOPPING"
|
|
32
|
+
RUNNING = "RUNNING"
|
|
33
|
+
STOPPED = "STOPPED"
|
|
34
|
+
ERROR = "ERROR"
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
def _set_application_status(status: ApplicationStatusEnum) -> None:
|
|
38
|
+
"""Write status to the GRIDAPPSD_APPLICATION_STATUS environment variable."""
|
|
39
|
+
os.environ[GRIDAPPSD_APPLICATION_STATUS] = status.value
|
|
40
|
+
|
|
41
|
+
|
|
17
42
|
# determine OS type
|
|
18
43
|
posix = False
|
|
19
44
|
if os.name == "posix":
|
|
@@ -35,20 +60,20 @@ class Job(threading.Thread):
|
|
|
35
60
|
def run(self):
|
|
36
61
|
try:
|
|
37
62
|
self.running = True
|
|
38
|
-
|
|
63
|
+
_set_application_status(ApplicationStatusEnum.RUNNING)
|
|
39
64
|
|
|
40
65
|
p = subprocess.Popen(args=self._args, shell=False, stdout=self._out, stderr=self._err)
|
|
41
66
|
|
|
42
67
|
# Loop while process is executing
|
|
43
68
|
while p.poll() is None and self.running:
|
|
44
|
-
|
|
69
|
+
_set_application_status(ApplicationStatusEnum.RUNNING)
|
|
45
70
|
time.sleep(1)
|
|
46
71
|
|
|
47
72
|
except Exception as e:
|
|
48
|
-
|
|
73
|
+
_set_application_status(ApplicationStatusEnum.ERROR)
|
|
49
74
|
_log.error(repr(e))
|
|
50
75
|
else:
|
|
51
|
-
|
|
76
|
+
_set_application_status(ApplicationStatusEnum.STOPPED)
|
|
52
77
|
|
|
53
78
|
|
|
54
79
|
class ApplicationController(object):
|
|
@@ -58,7 +83,7 @@ class ApplicationController(object):
|
|
|
58
83
|
if not isinstance(gridappsd, GridAPPSD):
|
|
59
84
|
raise ValueError("Invalid gridappsd instance passed.")
|
|
60
85
|
|
|
61
|
-
|
|
86
|
+
_set_application_status(ApplicationStatusEnum.STOPPED)
|
|
62
87
|
self._configDict = config.copy()
|
|
63
88
|
self._validate_config()
|
|
64
89
|
self._gapd = gridappsd
|
|
@@ -80,7 +105,7 @@ class ApplicationController(object):
|
|
|
80
105
|
self._end_callback = None
|
|
81
106
|
self._print_queue = Queue()
|
|
82
107
|
self._heartbeat_thread = None
|
|
83
|
-
|
|
108
|
+
_set_application_status(ApplicationStatusEnum.STOPPED)
|
|
84
109
|
|
|
85
110
|
if "type" not in self._configDict or self._configDict["type"] != "REMOTE":
|
|
86
111
|
_log.warning(
|
|
@@ -119,7 +144,7 @@ class ApplicationController(object):
|
|
|
119
144
|
self._stop_control_topic = response.get("stopControlTopic")
|
|
120
145
|
|
|
121
146
|
os.environ["GRIDAPPSD_APPLICATION_ID"] = self._application_id
|
|
122
|
-
|
|
147
|
+
_set_application_status(ApplicationStatusEnum.STOPPED)
|
|
123
148
|
|
|
124
149
|
self._gapd.subscribe(self._stop_control_topic, self.__handle_stop)
|
|
125
150
|
self._gapd.subscribe(self._start_control_topic, self.__handle_start)
|
|
@@ -160,7 +185,7 @@ class ApplicationController(object):
|
|
|
160
185
|
obj = json.loads(message)
|
|
161
186
|
else:
|
|
162
187
|
obj = message
|
|
163
|
-
|
|
188
|
+
_set_application_status(ApplicationStatusEnum.STARTING)
|
|
164
189
|
self._gapd.get_logger().debug("Handling Start: {}\ndict:\n{}".format(headers, obj))
|
|
165
190
|
|
|
166
191
|
if "command" not in obj:
|
|
@@ -176,12 +201,12 @@ class ApplicationController(object):
|
|
|
176
201
|
|
|
177
202
|
def __handle_stop(self, headers, message):
|
|
178
203
|
print("Handling Stop: {} {}".format(headers, message))
|
|
179
|
-
|
|
204
|
+
_set_application_status(ApplicationStatusEnum.STOPPING)
|
|
180
205
|
if self._thread:
|
|
181
206
|
self._thread.join()
|
|
182
207
|
if self._end_callback is not None:
|
|
183
208
|
self._end_callback()
|
|
184
|
-
|
|
209
|
+
_set_application_status(ApplicationStatusEnum.STOPPED)
|
|
185
210
|
|
|
186
211
|
def shutdown(self):
|
|
187
212
|
self._shutting_down = True
|
gridappsd/goss.py
CHANGED
|
@@ -57,7 +57,6 @@ from enum import Enum
|
|
|
57
57
|
from logging import Logger
|
|
58
58
|
from queue import Queue
|
|
59
59
|
|
|
60
|
-
import stomp as _stomp_module
|
|
61
60
|
from stomp import Connection12 as Connection
|
|
62
61
|
from stomp.exception import NotConnectedException
|
|
63
62
|
from time import sleep
|
|
@@ -66,19 +65,41 @@ from gridappsd import json_extension as json
|
|
|
66
65
|
|
|
67
66
|
_log: Logger = logging.getLogger(inspect.getmodulename(__file__))
|
|
68
67
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
68
|
+
|
|
69
|
+
def _unpack_stomp_args(*args):
|
|
70
|
+
"""Return (headers, body) from a stomp listener callback's arguments.
|
|
71
|
+
|
|
72
|
+
stomp-py pre 8.x, and this module's own CallbackRouter dispatch, call
|
|
73
|
+
on_message/on_error with two positional arguments: headers and body.
|
|
74
|
+
stomp-py 8.x's raw listener protocol calls with a single Frame object
|
|
75
|
+
exposing .headers and .body instead. A listener reached through
|
|
76
|
+
CallbackRouter (any listener registered via subscribe()) always
|
|
77
|
+
receives the two argument shape, regardless of the installed stomp-py
|
|
78
|
+
version, because CallbackRouter.run_callbacks is the caller, not
|
|
79
|
+
stomp itself. Only a listener registered directly on a raw stomp
|
|
80
|
+
Connection (CallbackRouter itself, TokenResponseListener) is actually
|
|
81
|
+
invoked by stomp's own version dependent dispatch. Detecting the
|
|
82
|
+
argument shape at each call, instead of trusting a single global
|
|
83
|
+
version sniffed flag, is correct for both callers.
|
|
84
|
+
"""
|
|
85
|
+
if len(args) >= 2:
|
|
86
|
+
return args[0], args[1]
|
|
87
|
+
frame = args[0]
|
|
88
|
+
if hasattr(frame, "headers") and hasattr(frame, "body"):
|
|
89
|
+
return frame.headers, frame.body
|
|
90
|
+
headers, body = frame
|
|
91
|
+
return headers, body
|
|
92
|
+
|
|
93
|
+
|
|
94
|
+
def _serialize_message(message):
|
|
95
|
+
"""Return message ready to send on the wire.
|
|
96
|
+
|
|
97
|
+
A list or dict body is serialized to a JSON string; any other body
|
|
98
|
+
(already a string, bytes, etc.) is passed through unchanged.
|
|
99
|
+
"""
|
|
100
|
+
if isinstance(message, (list, dict)):
|
|
101
|
+
return json.dumps(message)
|
|
102
|
+
return message
|
|
82
103
|
|
|
83
104
|
|
|
84
105
|
class GRIDAPPSD_ENV_ENUM(Enum):
|
|
@@ -168,8 +189,7 @@ class GOSS(object):
|
|
|
168
189
|
|
|
169
190
|
def send(self, topic, message):
|
|
170
191
|
self._make_connection()
|
|
171
|
-
|
|
172
|
-
message = json.dumps(message)
|
|
192
|
+
message = _serialize_message(message)
|
|
173
193
|
_log.debug("Sending topic: {} body: {}".format(topic, message))
|
|
174
194
|
self._conn.send(
|
|
175
195
|
body=message, destination=topic, headers={"GOSS_HAS_SUBJECT": True, "GOSS_SUBJECT": self.__token}
|
|
@@ -185,11 +205,8 @@ class GOSS(object):
|
|
|
185
205
|
if "resultFormat" in message:
|
|
186
206
|
self.result_format = message["resultFormat"]
|
|
187
207
|
|
|
188
|
-
# Change message to string if we have a dictionary.
|
|
189
|
-
|
|
190
|
-
message = json.dumps(message)
|
|
191
|
-
elif isinstance(message, list):
|
|
192
|
-
message = json.dumps(message)
|
|
208
|
+
# Change message to string if we have a dictionary or list.
|
|
209
|
+
message = _serialize_message(message)
|
|
193
210
|
|
|
194
211
|
class ResponseListener(object):
|
|
195
212
|
def __init__(self, topic, result_format):
|
|
@@ -198,11 +215,7 @@ class GOSS(object):
|
|
|
198
215
|
self.result_format = result_format
|
|
199
216
|
|
|
200
217
|
def on_message(self, *args):
|
|
201
|
-
|
|
202
|
-
frame = args[0]
|
|
203
|
-
header, message = frame.headers, frame.body
|
|
204
|
-
else:
|
|
205
|
-
header, message = args[0], args[1]
|
|
218
|
+
header, message = _unpack_stomp_args(*args)
|
|
206
219
|
_log.debug("Internal on message is: {} {}".format(header, message))
|
|
207
220
|
try:
|
|
208
221
|
if self.result_format == "JSON":
|
|
@@ -216,11 +229,7 @@ class GOSS(object):
|
|
|
216
229
|
self.response = dict(error="Invalid json returned", header=header, message=message)
|
|
217
230
|
|
|
218
231
|
def on_error(self, *args):
|
|
219
|
-
|
|
220
|
-
frame = args[0]
|
|
221
|
-
headers, message = frame.headers, frame.body
|
|
222
|
-
else:
|
|
223
|
-
headers, message = args[0], args[1]
|
|
232
|
+
headers, message = _unpack_stomp_args(*args)
|
|
224
233
|
_log.error("ERR: {}".format(headers))
|
|
225
234
|
_log.error("OUR ERROR: {}".format(message))
|
|
226
235
|
|
|
@@ -337,21 +346,13 @@ class GOSS(object):
|
|
|
337
346
|
return self.__token
|
|
338
347
|
|
|
339
348
|
def on_message(self, *args):
|
|
340
|
-
|
|
341
|
-
frame = args[0]
|
|
342
|
-
header, message = frame.headers, frame.body
|
|
343
|
-
else:
|
|
344
|
-
header, message = args[0], args[1]
|
|
349
|
+
header, message = _unpack_stomp_args(*args)
|
|
345
350
|
_log.debug("Internal on message is: {} {}".format(header, message))
|
|
346
351
|
|
|
347
352
|
self.__token = str(message)
|
|
348
353
|
|
|
349
354
|
def on_error(self, *args):
|
|
350
|
-
|
|
351
|
-
frame = args[0]
|
|
352
|
-
headers, message = frame.headers, frame.body
|
|
353
|
-
else:
|
|
354
|
-
headers, message = args[0], args[1]
|
|
355
|
+
headers, message = _unpack_stomp_args(*args)
|
|
355
356
|
_log.error("ERR: {}".format(headers))
|
|
356
357
|
_log.error("OUR ERROR: {}".format(message))
|
|
357
358
|
|
|
@@ -404,9 +405,10 @@ class CallbackRouter(object):
|
|
|
404
405
|
cb, hdrs, msg = self._queue_callerback.get()
|
|
405
406
|
try:
|
|
406
407
|
msg = json.loads(msg)
|
|
407
|
-
except:
|
|
408
|
+
except (TypeError, ValueError):
|
|
409
|
+
# msg was not JSON text (already a dict, or plain string body);
|
|
410
|
+
# pass it through unchanged rather than as a decode failure.
|
|
408
411
|
pass
|
|
409
|
-
# msg = message
|
|
410
412
|
|
|
411
413
|
for c in cb:
|
|
412
414
|
c(hdrs, msg)
|
|
@@ -429,11 +431,7 @@ class CallbackRouter(object):
|
|
|
429
431
|
pass
|
|
430
432
|
|
|
431
433
|
def on_message(self, *args):
|
|
432
|
-
|
|
433
|
-
frame = args[0]
|
|
434
|
-
headers, message = frame.headers, frame.body
|
|
435
|
-
else:
|
|
436
|
-
headers, message = args[0], args[1]
|
|
434
|
+
headers, message = _unpack_stomp_args(*args)
|
|
437
435
|
destination = headers["destination"]
|
|
438
436
|
# _log.debug("Topic map keys are: {keys}".format(keys=self._topics_callback_map.keys()))
|
|
439
437
|
if destination in self._topics_callback_map:
|
|
@@ -442,11 +440,7 @@ class CallbackRouter(object):
|
|
|
442
440
|
_log.error("INVALID DESTINATION {destination}".format(destination=destination))
|
|
443
441
|
|
|
444
442
|
def on_error(self, *args):
|
|
445
|
-
|
|
446
|
-
frame = args[0]
|
|
447
|
-
header, message = frame.headers, frame.body
|
|
448
|
-
else:
|
|
449
|
-
header, message = args[0], args[1]
|
|
443
|
+
header, message = _unpack_stomp_args(*args)
|
|
450
444
|
_log.error("Error in callback router")
|
|
451
445
|
_log.error(header)
|
|
452
446
|
_log.error(message)
|
gridappsd/gridappsd.py
CHANGED
|
@@ -116,29 +116,32 @@ class GridAPPSD(GOSS):
|
|
|
116
116
|
self._simulation_log_topic = t.simulation_log_topic(self._simulation_id)
|
|
117
117
|
return self._simulation_id
|
|
118
118
|
|
|
119
|
-
def
|
|
120
|
-
"""
|
|
121
|
-
|
|
122
|
-
:param status:
|
|
119
|
+
def _set_status(self, status, kind):
|
|
120
|
+
"""Set self._process_status, warning instead of raising on an invalid value.
|
|
121
|
+
|
|
122
|
+
:param status: candidate value for ProcessStatusEnum
|
|
123
|
+
:param kind: human readable label for the warning message, e.g. "application"
|
|
123
124
|
"""
|
|
124
125
|
try:
|
|
125
126
|
self._process_status = ProcessStatusEnum(status)
|
|
126
127
|
except ValueError:
|
|
127
128
|
self.get_logger().warning(
|
|
128
|
-
"Unsuccessful change of
|
|
129
|
+
f"Unsuccessful change of {kind} status." + f"Valid statuses are {ProcessStatusEnum.__members__}."
|
|
129
130
|
)
|
|
130
131
|
|
|
132
|
+
def set_application_status(self, status):
|
|
133
|
+
"""
|
|
134
|
+
Set the application status.
|
|
135
|
+
:param status:
|
|
136
|
+
"""
|
|
137
|
+
self._set_status(status, "application")
|
|
138
|
+
|
|
131
139
|
def set_service_status(self, status):
|
|
132
140
|
"""
|
|
133
141
|
Set the service status.
|
|
134
142
|
:param status:
|
|
135
143
|
"""
|
|
136
|
-
|
|
137
|
-
self._process_status = ProcessStatusEnum(status)
|
|
138
|
-
except ValueError:
|
|
139
|
-
self.get_logger().warning(
|
|
140
|
-
"Unsuccessful change of service status." + f"Valid statuses are {ProcessStatusEnum.__members__}."
|
|
141
|
-
)
|
|
144
|
+
self._set_status(status, "service")
|
|
142
145
|
|
|
143
146
|
def set_simulation_id(self, simulation_id):
|
|
144
147
|
if simulation_id is None:
|
|
@@ -148,12 +151,16 @@ class GridAPPSD(GOSS):
|
|
|
148
151
|
self._simulation_id = simulation_id
|
|
149
152
|
self._simulation_log_topic = t.simulation_log_topic(self._simulation_id)
|
|
150
153
|
|
|
154
|
+
def _get_status(self):
|
|
155
|
+
"""Return self._process_status as its plain string value."""
|
|
156
|
+
return self._process_status.value
|
|
157
|
+
|
|
151
158
|
def get_application_status(self):
|
|
152
159
|
"""
|
|
153
160
|
Return the application status
|
|
154
161
|
:return:
|
|
155
162
|
"""
|
|
156
|
-
return self.
|
|
163
|
+
return self._get_status()
|
|
157
164
|
|
|
158
165
|
def get_application_id(self):
|
|
159
166
|
return utils.get_gridappsd_application_id()
|
|
@@ -163,7 +170,7 @@ class GridAPPSD(GOSS):
|
|
|
163
170
|
Return the service status
|
|
164
171
|
:return:
|
|
165
172
|
"""
|
|
166
|
-
return self.
|
|
173
|
+
return self._get_status()
|
|
167
174
|
|
|
168
175
|
def query_object_types(self, model_id=None):
|
|
169
176
|
"""Allows the caller to query the different object types.
|
gridappsd/simulation.py
CHANGED
|
@@ -58,8 +58,8 @@ class ModelCreationConfig(ConfigBase):
|
|
|
58
58
|
class SimulationArgs(ConfigBase):
|
|
59
59
|
start_time: int = field(default=1655321830)
|
|
60
60
|
duration: int = field(default=300)
|
|
61
|
-
publish_period: int = field(default=None)
|
|
62
|
-
interval: int = field(default=None)
|
|
61
|
+
publish_period: int | None = field(default=None)
|
|
62
|
+
interval: int | None = field(default=None)
|
|
63
63
|
run_realtime: bool = field(default=True)
|
|
64
64
|
pause_after_measurements: bool = field(default=False)
|
|
65
65
|
simulation_name: str = field(default="ieee13nodeckt")
|
|
@@ -75,8 +75,10 @@ class SimulationArgs(ConfigBase):
|
|
|
75
75
|
if not self.publish_period:
|
|
76
76
|
self.publish_period = 60
|
|
77
77
|
if self.publish_period < self.interval:
|
|
78
|
-
raise RuntimeError(
|
|
79
|
-
|
|
78
|
+
raise RuntimeError(
|
|
79
|
+
"A simulation's publishing_period cannot be less than the simulation's timestep "
|
|
80
|
+
"interval. please make the publishing_period >= interval!"
|
|
81
|
+
)
|
|
80
82
|
|
|
81
83
|
|
|
82
84
|
@dataclass
|
|
@@ -215,26 +217,30 @@ class Simulation:
|
|
|
215
217
|
for p in self.__on_start:
|
|
216
218
|
p(self)
|
|
217
219
|
|
|
218
|
-
def
|
|
219
|
-
"""
|
|
220
|
-
|
|
221
|
-
command
|
|
220
|
+
def _send_simulation_command(self, command_name, **command_input):
|
|
221
|
+
"""Send a command to this simulation's input topic.
|
|
222
|
+
|
|
223
|
+
:param command_name: value of the command field sent to the simulation
|
|
224
|
+
:param command_input: when given, nested under the command's "input" key
|
|
225
|
+
"""
|
|
226
|
+
_log.debug("Sending simulation command: {}".format(command_name))
|
|
227
|
+
command = dict(command=command_name)
|
|
228
|
+
if command_input:
|
|
229
|
+
command["input"] = command_input
|
|
222
230
|
self._gapps.send(t.simulation_input_topic(self.simulation_id), json.dumps(command))
|
|
223
231
|
self._running_or_paused = True
|
|
224
232
|
|
|
233
|
+
def pause(self):
|
|
234
|
+
"""Pause simulation"""
|
|
235
|
+
self._send_simulation_command("pause")
|
|
236
|
+
|
|
225
237
|
def stop(self):
|
|
226
238
|
"""Stop the simulation"""
|
|
227
|
-
|
|
228
|
-
command = dict(command="stop")
|
|
229
|
-
self._gapps.send(t.simulation_input_topic(self.simulation_id), json.dumps(command))
|
|
230
|
-
self._running_or_paused = True
|
|
239
|
+
self._send_simulation_command("stop")
|
|
231
240
|
|
|
232
241
|
def resume(self):
|
|
233
242
|
"""Resume the simulation"""
|
|
234
|
-
|
|
235
|
-
command = dict(command="resume")
|
|
236
|
-
self._gapps.send(t.simulation_input_topic(self.simulation_id), json.dumps(command))
|
|
237
|
-
self._running_or_paused = True
|
|
243
|
+
self._send_simulation_command("resume")
|
|
238
244
|
|
|
239
245
|
def run_loop(self):
|
|
240
246
|
"""Loop around the running of the simulation itself.
|
|
@@ -265,9 +271,7 @@ class Simulation:
|
|
|
265
271
|
:param pause_in: number of seconds to run before pausing the simulation
|
|
266
272
|
"""
|
|
267
273
|
_log.debug("Resuming simulation. Will pause after {} seconds".format(pause_in))
|
|
268
|
-
|
|
269
|
-
self._gapps.send(t.simulation_input_topic(self.simulation_id), json.dumps(command))
|
|
270
|
-
self._running_or_paused = True
|
|
274
|
+
self._send_simulation_command("resumePauseAt", pauseIn=pause_in)
|
|
271
275
|
|
|
272
276
|
def add_onmeasurement_callback(self, callback, device_filter=()):
|
|
273
277
|
"""registers an onmeasurment callback to be called when measurements have come through.
|
gridappsd/timeseries.py
CHANGED
|
@@ -46,38 +46,37 @@ class Query:
|
|
|
46
46
|
self.last = n
|
|
47
47
|
return self
|
|
48
48
|
|
|
49
|
-
def
|
|
50
|
-
"""
|
|
49
|
+
def _add_filter(self, operator, value):
|
|
50
|
+
"""Append a single {key, operator: value} filter for the current key.
|
|
51
51
|
|
|
52
|
-
:param
|
|
52
|
+
:param operator: one of "ge", "le", "eq"
|
|
53
|
+
:param value: value to filter on
|
|
53
54
|
"""
|
|
54
55
|
if self.key is None:
|
|
55
56
|
raise ValueError("Key is not specified. Call where_key first.")
|
|
56
|
-
|
|
57
|
-
self.queryFilter.append(obj)
|
|
57
|
+
self.queryFilter.append({"key": self.key, operator: value})
|
|
58
58
|
return self
|
|
59
59
|
|
|
60
|
+
def ge(self, value):
|
|
61
|
+
"""Method to add 'value greater than or equal to' filter to a key.
|
|
62
|
+
|
|
63
|
+
:param value:
|
|
64
|
+
"""
|
|
65
|
+
return self._add_filter("ge", value)
|
|
66
|
+
|
|
60
67
|
def le(self, value):
|
|
61
68
|
"""Method to add 'value less than or equal to' filter to a key.
|
|
62
69
|
|
|
63
70
|
:param value:
|
|
64
71
|
"""
|
|
65
|
-
|
|
66
|
-
raise ValueError("Key is not specified. Call where_key first.")
|
|
67
|
-
obj = {"key": self.key, "le": value}
|
|
68
|
-
self.queryFilter.append(obj)
|
|
69
|
-
return self
|
|
72
|
+
return self._add_filter("le", value)
|
|
70
73
|
|
|
71
74
|
def eq(self, value):
|
|
72
75
|
"""Method to add 'value equal to' filter to a key.
|
|
73
76
|
|
|
74
77
|
:param value:
|
|
75
78
|
"""
|
|
76
|
-
|
|
77
|
-
raise ValueError("Key is not specified. Call where_key first.")
|
|
78
|
-
obj = {"key": self.key, "eq": value}
|
|
79
|
-
self.queryFilter.append(obj)
|
|
80
|
-
return self
|
|
79
|
+
return self._add_filter("eq", value)
|
|
81
80
|
|
|
82
81
|
def between(self, value1, value2):
|
|
83
82
|
"""Method to add 'value between' value1 and value2 filter to a key.
|
|
@@ -85,13 +84,8 @@ class Query:
|
|
|
85
84
|
:param value1: defines 'greater than equal to' filter for key's value
|
|
86
85
|
:param value2: defines 'less than equal to' filter for key's value
|
|
87
86
|
"""
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
obj = {"key": self.key, "ge": value1}
|
|
91
|
-
self.queryFilter.append(obj)
|
|
92
|
-
obj = {"key": self.key, "le": value2}
|
|
93
|
-
self.queryFilter.append(obj)
|
|
94
|
-
return self
|
|
87
|
+
self._add_filter("ge", value1)
|
|
88
|
+
return self._add_filter("le", value2)
|
|
95
89
|
|
|
96
90
|
def where_key(self, key):
|
|
97
91
|
self.key = key
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
gridappsd/__init__.py,sha256=vg4wBmPEfm-4nPXWoW_H8kHXPjQ7E6VIfWQbcdJY1KI,3887
|
|
2
2
|
gridappsd/__main__.py,sha256=-0UJXB-B5EALPmwRoL4nyxHpAucVhE8lWk1TS8OC87E,5073
|
|
3
|
-
gridappsd/app_registration.py,sha256=
|
|
3
|
+
gridappsd/app_registration.py,sha256=P2WvSzj4ijKK92iyJUjE7mY-XPGBDV7JP-YGG3ZBg6M,7728
|
|
4
4
|
gridappsd/difference_builder.py,sha256=-J0Lw3t1srn7VyYrthI_yYY9M2hAN_BRRc01SWRl_GA,5012
|
|
5
5
|
gridappsd/docker_handler.py,sha256=VQVqImWu3Kmu_OBJTkMSuU2bZ9xCd1v3RW1doc9iqzM,30366
|
|
6
|
-
gridappsd/goss.py,sha256=
|
|
7
|
-
gridappsd/gridappsd.py,sha256=
|
|
6
|
+
gridappsd/goss.py,sha256=qMmxllYX__1pvA8tdWvRiUJfJiAxPY0B8aqYelO_KIE,19207
|
|
7
|
+
gridappsd/gridappsd.py,sha256=nfmIKufPAxwQxRn2hfoxrz_eden1yqbJ8kgn0WM3pM0,12821
|
|
8
8
|
gridappsd/houses.py,sha256=9KD3H23qKxjJ0ub0-J2wzo4AhWMu3ulruT-e_cMUwTU,3567
|
|
9
9
|
gridappsd/json_extension.py,sha256=0ByHmNedUDs2W2Ovg4QW-pFErE0OysDxBuYqGof3SUI,2843
|
|
10
10
|
gridappsd/loghandler.py,sha256=Ou4CfVrfAUr3N0zM8i49e0uOn1f81Iu1y8zvx_2ZgQc,2716
|
|
11
11
|
gridappsd/register_app.py,sha256=Jirf-03ufoZRPxyaNy0uMfXJpzGoN_f_P7xiTF9I-kg,2535
|
|
12
|
-
gridappsd/simulation.py,sha256=
|
|
13
|
-
gridappsd/timeseries.py,sha256=
|
|
12
|
+
gridappsd/simulation.py,sha256=bEXkF9UHbL7Zc9ZyyEce2gjZifLHffKigz9wTkZfldU,13643
|
|
13
|
+
gridappsd/timeseries.py,sha256=110liMUJ4Yab8fuJnlCupYGlE6Ms4vSM8aed6kbn1NA,2870
|
|
14
14
|
gridappsd/topics.py,sha256=elkAfNPZWkFLtFRYv58hLu4M2uDFfv5oVw35sxR732k,12053
|
|
15
15
|
gridappsd/utils.py,sha256=M8vNYOdCj9cn2YnIGo8Twa7AneRxyT6G6tUsqu5C8BI,3170
|
|
16
16
|
gridappsd/field_interface/__init__.py,sha256=br3JZKQvMOykeKtUfbFAXQuhPd-t2EjdMUkCn8EH18I,2214
|
|
17
|
-
gridappsd_python-2026.2.
|
|
18
|
-
gridappsd_python-2026.2.
|
|
19
|
-
gridappsd_python-2026.2.
|
|
20
|
-
gridappsd_python-2026.2.
|
|
17
|
+
gridappsd_python-2026.2.1a2.dist-info/METADATA,sha256=JAq4luGIWkqXDHrE2ooI8TkuNw1OWu0nRe5omimyOfw,11239
|
|
18
|
+
gridappsd_python-2026.2.1a2.dist-info/WHEEL,sha256=lCkmxWfQsSc9CfIClYeavTdQeEX2toPqufh9gI35EQA,87
|
|
19
|
+
gridappsd_python-2026.2.1a2.dist-info/entry_points.txt,sha256=s9EgWPiNAeDNWa5-5hA5CKaYLbl0DiAt6yzIUtMLYvQ,97
|
|
20
|
+
gridappsd_python-2026.2.1a2.dist-info/RECORD,,
|
|
File without changes
|
{gridappsd_python-2026.2.1a1.dist-info → gridappsd_python-2026.2.1a2.dist-info}/entry_points.txt
RENAMED
|
File without changes
|