genie-python 15.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.
Files changed (45) hide show
  1. genie_python/.pylintrc +539 -0
  2. genie_python/__init__.py +1 -0
  3. genie_python/_version.py +16 -0
  4. genie_python/block_names.py +123 -0
  5. genie_python/channel_access_exceptions.py +45 -0
  6. genie_python/genie.py +2462 -0
  7. genie_python/genie_advanced.py +418 -0
  8. genie_python/genie_alerts.py +195 -0
  9. genie_python/genie_api_setup.py +451 -0
  10. genie_python/genie_blockserver.py +64 -0
  11. genie_python/genie_cachannel_wrapper.py +551 -0
  12. genie_python/genie_change_cache.py +151 -0
  13. genie_python/genie_dae.py +2219 -0
  14. genie_python/genie_epics_api.py +906 -0
  15. genie_python/genie_experimental_data.py +186 -0
  16. genie_python/genie_logging.py +200 -0
  17. genie_python/genie_p4p_wrapper.py +203 -0
  18. genie_python/genie_plot.py +77 -0
  19. genie_python/genie_pre_post_cmd_manager.py +21 -0
  20. genie_python/genie_pv_connection_protocol.py +36 -0
  21. genie_python/genie_script_checker.py +507 -0
  22. genie_python/genie_script_generator.py +212 -0
  23. genie_python/genie_simulate.py +69 -0
  24. genie_python/genie_simulate_impl.py +1265 -0
  25. genie_python/genie_startup.py +29 -0
  26. genie_python/genie_toggle_settings.py +58 -0
  27. genie_python/genie_wait_for_move.py +154 -0
  28. genie_python/genie_waitfor.py +576 -0
  29. genie_python/matplotlib_backend/__init__.py +0 -0
  30. genie_python/matplotlib_backend/ibex_websocket_backend.py +366 -0
  31. genie_python/mysql_abstraction_layer.py +272 -0
  32. genie_python/scanning_instrument_pylint_plugin.py +31 -0
  33. genie_python/testing_utils/__init__.py +4 -0
  34. genie_python/testing_utils/script_checker.py +63 -0
  35. genie_python/typings/CaChannel/CaChannel.pyi +893 -0
  36. genie_python/typings/CaChannel/__init__.pyi +9 -0
  37. genie_python/typings/CaChannel/_version.pyi +6 -0
  38. genie_python/typings/CaChannel/ca.pyi +31 -0
  39. genie_python/utilities.py +406 -0
  40. genie_python/version.py +6 -0
  41. genie_python-15.1.0.dist-info/LICENSE +28 -0
  42. genie_python-15.1.0.dist-info/METADATA +84 -0
  43. genie_python-15.1.0.dist-info/RECORD +45 -0
  44. genie_python-15.1.0.dist-info/WHEEL +5 -0
  45. genie_python-15.1.0.dist-info/top_level.txt +1 -0
