genie-python 15.1.0rc1__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 (43) hide show
  1. genie_python/.pylintrc +539 -0
  2. genie_python/__init__.py +1 -0
  3. genie_python/block_names.py +123 -0
  4. genie_python/channel_access_exceptions.py +45 -0
  5. genie_python/genie.py +2462 -0
  6. genie_python/genie_advanced.py +418 -0
  7. genie_python/genie_alerts.py +195 -0
  8. genie_python/genie_api_setup.py +451 -0
  9. genie_python/genie_blockserver.py +64 -0
  10. genie_python/genie_cachannel_wrapper.py +545 -0
  11. genie_python/genie_change_cache.py +151 -0
  12. genie_python/genie_dae.py +2218 -0
  13. genie_python/genie_epics_api.py +906 -0
  14. genie_python/genie_experimental_data.py +186 -0
  15. genie_python/genie_logging.py +200 -0
  16. genie_python/genie_p4p_wrapper.py +203 -0
  17. genie_python/genie_plot.py +77 -0
  18. genie_python/genie_pre_post_cmd_manager.py +21 -0
  19. genie_python/genie_pv_connection_protocol.py +36 -0
  20. genie_python/genie_script_checker.py +507 -0
  21. genie_python/genie_script_generator.py +212 -0
  22. genie_python/genie_simulate.py +69 -0
  23. genie_python/genie_simulate_impl.py +1265 -0
  24. genie_python/genie_startup.py +29 -0
  25. genie_python/genie_toggle_settings.py +58 -0
  26. genie_python/genie_wait_for_move.py +154 -0
  27. genie_python/genie_waitfor.py +576 -0
  28. genie_python/matplotlib_backend/__init__.py +0 -0
  29. genie_python/matplotlib_backend/ibex_websocket_backend.py +366 -0
  30. genie_python/mysql_abstraction_layer.py +272 -0
  31. genie_python/run_tests.py +56 -0
  32. genie_python/scanning_instrument_pylint_plugin.py +31 -0
  33. genie_python/typings/CaChannel/CaChannel.pyi +893 -0
  34. genie_python/typings/CaChannel/__init__.pyi +9 -0
  35. genie_python/typings/CaChannel/_version.pyi +6 -0
  36. genie_python/typings/CaChannel/ca.pyi +31 -0
  37. genie_python/utilities.py +406 -0
  38. genie_python/version.py +1 -0
  39. genie_python-15.1.0rc1.dist-info/LICENSE +28 -0
  40. genie_python-15.1.0rc1.dist-info/METADATA +95 -0
  41. genie_python-15.1.0rc1.dist-info/RECORD +43 -0
  42. genie_python-15.1.0rc1.dist-info/WHEEL +5 -0
  43. genie_python-15.1.0rc1.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 @@
