genie-python 25.2.2__tar.gz → 25.8.0__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.
- {genie_python-25.2.2 → genie_python-25.8.0}/.github/workflows/release.yml +1 -1
- {genie_python-25.2.2 → genie_python-25.8.0}/PKG-INFO +1 -2
- {genie_python-25.2.2 → genie_python-25.8.0}/pyproject.toml +1 -1
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/_version.py +16 -3
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/block_names.py +33 -21
- genie_python-25.8.0/src/genie_python/channel_access_exceptions.py +44 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie.py +214 -124
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_advanced.py +25 -17
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_alerts.py +24 -15
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_blockserver.py +18 -10
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_cachannel_wrapper.py +4 -4
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_dae.py +29 -9
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_epics_api.py +106 -43
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_p4p_wrapper.py +2 -2
- genie_python-25.8.0/src/genie_python/genie_pre_post_cmd_manager.py +45 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_pv_connection_protocol.py +3 -3
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_script_checker.py +24 -13
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_simulate_impl.py +71 -24
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_wait_for_move.py +35 -18
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_waitfor.py +6 -7
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/matplotlib_backend/ibex_websocket_backend.py +87 -55
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/mysql_abstraction_layer.py +3 -1
- genie_python-25.8.0/src/genie_python/scanning_instrument_pylint_plugin.py +53 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/utilities.py +71 -47
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python.egg-info/PKG-INFO +1 -2
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python.egg-info/SOURCES.txt +1 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python.egg-info/requires.txt +0 -1
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/py3_test_genie_experimental_data.py +1 -1
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_block_names.py +2 -2
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_genie.py +17 -1
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_genie_alerts.py +1 -2
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_genie_api_setup.py +1 -1
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_genie_blockserver_tests.py +1 -2
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_genie_dae.py +84 -10
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_genie_epics_api.py +1 -1
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_matplotlib_backend.py +2 -3
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_mysql_abstraction_layer.py +1 -2
- genie_python-25.8.0/tests/test_scripts/test.py +2 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_simulation.py +1 -1
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_utilities.py +1 -2
- genie_python-25.2.2/src/genie_python/channel_access_exceptions.py +0 -45
- genie_python-25.2.2/src/genie_python/genie_pre_post_cmd_manager.py +0 -21
- genie_python-25.2.2/src/genie_python/scanning_instrument_pylint_plugin.py +0 -31
- {genie_python-25.2.2 → genie_python-25.8.0}/.git-blame-ignore-revs +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/.gitattributes +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/.github/dependabot.yml +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/.github/workflows/documentation.yml +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/.github/workflows/lint-and-test-nightly.yml +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/.github/workflows/lint_and_test.yml +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/.gitignore +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/LICENSE +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/README.md +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/doc/conf.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/doc/genie_python.rst +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/ruff.toml +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/setup.cfg +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/.pylintrc +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/__init__.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_api_setup.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_change_cache.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_experimental_data.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_logging.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_plot.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_script_generator.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_simulate.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_startup.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/genie_toggle_settings.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/matplotlib_backend/__init__.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/testing_utils/__init__.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/testing_utils/script_checker.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/typings/CaChannel/CaChannel.pyi +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/typings/CaChannel/__init__.pyi +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/typings/CaChannel/_version.pyi +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/typings/CaChannel/ca.pyi +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python/version.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python.egg-info/dependency_links.txt +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/src/genie_python.egg-info/top_level.txt +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/__init__.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_genie_change_cache.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_genie_wait_for_move.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_genie_waitfor.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_script_checker.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_script_generator.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_scripts/error.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_scripts/error_for_script_checker.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_scripts/valid.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_scripts/valid_python_2.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_scripts/valid_to_import.py +0 -0
- {genie_python-25.2.2 → genie_python-25.8.0}/tests/test_utils_with_unicode_literals.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: genie_python
|
|
3
|
-
Version: 25.
|
|
3
|
+
Version: 25.8.0
|
|
4
4
|
Summary: Instrument control & scripting for the ISIS Neutron & Muon source
|
|
5
5
|
Author-email: ISIS Experiment Controls <ISISExperimentControls@stfc.ac.uk>
|
|
6
6
|
Maintainer-email: ISIS Experiment Controls <ISISExperimentControls@stfc.ac.uk>
|
|
@@ -36,7 +36,6 @@ Requires-Dist: myst_parser; extra == "doc"
|
|
|
36
36
|
Requires-Dist: sphinx-autobuild; extra == "doc"
|
|
37
37
|
Provides-Extra: dev
|
|
38
38
|
Requires-Dist: genie_python[doc,plot]; extra == "dev"
|
|
39
|
-
Requires-Dist: mock; extra == "dev"
|
|
40
39
|
Requires-Dist: parameterized; extra == "dev"
|
|
41
40
|
Requires-Dist: pyhamcrest; extra == "dev"
|
|
42
41
|
Requires-Dist: pytest; extra == "dev"
|
|
@@ -72,7 +72,6 @@ doc = [
|
|
|
72
72
|
|
|
73
73
|
dev = [
|
|
74
74
|
"genie_python[plot,doc]",
|
|
75
|
-
"mock",
|
|
76
75
|
"parameterized",
|
|
77
76
|
"pyhamcrest",
|
|
78
77
|
"pytest",
|
|
@@ -118,6 +117,7 @@ reportUnnecessaryIsInstance = true
|
|
|
118
117
|
reportUntypedBaseClass = true
|
|
119
118
|
reportUntypedClassDecorator = true
|
|
120
119
|
reportUntypedFunctionDecorator = true
|
|
120
|
+
stubPath = "src/genie_python/typings"
|
|
121
121
|
|
|
122
122
|
[tool.setuptools_scm]
|
|
123
123
|
version_file = "src/genie_python/_version.py"
|
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
# file generated by setuptools-scm
|
|
2
2
|
# don't change, don't track in version control
|
|
3
3
|
|
|
4
|
-
__all__ = [
|
|
4
|
+
__all__ = [
|
|
5
|
+
"__version__",
|
|
6
|
+
"__version_tuple__",
|
|
7
|
+
"version",
|
|
8
|
+
"version_tuple",
|
|
9
|
+
"__commit_id__",
|
|
10
|
+
"commit_id",
|
|
11
|
+
]
|
|
5
12
|
|
|
6
13
|
TYPE_CHECKING = False
|
|
7
14
|
if TYPE_CHECKING:
|
|
@@ -9,13 +16,19 @@ if TYPE_CHECKING:
|
|
|
9
16
|
from typing import Union
|
|
10
17
|
|
|
11
18
|
VERSION_TUPLE = Tuple[Union[int, str], ...]
|
|
19
|
+
COMMIT_ID = Union[str, None]
|
|
12
20
|
else:
|
|
13
21
|
VERSION_TUPLE = object
|
|
22
|
+
COMMIT_ID = object
|
|
14
23
|
|
|
15
24
|
version: str
|
|
16
25
|
__version__: str
|
|
17
26
|
__version_tuple__: VERSION_TUPLE
|
|
18
27
|
version_tuple: VERSION_TUPLE
|
|
28
|
+
commit_id: COMMIT_ID
|
|
29
|
+
__commit_id__: COMMIT_ID
|
|
19
30
|
|
|
20
|
-
__version__ = version = '25.
|
|
21
|
-
__version_tuple__ = version_tuple = (25,
|
|
31
|
+
__version__ = version = '25.8.0'
|
|
32
|
+
__version_tuple__ = version_tuple = (25, 8, 0)
|
|
33
|
+
|
|
34
|
+
__commit_id__ = commit_id = 'g1fca963b3'
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import zlib
|
|
2
2
|
from keyword import iskeyword
|
|
3
3
|
from threading import RLock, Timer
|
|
4
|
+
from typing import TYPE_CHECKING, Optional
|
|
4
5
|
|
|
5
6
|
from .channel_access_exceptions import UnableToConnectToPVException
|
|
6
7
|
from .genie_blockserver import BLOCK_SERVER_PREFIX, PV_BLOCK_NAMES
|
|
@@ -9,6 +10,9 @@ from .utilities import dehex_decompress_and_dejson
|
|
|
9
10
|
|
|
10
11
|
DELAY_BEFORE_RETRYING_BLOCK_NAMES_PV_ON_FAIL = 30.0
|
|
11
12
|
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from genie_python.genie import PVValue
|
|
15
|
+
|
|
12
16
|
|
|
13
17
|
class BlockNamesManager:
|
|
14
18
|
"""
|
|
@@ -17,23 +21,24 @@ class BlockNamesManager:
|
|
|
17
21
|
|
|
18
22
|
def __init__(
|
|
19
23
|
self,
|
|
20
|
-
block_names,
|
|
21
|
-
delay_before_retry_add_monitor=DELAY_BEFORE_RETRYING_BLOCK_NAMES_PV_ON_FAIL,
|
|
22
|
-
):
|
|
24
|
+
block_names: "BlockNames",
|
|
25
|
+
delay_before_retry_add_monitor: float = DELAY_BEFORE_RETRYING_BLOCK_NAMES_PV_ON_FAIL,
|
|
26
|
+
) -> None:
|
|
23
27
|
"""
|
|
24
28
|
Constructor.
|
|
25
29
|
:param block_names: the block name instance that this manger is managing
|
|
26
|
-
:param delay_before_retry_add_monitor: if the block names pv doesn't exist
|
|
30
|
+
:param delay_before_retry_add_monitor: if the block names pv doesn't exist
|
|
31
|
+
on start the delay before retrying
|
|
27
32
|
"""
|
|
28
33
|
self._block_names = block_names
|
|
29
34
|
self._cancel_monitor_fn = None
|
|
30
35
|
self._delay_before_retry_add_monitor = delay_before_retry_add_monitor
|
|
31
36
|
self._timer = None
|
|
32
|
-
self._pv_name =
|
|
37
|
+
self._pv_name = ""
|
|
33
38
|
# lock used to access _timer or _pv_name
|
|
34
39
|
self.pv_name_lock = RLock()
|
|
35
40
|
|
|
36
|
-
def update_prefix(self, pv_prefix):
|
|
41
|
+
def update_prefix(self, pv_prefix: str) -> None:
|
|
37
42
|
"""
|
|
38
43
|
Update the instrument prefix that the manager is using if it has changed
|
|
39
44
|
:param pv_prefix: new pv prefix
|
|
@@ -45,44 +50,49 @@ class BlockNamesManager:
|
|
|
45
50
|
self._pv_name = new_name
|
|
46
51
|
if self._timer is None:
|
|
47
52
|
self._timer = Timer(0, self._add_monitor)
|
|
48
|
-
self._timer.
|
|
53
|
+
self._timer.daemon = True
|
|
49
54
|
self._timer.start()
|
|
50
55
|
|
|
51
|
-
def _add_monitor(self):
|
|
56
|
+
def _add_monitor(self) -> None:
|
|
52
57
|
"""
|
|
53
|
-
Add a monitor to the block names pv if it is not already monitored,
|
|
54
|
-
pv is monitored don't run.
|
|
58
|
+
Add a monitor to the block names pv if it is not already monitored,
|
|
59
|
+
then reschedule task to add monitor. If the pv is monitored don't run.
|
|
55
60
|
"""
|
|
56
61
|
|
|
57
|
-
# Get PV we should monitor and check whether we need to add new monitor
|
|
62
|
+
# Get PV we should monitor and check whether we need to add new monitor
|
|
63
|
+
# if so cancel old monitor
|
|
58
64
|
with self.pv_name_lock:
|
|
59
65
|
self._timer = None
|
|
60
66
|
# not monitoring the correct pv
|
|
61
67
|
if self._cancel_monitor_fn is not None:
|
|
62
68
|
self._cancel_monitor_fn()
|
|
63
69
|
|
|
64
|
-
# Add new monitor if successful then record monitored pv and pull
|
|
70
|
+
# Add new monitor if successful then record monitored pv and pull
|
|
71
|
+
# first value, otherwise do nothing
|
|
65
72
|
try:
|
|
66
73
|
self._cancel_monitor_fn = CaChannelWrapper.add_monitor(
|
|
67
74
|
self._pv_name, self._update_block_names, to_string=True
|
|
68
75
|
)
|
|
69
76
|
self._update_block_names(
|
|
70
|
-
CaChannelWrapper.get_pv_value(self._pv_name, to_string=True),
|
|
77
|
+
CaChannelWrapper.get_pv_value(self._pv_name, to_string=True), "", ""
|
|
71
78
|
)
|
|
72
79
|
except UnableToConnectToPVException:
|
|
73
|
-
# Schedule next add monitor if needed; i.e. a old pv-prefix change
|
|
80
|
+
# Schedule next add monitor if needed; i.e. a old pv-prefix change
|
|
81
|
+
# was slower the the last pv-prefix
|
|
74
82
|
# and so we are monitoring the wrong pv.
|
|
75
83
|
self._timer = Timer(self._delay_before_retry_add_monitor, self._add_monitor)
|
|
76
|
-
self._timer.
|
|
84
|
+
self._timer.daemon = True
|
|
77
85
|
self._timer.start()
|
|
78
86
|
|
|
79
|
-
def _update_block_names(self, value, _, _1):
|
|
87
|
+
def _update_block_names(self, value: "PVValue", _: Optional[str], _1: Optional[str]) -> None:
|
|
80
88
|
"""
|
|
81
89
|
Update the block names from a pv
|
|
82
90
|
Args:
|
|
83
91
|
:param value: new value of block names pv
|
|
84
|
-
:param _(CaChannel._ca.AlarmSeverity): severity of any alarm
|
|
85
|
-
|
|
92
|
+
:param _(CaChannel._ca.AlarmSeverity): severity of any alarm
|
|
93
|
+
(not used but passed in by monitor)
|
|
94
|
+
:param _1(CaChannel._ca.AlarmCondition): status of the alarm
|
|
95
|
+
(not used but passed in by monitor)
|
|
86
96
|
"""
|
|
87
97
|
# remove old blocks
|
|
88
98
|
for block_name in list(self._block_names.__dict__.keys()):
|
|
@@ -90,6 +100,7 @@ class BlockNamesManager:
|
|
|
90
100
|
|
|
91
101
|
# add new block as attributes to class
|
|
92
102
|
try:
|
|
103
|
+
assert isinstance(value, (str, bytes)), value
|
|
93
104
|
block_names = dehex_decompress_and_dejson(value)
|
|
94
105
|
for name in block_names:
|
|
95
106
|
attribute_name = name
|
|
@@ -103,11 +114,12 @@ class BlockNamesManager:
|
|
|
103
114
|
|
|
104
115
|
class BlockNames:
|
|
105
116
|
"""
|
|
106
|
-
Hold names of the current blocks in config. If block is requested which
|
|
107
|
-
|
|
117
|
+
Hold names of the current blocks in config. If block is requested which
|
|
118
|
+
does not appear in the current config block name returned but message
|
|
119
|
+
printed about it.
|
|
108
120
|
"""
|
|
109
121
|
|
|
110
|
-
def __getattr__(self, attr):
|
|
122
|
+
def __getattr__(self, attr: str) -> str:
|
|
111
123
|
"""
|
|
112
124
|
If an attribute is not set then return name requested
|
|
113
125
|
:param attr: attribute name
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Useful and slightly more explicit exceptions that can be thrown.
|
|
3
|
+
In general catch the super class of these.
|
|
4
|
+
"""
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
class UnableToConnectToPVException(IOError): # noqa N818 Historic name
|
|
8
|
+
"""
|
|
9
|
+
The system is unable to connect to a PV for some reason.
|
|
10
|
+
"""
|
|
11
|
+
|
|
12
|
+
def __init__(self, pv_name: str, err: str) -> None:
|
|
13
|
+
super(UnableToConnectToPVException, self).__init__(
|
|
14
|
+
f"Unable to connect to PV {pv_name}: {err}"
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class InvalidEnumStringException(KeyError): # noqa N818 Historic name
|
|
19
|
+
"""
|
|
20
|
+
The enum string that is trying to be set is not listed in the pv.
|
|
21
|
+
"""
|
|
22
|
+
|
|
23
|
+
def __init__(self, pv_name: str, valid_states: str) -> None:
|
|
24
|
+
super(InvalidEnumStringException, self).__init__(
|
|
25
|
+
f"Invalid string value entered for {pv_name}. Valid strings are {valid_states}"
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
class ReadAccessException(IOError): # noqa N818 Historic name
|
|
30
|
+
"""
|
|
31
|
+
PV exists but its value is unavailable to read.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
def __init__(self, pv_name: str) -> None:
|
|
35
|
+
super(ReadAccessException, self).__init__(f"Read access denied for PV {pv_name}")
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
class WriteAccessException(IOError): # noqa N818 Historic name
|
|
39
|
+
"""
|
|
40
|
+
PV was written to but does not allow writes.
|
|
41
|
+
"""
|
|
42
|
+
|
|
43
|
+
def __init__(self, pv_name: str) -> None:
|
|
44
|
+
super(WriteAccessException, self).__init__(f"Write access denied for PV {pv_name}")
|