@@ -0,0 +1,9 @@
1
+ """
2
+ This type stub file was generated by pyright.
3
+ """
4
+
5
+ from .CaChannel import CaChannel, CaChannelException
6
+
7
+ USE_NUMPY = ...
8
+
9
+ __all__ = ["CaChannel", "CaChannelException"]
@@ -0,0 +1,6 @@
1
+ """
2
+ This type stub file was generated by pyright.
3
+ """
4
+
5
+ version_info = ...
6
+ __version__ = ...
@@ -0,0 +1,31 @@
1
+ """
2
+ This type stub file was generated by pyright.
3
+ """
4
+
5
+ import os
6
+ from enum import Enum
7
+ from typing import TypeAlias
8
+
9
+ from caffi.ca import *
10
+ from caffi.constants import *
11
+ from caffi.macros import *
12
+ from numpy import NDArray
13
+
14
+ from ._ca import *
15
+
16
+ if os.environ.get("CACHANNEL_BACKEND") == "caffi": ...
17
+ else: ...
18
+
19
+ ECA_TIMEOUT: int
20
+ DBR_STRING: str
21
+ DBR_CHAR: str
22
+ DBR_CTRL_ENUM: Enum
23
+ cs_conn: Enum
24
+ CA_OP_CONN_DOWN: int
25
+
26
+ PVBaseValue: TypeAlias = bool | int | float | str
27
+ PVValue: TypeAlias = PVBaseValue | list[PVBaseValue] | NDArray | None
28
+
29
+ def dbr_type_is_CHAR(PVValue) -> bool: ...
30
+ def dbr_type_is_ENUM(PVValue) -> bool: ...
31
+ def dbr_type_is_STRING(PVValue) -> bool: ...
@@ -0,0 +1,406 @@
1
+ from __future__ import absolute_import, print_function
2
+
3
+ import codecs
4
+ import json
5
+ import os
6
+ import re
7
+ import unicodedata
8
+ import zlib
9
+ from builtins import object
10
+ from datetime import timedelta
11
+ from functools import wraps
12
+
13
+ try:
14
+ from nicos import session
15
+
16
+ def check_break(level):
17
+ session.breakpoint(level)
18
+ except ImportError:
19
+
20
+ def check_break(level):
21
+ pass
22
+
23
+
24
+ ## call to make sure we cleanup any subprocesses on process termination
25
+ ## useful to call from e.g. ioc test framework
26
+ ## it creates windows job object with kill on close property, which will be inherited by sub processes
27
+ ## when returned handle is closed, all processes will die
28
+ ## we make sure we detach the Py_HANDLE object from the underlying WIN32 handle
29
+ ## so termination is done by windows and not when pythion obecjt goes out of scope
30
+ def cleanup_subprocs_on_process_exit():
31
+ if os.name == "nt":
32
+ try:
33
+ import win32api
34
+ import win32job
35
+
36
+ h = win32job.CreateJobObject(None, "")
37
+ info = win32job.QueryInformationJobObject(h, win32job.JobObjectExtendedLimitInformation)
38
+ info["BasicLimitInformation"]["LimitFlags"] |= (
39
+ win32job.JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE
40
+ )
41
+ win32job.SetInformationJobObject(h, win32job.JobObjectExtendedLimitInformation, info)
42
+ win32job.AssignProcessToJobObject(h, win32api.GetCurrentProcess())
43
+ h.Detach()
44
+ except Exception as err:
45
+ raise OSError(f"cleanup_subprocs_on_process_exit() failed: {err}")
46
+
47
+
48
+ class PVReadException(Exception):
49
+ """
50
+ Exception to throw when there is a problem reading a PV.
51
+ """
52
+
53
+ def __init__(self, message):
54
+ super(PVReadException, self).__init__(message)
55
+
56
+
57
+ def compress_and_hex(value):
58
+ compr = zlib.compress(bytearray(value, "utf-8"))
59
+ return codecs.encode(compr, "hex_codec")
60
+
61
+
62
+ def dehex_and_decompress(value):
63
+ """
64
+ Dehex and decompress a string and return it
65
+ :param value: compressed hexed string
66
+ :return: value as a strinnng
67
+ """
68
+ try:
69
+ # If it comes as bytes then cast to string
70
+ value = value.decode("utf-8")
71
+ except AttributeError:
72
+ pass
73
+
74
+ return zlib.decompress(bytes.fromhex(value)).decode("utf-8")
75
+
76
+
77
+ def dehex_decompress_and_dejson(value):
78
+ """
79
+ Convert string from zipped hexed json to a python representation
80
+ :param value: value to convert
81
+ :return: python representation of json
82
+ """
83
+ return json.loads(dehex_and_decompress(value))
84
+
85
+
86
+ def waveform_to_string(data):
87
+ output = ""
88
+ for i in data:
89
+ if i == 0:
90
+ break
91
+ if isinstance(i, str):
92
+ output += i
93
+ else:
94
+ output += str(chr(i))
95
+ return output
96
+
97
+
98
+ def convert_string_to_ascii(data):
99
+ """
100
+ Converts a string to be ascii.
101
+
102
+ Args:
103
+ data: the string to convert
104
+
105
+ Returns:
106
+ string: the ascii equivalent
107
+ """
108
+
109
+ def _make_ascii_mappings():
110
+ """
111
+ Create mapping for characters not converted to 7-bit by NFKD.
112
+ """
113
+ mappings_in = [ord(char) for char in "\xd0\xd7\xd8\xde\xdf\xf0\xf8\xfe"]
114
+ mappings_out = "DXOPBoop"
115
+ d = dict(list(zip(mappings_in, mappings_out)))
116
+ d[ord("\xc6")] = "AE"
117
+ d[ord("\xe6")] = "ae"
118
+ return d
119
+
120
+ # Replace all compatibility characters with their equivalents
121
+ normalised = unicodedata.normalize("NFKD", data)
122
+ # Keep non-combining chars only
123
+ extracted = "".join([c for c in normalised if not unicodedata.combining(c)])
124
+ # Finally translate to ascii
125
+ return extracted.translate(_make_ascii_mappings()).encode("ascii", "ignore").decode("utf-8")
126
+
127
+
128
+ def get_correct_path(path):
129
+ """
130
+ Corrects the slashes and escapes any slash characters.
131
+
132
+ Note: does not check whether the file exists.
133
+
134
+ Args:
135
+ path (string): the file path to correct
136
+
137
+ Returns:
138
+ string : the corrected file path
139
+ """
140
+ # Remove any unescaped chars
141
+ path = _convert_to_rawstring(path)
142
+ # Replace '\' with '/'
143
+ path = path.replace("\\", "/").replace("'", "")
144
+ # Remove multiple slashes
145
+ return re.sub("/+", "/", path)
146
+
147
+
148
+ def get_time_delta(seconds, minutes, hours):
149
+ """
150
+ Returns a timedelta representation of the input seconds, minutes and hours. If all parameters are None, then
151
+ None returned, else None parameters are interpreted as 0
152
+ """
153
+ if all(t is None for t in (seconds, minutes, hours)):
154
+ return None
155
+ else:
156
+ num_seconds, num_minutes, num_hours = (
157
+ 0 if t is None else t for t in (seconds, minutes, hours)
158
+ )
159
+ return timedelta(hours=num_hours, minutes=num_minutes, seconds=num_seconds)
160
+
161
+
162
+ def _correct_path_casing_existing(path):
163
+ """
164
+ If the file exists it get the correct path with the correct casing.
165
+ """
166
+ if os.name == "nt":
167
+ try:
168
+ # Correct path case for windows as Python needs correct casing
169
+ # Windows specific stuff
170
+ import win32api
171
+
172
+ return win32api.GetLongPathName(win32api.GetShortPathName(path))
173
+ except Exception as err:
174
+ raise OSError("Invalid file path entered: %s" % err)
175
+ else:
176
+ # Nothing to do for unix
177
+ return path
178
+
179
+
180
+ def _convert_to_rawstring(data):
181
+ escape_dict = {
182
+ "\a": r"\a",
183
+ "\b": r"\b",
184
+ "\c": r"\c",
185
+ "\f": r"\f",
186
+ "\n": r"\n",
187
+ "\r": r"\r",
188
+ "\t": r"\t",
189
+ "\v": r"\v",
190
+ "'": r"\'",
191
+ '"': r"\"",
192
+ }
193
+ raw_string = ""
194
+ for char in data:
195
+ try:
196
+ raw_string += escape_dict[char]
197
+ except KeyError:
198
+ raw_string += char
199
+ return raw_string
200
+
201
+
202
+ def get_correct_filepath_existing(path):
203
+ """
204
+ Corrects the file path to make it OS independent.
205
+
206
+ Args:
207
+ path (string): the file path to correct
208
+
209
+ Returns:
210
+ string : the corrected file path
211
+
212
+ Raises:
213
+ if the directory does not exist.
214
+ """
215
+ path = get_correct_path(path)
216
+ return _correct_path_casing_existing(path)
217
+
218
+
219
+ def crc8(value):
220
+ """
221
+ Generate a CRC 8 from the value (See EPICS\\utils_win32\\master\\src\\crc8.c).
222
+
223
+ Args:
224
+ value: the value to generate a CRC from
225
+
226
+ Returns:
227
+ string: representation of the CRC8 of the value; two characters
228
+
229
+ """
230
+ if value == "":
231
+ return ""
232
+
233
+ crc_size = 8
234
+ maximum_crc_value = 255
235
+ generator = 0x07
236
+
237
+ as_bytes = value.encode("utf-8")
238
+
239
+ crc = 0 # start with 0 so first byte can be 'xored' in
240
+
241
+ for byte in as_bytes:
242
+ crc ^= byte # XOR-in the next input byte
243
+
244
+ for i in range(8):
245
+ # unlike the c code we have to artifically restrict the maximum value wherever it is caluclated
246
+ if (crc >> (crc_size - 1)) & maximum_crc_value != 0:
247
+ crc = ((crc << 1 & maximum_crc_value) ^ generator) & maximum_crc_value
248
+ else:
249
+ crc <<= 1
250
+
251
+ return "{0:02X}".format(crc)
252
+
253
+
254
+ def get_json_pv_value(pv_name, api, attempts=3):
255
+ """
256
+ Get the pv value decompress and convert from JSON.
257
+
258
+ Args:
259
+ pv_name: name of the pv to read
260
+ api: the api to use to read it
261
+ attempts: number of attempts to try to read PV
262
+
263
+ Returns:
264
+ pv value as python objects
265
+
266
+ Raises:
267
+ PVReadException: if value can not be read
268
+
269
+ """
270
+ try:
271
+ raw = api.get_pv_value(pv_name, to_string=True, attempts=attempts)
272
+ except Exception:
273
+ raise PVReadException("Can not read '{0}'".format(pv_name))
274
+
275
+ try:
276
+ raw = dehex_and_decompress(raw)
277
+ except Exception:
278
+ raise PVReadException("Can not decompress '{0}'".format(pv_name))
279
+
280
+ try:
281
+ result = json.loads(raw)
282
+ except Exception:
283
+ raise PVReadException("Can not unmarshal '{0}'".format(pv_name))
284
+
285
+ return result
286
+
287
+
288
+ def remove_field_from_pv(pv):
289
+ """
290
+ Given a PV, return it with any field postfixes removed.
291
+
292
+ examples:
293
+ IN:TEST:FIELD.RVAL -> IN:TEST:FIELD
294
+ IN:TEST:NOFIELD -> IN:TEST:NOFIELD
295
+
296
+ args:
297
+ pv (str): the pv to remove the field from
298
+
299
+ returns:
300
+ (str) the pv name with the field postfix removed
301
+ """
302
+ return pv.split(".")[0] if "." in pv else pv
303
+
304
+
305
+ def check_lowlimit_against_highlimit(lowlimit, highlimit):
306
+ """
307
+ Check the lowlimit is below the highlimit, and warns if this is the case
308
+ """
309
+ if lowlimit is not None and highlimit is not None and lowlimit > highlimit:
310
+ print(
311
+ "WARNING: You have set the lowlimit({}) above the highlimit({})".format(
312
+ lowlimit, highlimit
313
+ )
314
+ )
315
+
316
+
317
+ def require_runstate(runstates):
318
+ """
319
+ Decorator that checks for needed runstates.
320
+ If skip_required_runstates is passed in as a keyword argument to the underlying function then it will be ignore this
321
+ check
322
+ """
323
+ runstates_string = ", ".join(runstates)
324
+
325
+ def _check_runstate(func):
326
+ @wraps(func)
327
+ def _wrapper(self, *args, **kwargs):
328
+ if not kwargs.pop("skip_required_runstates", False):
329
+ run_state = self.get_run_state()
330
+ if run_state not in set(runstates):
331
+ e_string = "{} can only be run in the following runstates: {}".format(
332
+ func.__name__, runstates_string
333
+ )
334
+ raise ValueError(e_string)
335
+ return func(self, *args, **kwargs)
336
+
337
+ return _wrapper
338
+
339
+ return _check_runstate
340
+
341
+
342
+ class EnvironmentDetails(object):
343
+ """
344
+ Details of the computer environment the code is running in.
345
+ """
346
+
347
+ # PV which holds the live instrument list
348
+ INSTRUMENT_LIST_PV = "CS:INSTLIST"
349
+
350
+ # List of instruments dictionary similar to CS:INSTLIST
351
+ DEFAULT_INST_LIST = [
352
+ {"name": "LARMOR"},
353
+ {"name": "ALF"},
354
+ {"name": "DEMO"},
355
+ {"name": "IMAT"},
356
+ {"name": "MUONFE"},
357
+ {"name": "ZOOM"},
358
+ {"name": "IRIS"},
359
+ ]
360
+
361
+ def __init__(self, host_name=None):
362
+ """
363
+ Consturctor.
364
+
365
+ Args:
366
+ host_name: computer host name to use; None to get it from the system
367
+ Returns:
368
+
369
+ """
370
+ import socket
371
+
372
+ if host_name is None:
373
+ self._host_name = socket.gethostname()
374
+ else:
375
+ self._host_name = host_name
376
+
377
+ def get_host_name(self):
378
+ """
379
+ Gets the name of the computer.
380
+
381
+ Returns:
382
+ the host name of the computer
383
+ """
384
+ return self._host_name
385
+
386
+ def get_instrument_list(self, api):
387
+ """
388
+ Get the instrument list.
389
+
390
+ Args:
391
+ api: api to use to get a pv value
392
+
393
+ Returns:
394
+ the current instrument list
395
+ """
396
+ try:
397
+ return get_json_pv_value(self.INSTRUMENT_LIST_PV, api, attempts=1)
398
+ except PVReadException as ex:
399
+ print("Error: {!r}. Using internal instrument list.".format(ex))
400
+ return self.DEFAULT_INST_LIST
401
+
402
+ def get_settings_directory(self):
403
+ default_directory = "C:/Instrument/Settings/config/{}/configurations".format(
404
+ self._host_name
405
+ )
406
+ return os.environ.get("ICPCONFIGROOT", default_directory)
@@ -0,0 +1,6 @@
1
+ from genie_python._version import version
2
+
3
+ __all__ = ["VERSION"]
4
+
5
+ # Shim for backwards-compatibility. Version now auto-generated by setuptools_scm.
6
+ VERSION = version
@@ -0,0 +1,28 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2024, ISIS Experiment Controls Computing
4
+
5
+ Redistribution and use in source and binary forms, with or without
6
+ modification, are permitted provided that the following conditions are met:
7
+
8
+ 1. Redistributions of source code must retain the above copyright notice, this
9
+ list of conditions and the following disclaimer.
10
+
11
+ 2. Redistributions in binary form must reproduce the above copyright notice,
12
+ this list of conditions and the following disclaimer in the documentation
13
+ and/or other materials provided with the distribution.
14
+
15
+ 3. Neither the name of the copyright holder nor the names of its
16
+ contributors may be used to endorse or promote products derived from
17
+ this software without specific prior written permission.
18
+
19
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
23
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
24
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
25
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
26
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
27
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,84 @@
1
+ Metadata-Version: 2.1
2
+ Name: genie_python
3
+ Version: 15.1.0
4
+ Summary: Instrument control & scripting for the ISIS Neutron & Muon source
5
+ Author-email: ISIS Experiment Controls <ISISExperimentControls@stfc.ac.uk>
6
+ Maintainer-email: ISIS Experiment Controls <ISISExperimentControls@stfc.ac.uk>
7
+ License: BSD 3-Clause License
8
+
9
+ Copyright (c) 2024, ISIS Experiment Controls Computing
10
+
11
+ Redistribution and use in source and binary forms, with or without
12
+ modification, are permitted provided that the following conditions are met:
13
+
14
+ 1. Redistributions of source code must retain the above copyright notice, this
15
+ list of conditions and the following disclaimer.
16
+
17
+ 2. Redistributions in binary form must reproduce the above copyright notice,
18
+ this list of conditions and the following disclaimer in the documentation
19
+ and/or other materials provided with the distribution.
20
+
21
+ 3. Neither the name of the copyright holder nor the names of its
22
+ contributors may be used to endorse or promote products derived from
23
+ this software without specific prior written permission.
24
+
25
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
26
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
28
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
29
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
32
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
33
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
34
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35
+
36
+ Project-URL: Homepage, https://github.com/isiscomputinggroup/genie
37
+ Project-URL: Bug Reports, https://github.com/isiscomputinggroup/genie/issues
38
+ Project-URL: Source, https://github.com/isiscomputinggroup/genie
39
+ Classifier: Development Status :: 5 - Production/Stable
40
+ Classifier: Intended Audience :: Developers
41
+ Classifier: License :: OSI Approved :: BSD License
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Requires-Python: >=3.11
44
+ Description-Content-Type: text/markdown
45
+ License-File: LICENSE
46
+ Requires-Dist: CaChannel
47
+ Requires-Dist: graypy
48
+ Requires-Dist: ipython
49
+ Requires-Dist: mysql-connector-python
50
+ Requires-Dist: numpy
51
+ Requires-Dist: p4p
52
+ Requires-Dist: psutil
53
+ Requires-Dist: pylint
54
+ Requires-Dist: pyright
55
+ Requires-Dist: pywin32; platform_system == "Windows"
56
+ Provides-Extra: plot
57
+ Requires-Dist: matplotlib==3.9.2; extra == "plot"
58
+ Requires-Dist: py4j; extra == "plot"
59
+ Requires-Dist: tornado; extra == "plot"
60
+ Provides-Extra: doc
61
+ Requires-Dist: sphinx; extra == "doc"
62
+ Requires-Dist: sphinx_rtd_theme; extra == "doc"
63
+ Requires-Dist: myst_parser; extra == "doc"
64
+ Requires-Dist: sphinx-autobuild; extra == "doc"
65
+ Provides-Extra: dev
66
+ Requires-Dist: genie_python[doc,plot]; extra == "dev"
67
+ Requires-Dist: mock; extra == "dev"
68
+ Requires-Dist: parameterized; extra == "dev"
69
+ Requires-Dist: pyhamcrest; extra == "dev"
70
+ Requires-Dist: pytest; extra == "dev"
71
+ Requires-Dist: pytest-cov; extra == "dev"
72
+ Requires-Dist: ruff>=0.6; extra == "dev"
73
+
74
+ # genie_python
75
+
76
+ Instrument control and scripting library at the ISIS Neutron & Muon source.
77
+
78
+ ---
79
+
80
+ Documentation: https://isiscomputinggroup.github.io/genie/genie_python
81
+
82
+ Source: https://github.com/ISISComputingGroup/genie
83
+
84
+ PyPi: https://pypi.org/project/genie_python/
@@ -0,0 +1,45 @@
1
+ genie_python/.pylintrc,sha256=_DRngouR1JvKbizT3AynF80UTgiXcBkqQ4ogCXNli5o,16340
2
+ genie_python/__init__.py,sha256=_6EmvSY6Mgea6kqFt6iavz4NDcUtXrozECUGUGAjcG0,41
3
+ genie_python/_version.py,sha256=xQcxfj326WFmShY44W_p6r7yXZaPAUVVo1QeQ0vRaRg,413
4
+ genie_python/block_names.py,sha256=-1IolEpAq3XFfesNqnsp50UGEQPHI4N7cU7CYRrIhsU,5044
5
+ genie_python/channel_access_exceptions.py,sha256=5H_DC68sdLOVG0xSOpp1g3vrj7Jt9O5ftD4na3zJY-A,1271
6
+ genie_python/genie.py,sha256=H_EepNCu_ao15RlbcAWnGTaEZpNseBY8n_TobqdUyWo,74834
7
+ genie_python/genie_advanced.py,sha256=DzVPlAM3Dfr7WlAJo6SVk00XzADVlntHcgllBjreET0,11863
8
+ genie_python/genie_alerts.py,sha256=We2o_iSnhO0SWpaG1M-0qyikioAATFJBmyzFVXXzHng,6514
9
+ genie_python/genie_api_setup.py,sha256=OKGPRjprrbBvYgAO4W4r7Wu6K8lTr6-CH5YaFMGa52o,15882
10
+ genie_python/genie_blockserver.py,sha256=FB85zjQ1rHs5sD4cvopNdFrFwG9fnqmXP56uWoEkj5U,2267
11
+ genie_python/genie_cachannel_wrapper.py,sha256=JbiiEkolPW62_OsVSMWQVRqUyXzOUvm8khjOwgiCs9w,19850
12
+ genie_python/genie_change_cache.py,sha256=IcUpAGNE6ajrlQtLwOXX_02LLOg1IHooQZ_962kLt-4,6021
13
+ genie_python/genie_dae.py,sha256=aD9Yc8TYdaJr3qEwzutjko8_vIx2y4rql-m85yEAgps,78084
14
+ genie_python/genie_epics_api.py,sha256=HIR7QdW4KllWWmgljBcSrABr4a52NTNcH2nKCc06bA0,33199
15
+ genie_python/genie_experimental_data.py,sha256=aJsRHgtO2tENfBwnKc0OkND1MEhmTp_kHCPUp8TVL9I,6604
16
+ genie_python/genie_logging.py,sha256=lxobLji-RSXw0onMiSdXs9vQtNdqCBBQPhr85370jjc,6523
17
+ genie_python/genie_p4p_wrapper.py,sha256=eDgfspZ9K9qQUrGkLTCg0jY4TDzKjrt7TsDWBzEQtvU,6921
18
+ genie_python/genie_plot.py,sha256=K0IQIiNGzRImsXqNVd2TxB-uOWUDYL9VHSZEmTVe8oE,2392
19
+ genie_python/genie_pre_post_cmd_manager.py,sha256=fZAHHe9Ay_sG7fKYUSk46v2MXu3ity87tEFJxFcKRhA,787
20
+ genie_python/genie_pv_connection_protocol.py,sha256=f0IzmsBzOCZI47Wn6fgn8fa6R579L6k6CKQggLkOBxo,1048
21
+ genie_python/genie_script_checker.py,sha256=KCzf0OWsonmyIMZGrtWb-FLdhA5tyf4KiJ0HrKOXrB4,19334
22
+ genie_python/genie_script_generator.py,sha256=6J5rujmZ9GWMZ7w76U_Wh7mTnhqkjMrbR70xi_SePaQ,8927
23
+ genie_python/genie_simulate.py,sha256=yoFNnlmEveKaMr4WoY0y2WhlUbjRB8FXlW3bbxPg_5E,2704
24
+ genie_python/genie_simulate_impl.py,sha256=9OJmSPUqUw9Y1R0orobtjn48jQqIJV46zNOt6wcz2XI,44639
25
+ genie_python/genie_startup.py,sha256=AMGU37NYUI3DgffmialtYtzzgHZr-MKfE5KJor63Etk,1023
26
+ genie_python/genie_toggle_settings.py,sha256=jrbFMIS46n4dKrhUqpPlnhiRbyHxKvvndthFoT5ED2w,1771
27
+ genie_python/genie_wait_for_move.py,sha256=_Ihk0vQ2knwuBXcC5FNpbo0beMNO289vn3vqpCt0fYo,6358
28
+ genie_python/genie_waitfor.py,sha256=YtqyNeOe9pKOzKmkMqod5yMPlJRVvsgAZSAjKv9qnGo,22653
29
+ genie_python/mysql_abstraction_layer.py,sha256=1UllAEoCz_Yb6zSuDvIDjfi3wYH7Ep6s00e9niTwNeg,9818
30
+ genie_python/scanning_instrument_pylint_plugin.py,sha256=rJ2Ss4k3O6GQW-fO80qh7HGlEVeN2rSA1ioMETusOos,1174
31
+ genie_python/utilities.py,sha256=_Dn_ieMOU7lxRDuZuy4V3OKMT0d1nS5O8UWKcPqHV18,11181
32
+ genie_python/version.py,sha256=wofn0DmHbgME-tQoevYn8nyKO1D1_td9Xeivy0R6BC0,166
33
+ genie_python/matplotlib_backend/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
34
+ genie_python/matplotlib_backend/ibex_websocket_backend.py,sha256=tvCffygzcay8Y2B6Wxlm-zy59o0snCPOfAtGL7N1LpA,12450
35
+ genie_python/testing_utils/__init__.py,sha256=o47zjk_PG0s2FCASBOvkPkhWdmaMYiz5zHkwY3M5Pig,144
36
+ genie_python/testing_utils/script_checker.py,sha256=QjnFrAt0ZJriKlQzmAbPYpDgJtQE2ovM_KTShKLfOzw,1804
37
+ genie_python/typings/CaChannel/CaChannel.pyi,sha256=yvNHOtZZzfrrOI2ggxkUySXl889xoVerjPt-tfPD64U,42021
38
+ genie_python/typings/CaChannel/__init__.pyi,sha256=XVuVzAQJF8WSbzf0Q1pOOsEX6tAVBB7cjFtwqh-35aw,172
39
+ genie_python/typings/CaChannel/_version.pyi,sha256=g-keGfiquGWTLjf9HR3zCWszAtz6CrMcGT3otGJ6Cb0,92
40
+ genie_python/typings/CaChannel/ca.pyi,sha256=mAAbTk3rAC91ny7x128TaS6-7_nkPCd1YOpvQj-kLRM,665
41
+ genie_python-15.1.0.dist-info/LICENSE,sha256=cASiBLOac74VMKBPq44ijTeGntmlx75qnUavxbZtqN4,1521
42
+ genie_python-15.1.0.dist-info/METADATA,sha256=QPnOEgAfwGK_sJERh6WY2IykusptVwSyt47TtWXIg9o,3738
43
+ genie_python-15.1.0.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
44
+ genie_python-15.1.0.dist-info/top_level.txt,sha256=VdV_RRsxfn--QiaIBZzB5AGVWSkb1LDUtu3b85qTN5s,13
45
+ genie_python-15.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.6.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ genie_python