1
+ VERSION = "0.0.0.qualifier"
@@ -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,95 @@
1
+ Metadata-Version: 2.1
2
+ Name: genie_python
3
+ Version: 15.1.0rc1
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: caffi
48
+ Requires-Dist: graypy
49
+ Requires-Dist: ipython
50
+ Requires-Dist: mysql-connector-python
51
+ Requires-Dist: numpy
52
+ Requires-Dist: p4p
53
+ Requires-Dist: psutil
54
+ Requires-Dist: pylint
55
+ Requires-Dist: pyright
56
+ Requires-Dist: pywin32 ; platform_system == "Windows"
57
+ Provides-Extra: dev
58
+ Requires-Dist: genie-python[doc,plot] ; extra == 'dev'
59
+ Requires-Dist: mock ; extra == 'dev'
60
+ Requires-Dist: parameterized ; extra == 'dev'
61
+ Requires-Dist: pyhamcrest ; extra == 'dev'
62
+ Requires-Dist: pytest ; extra == 'dev'
63
+ Requires-Dist: pytest-cov ; extra == 'dev'
64
+ Requires-Dist: ruff >=0.6 ; extra == 'dev'
65
+ Provides-Extra: doc
66
+ Requires-Dist: sphinx ; extra == 'doc'
67
+ Requires-Dist: sphinx-rtd-theme ; extra == 'doc'
68
+ Requires-Dist: myst-parser ; extra == 'doc'
69
+ Requires-Dist: sphinx-autobuild ; extra == 'doc'
70
+ Provides-Extra: plot
71
+ Requires-Dist: matplotlib ==3.9.2 ; extra == 'plot'
72
+ Requires-Dist: py4j ; extra == 'plot'
73
+ Requires-Dist: tornado ; extra == 'plot'
74
+
75
+ # genie_python
76
+
77
+ The ISIS Python-based instrument control and scripting library.
78
+
79
+ ## Instrument initialisation
80
+
81
+ By default when setting an instrument the init_default.py file is loaded.
82
+ This file checks for the existence of a folder called C:\Instrument\Settings\config\NDX%INSTNAME%\Python and adds this to the sys path if it does.
83
+ If this path exists and contains a file called init_%INSTNAME%.py, it will load it too.
84
+
85
+ On the NDX any files in C:\Instrument\Settings\config\NDX%INSTNAME%\Python can be added to SVN for safe keeping.
86
+
87
+ Python modules can be imported directly from the C:\Instrument\Settings\config\NDX%INSTNAME%\Python directory. If running on a client it is necessary to have a copy of the Python directory for the instrument being connected to in the correct location.
88
+
89
+ Folders inside the Python directory must have a `__init__.py` file for them to be available to be imported.
90
+
91
+ ## Start-up
92
+ The line "from genie_python import *" in genie_startup is responsible for loading all the genie_python stuff!
93
+ This file also contains code for disabling quickedit and for making genie_python guess the instrument name.
94
+
95
+ As genie_python is running inside IPython we use c.TerminalIPythonApp.exec_files to run genie_start.py, so everything is imported correctly.
@@ -0,0 +1,43 @@
1
+ genie_python/.pylintrc,sha256=_DRngouR1JvKbizT3AynF80UTgiXcBkqQ4ogCXNli5o,16340
2
+ genie_python/__init__.py,sha256=_6EmvSY6Mgea6kqFt6iavz4NDcUtXrozECUGUGAjcG0,41
3
+ genie_python/block_names.py,sha256=-1IolEpAq3XFfesNqnsp50UGEQPHI4N7cU7CYRrIhsU,5044
4
+ genie_python/channel_access_exceptions.py,sha256=5H_DC68sdLOVG0xSOpp1g3vrj7Jt9O5ftD4na3zJY-A,1271
5
+ genie_python/genie.py,sha256=DCRXo1_L-8JaO7XiOWi6sQxLeScd2ycFSrbr5bnbQ2U,74834
6
+ genie_python/genie_advanced.py,sha256=DzVPlAM3Dfr7WlAJo6SVk00XzADVlntHcgllBjreET0,11863
7
+ genie_python/genie_alerts.py,sha256=We2o_iSnhO0SWpaG1M-0qyikioAATFJBmyzFVXXzHng,6514
8
+ genie_python/genie_api_setup.py,sha256=OKGPRjprrbBvYgAO4W4r7Wu6K8lTr6-CH5YaFMGa52o,15882
9
+ genie_python/genie_blockserver.py,sha256=FB85zjQ1rHs5sD4cvopNdFrFwG9fnqmXP56uWoEkj5U,2267
10
+ genie_python/genie_cachannel_wrapper.py,sha256=gApFfCC1zsoYv92gSzRleQTi3WsjjTlB41Sb6SNAuOI,19678
11
+ genie_python/genie_change_cache.py,sha256=IcUpAGNE6ajrlQtLwOXX_02LLOg1IHooQZ_962kLt-4,6021
12
+ genie_python/genie_dae.py,sha256=LA5jzOseNSTM0MQWZ2I83p2O-A7kGiFkW6qka2RY1bY,77953
13
+ genie_python/genie_epics_api.py,sha256=HIR7QdW4KllWWmgljBcSrABr4a52NTNcH2nKCc06bA0,33199
14
+ genie_python/genie_experimental_data.py,sha256=aJsRHgtO2tENfBwnKc0OkND1MEhmTp_kHCPUp8TVL9I,6604
15
+ genie_python/genie_logging.py,sha256=lxobLji-RSXw0onMiSdXs9vQtNdqCBBQPhr85370jjc,6523
16
+ genie_python/genie_p4p_wrapper.py,sha256=eDgfspZ9K9qQUrGkLTCg0jY4TDzKjrt7TsDWBzEQtvU,6921
17
+ genie_python/genie_plot.py,sha256=K0IQIiNGzRImsXqNVd2TxB-uOWUDYL9VHSZEmTVe8oE,2392
18
+ genie_python/genie_pre_post_cmd_manager.py,sha256=fZAHHe9Ay_sG7fKYUSk46v2MXu3ity87tEFJxFcKRhA,787
19
+ genie_python/genie_pv_connection_protocol.py,sha256=f0IzmsBzOCZI47Wn6fgn8fa6R579L6k6CKQggLkOBxo,1048
20
+ genie_python/genie_script_checker.py,sha256=KCzf0OWsonmyIMZGrtWb-FLdhA5tyf4KiJ0HrKOXrB4,19334
21
+ genie_python/genie_script_generator.py,sha256=6J5rujmZ9GWMZ7w76U_Wh7mTnhqkjMrbR70xi_SePaQ,8927
22
+ genie_python/genie_simulate.py,sha256=yoFNnlmEveKaMr4WoY0y2WhlUbjRB8FXlW3bbxPg_5E,2704
23
+ genie_python/genie_simulate_impl.py,sha256=9OJmSPUqUw9Y1R0orobtjn48jQqIJV46zNOt6wcz2XI,44639
24
+ genie_python/genie_startup.py,sha256=AMGU37NYUI3DgffmialtYtzzgHZr-MKfE5KJor63Etk,1023
25
+ genie_python/genie_toggle_settings.py,sha256=jrbFMIS46n4dKrhUqpPlnhiRbyHxKvvndthFoT5ED2w,1771
26
+ genie_python/genie_wait_for_move.py,sha256=_Ihk0vQ2knwuBXcC5FNpbo0beMNO289vn3vqpCt0fYo,6358
27
+ genie_python/genie_waitfor.py,sha256=YtqyNeOe9pKOzKmkMqod5yMPlJRVvsgAZSAjKv9qnGo,22653
28
+ genie_python/mysql_abstraction_layer.py,sha256=1UllAEoCz_Yb6zSuDvIDjfi3wYH7Ep6s00e9niTwNeg,9818
29
+ genie_python/run_tests.py,sha256=VuKtVDdB0mx1doyX0-KEwpZr6oCRIGwE5B_jYCZ_NnY,2009
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=foZqjv1s035uLKjlG_5PkcUFysvR2T31SGW0M_xeo48,28
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/typings/CaChannel/CaChannel.pyi,sha256=yvNHOtZZzfrrOI2ggxkUySXl889xoVerjPt-tfPD64U,42021
36
+ genie_python/typings/CaChannel/__init__.pyi,sha256=XVuVzAQJF8WSbzf0Q1pOOsEX6tAVBB7cjFtwqh-35aw,172
37
+ genie_python/typings/CaChannel/_version.pyi,sha256=g-keGfiquGWTLjf9HR3zCWszAtz6CrMcGT3otGJ6Cb0,92
38
+ genie_python/typings/CaChannel/ca.pyi,sha256=mAAbTk3rAC91ny7x128TaS6-7_nkPCd1YOpvQj-kLRM,665
39
+ genie_python-15.1.0rc1.dist-info/LICENSE,sha256=cASiBLOac74VMKBPq44ijTeGntmlx75qnUavxbZtqN4,1521
40
+ genie_python-15.1.0rc1.dist-info/METADATA,sha256=2mvjmr2NOjeDJLIwibt5xHnopJLdN9GcmlmUgPV3vZk,4781
41
+ genie_python-15.1.0rc1.dist-info/WHEEL,sha256=R06PA3UVYHThwHvxuRWMqaGcr-PuniXahwjmQRFMEkY,91
42
+ genie_python-15.1.0rc1.dist-info/top_level.txt,sha256=VdV_RRsxfn--QiaIBZzB5AGVWSkb1LDUtu3b85qTN5s,13
43
+ genie_python-15.1.0rc1.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (75.5.0)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ genie_python