genie-python 25.2.1.2__tar.gz → 25.2.2__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.
Files changed (88) hide show
  1. genie_python-25.2.2/.github/workflows/lint-and-test-nightly.yml +8 -0
  2. {genie_python-25.2.1.2 → genie_python-25.2.2}/.github/workflows/lint_and_test.yml +2 -2
  3. {genie_python-25.2.1.2 → genie_python-25.2.2}/.github/workflows/release.yml +1 -1
  4. genie_python-25.2.2/PKG-INFO +57 -0
  5. {genie_python-25.2.1.2 → genie_python-25.2.2}/pyproject.toml +4 -3
  6. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/_version.py +9 -4
  7. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie.py +24 -20
  8. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_cachannel_wrapper.py +22 -2
  9. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_dae.py +2 -5
  10. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_epics_api.py +10 -2
  11. genie_python-25.2.2/src/genie_python.egg-info/PKG-INFO +57 -0
  12. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python.egg-info/SOURCES.txt +1 -0
  13. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python.egg-info/requires.txt +1 -1
  14. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_genie_dae.py +4 -5
  15. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_genie_epics_api.py +64 -23
  16. genie_python-25.2.1.2/PKG-INFO +0 -84
  17. genie_python-25.2.1.2/src/genie_python.egg-info/PKG-INFO +0 -84
  18. {genie_python-25.2.1.2 → genie_python-25.2.2}/.git-blame-ignore-revs +0 -0
  19. {genie_python-25.2.1.2 → genie_python-25.2.2}/.gitattributes +0 -0
  20. {genie_python-25.2.1.2 → genie_python-25.2.2}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  21. {genie_python-25.2.1.2 → genie_python-25.2.2}/.github/dependabot.yml +0 -0
  22. {genie_python-25.2.1.2 → genie_python-25.2.2}/.github/workflows/documentation.yml +0 -0
  23. {genie_python-25.2.1.2 → genie_python-25.2.2}/.gitignore +0 -0
  24. {genie_python-25.2.1.2 → genie_python-25.2.2}/LICENSE +0 -0
  25. {genie_python-25.2.1.2 → genie_python-25.2.2}/README.md +0 -0
  26. {genie_python-25.2.1.2 → genie_python-25.2.2}/doc/conf.py +0 -0
  27. {genie_python-25.2.1.2 → genie_python-25.2.2}/doc/genie_python.rst +0 -0
  28. {genie_python-25.2.1.2 → genie_python-25.2.2}/ruff.toml +0 -0
  29. {genie_python-25.2.1.2 → genie_python-25.2.2}/setup.cfg +0 -0
  30. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/.pylintrc +0 -0
  31. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/__init__.py +0 -0
  32. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/block_names.py +0 -0
  33. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/channel_access_exceptions.py +0 -0
  34. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_advanced.py +0 -0
  35. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_alerts.py +0 -0
  36. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_api_setup.py +0 -0
  37. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_blockserver.py +0 -0
  38. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_change_cache.py +0 -0
  39. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_experimental_data.py +0 -0
  40. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_logging.py +0 -0
  41. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_p4p_wrapper.py +0 -0
  42. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_plot.py +0 -0
  43. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_pre_post_cmd_manager.py +0 -0
  44. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_pv_connection_protocol.py +0 -0
  45. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_script_checker.py +0 -0
  46. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_script_generator.py +0 -0
  47. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_simulate.py +0 -0
  48. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_simulate_impl.py +0 -0
  49. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_startup.py +0 -0
  50. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_toggle_settings.py +0 -0
  51. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_wait_for_move.py +0 -0
  52. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/genie_waitfor.py +0 -0
  53. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/matplotlib_backend/__init__.py +0 -0
  54. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/matplotlib_backend/ibex_websocket_backend.py +0 -0
  55. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/mysql_abstraction_layer.py +0 -0
  56. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/scanning_instrument_pylint_plugin.py +0 -0
  57. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/testing_utils/__init__.py +0 -0
  58. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/testing_utils/script_checker.py +0 -0
  59. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/typings/CaChannel/CaChannel.pyi +0 -0
  60. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/typings/CaChannel/__init__.pyi +0 -0
  61. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/typings/CaChannel/_version.pyi +0 -0
  62. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/typings/CaChannel/ca.pyi +0 -0
  63. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/utilities.py +0 -0
  64. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python/version.py +0 -0
  65. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python.egg-info/dependency_links.txt +0 -0
  66. {genie_python-25.2.1.2 → genie_python-25.2.2}/src/genie_python.egg-info/top_level.txt +0 -0
  67. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/__init__.py +0 -0
  68. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/py3_test_genie_experimental_data.py +0 -0
  69. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_block_names.py +0 -0
  70. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_genie.py +0 -0
  71. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_genie_alerts.py +0 -0
  72. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_genie_api_setup.py +0 -0
  73. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_genie_blockserver_tests.py +0 -0
  74. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_genie_change_cache.py +0 -0
  75. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_genie_wait_for_move.py +0 -0
  76. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_genie_waitfor.py +0 -0
  77. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_matplotlib_backend.py +0 -0
  78. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_mysql_abstraction_layer.py +0 -0
  79. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_script_checker.py +0 -0
  80. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_script_generator.py +0 -0
  81. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_scripts/error.py +0 -0
  82. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_scripts/error_for_script_checker.py +0 -0
  83. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_scripts/valid.py +0 -0
  84. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_scripts/valid_python_2.py +0 -0
  85. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_scripts/valid_to_import.py +0 -0
  86. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_simulation.py +0 -0
  87. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_utilities.py +0 -0
  88. {genie_python-25.2.1.2 → genie_python-25.2.2}/tests/test_utils_with_unicode_literals.py +0 -0
@@ -0,0 +1,8 @@
1
+ name: lint-and-test-nightly
2
+ on:
3
+ schedule:
4
+ - cron: "0 0 * * *"
5
+
6
+ jobs:
7
+ lint-and-test-nightly:
8
+ uses: ./.github/workflows/lint_and_test.yml
@@ -7,13 +7,13 @@ jobs:
7
7
  uses: ISISComputingGroup/reusable-workflows/.github/workflows/linters.yml@main
8
8
  with:
9
9
  compare-branch: origin/main
10
- python-ver: '3.11'
10
+ python-ver: '3.12'
11
11
  unit-tests:
12
12
  runs-on: ${{ matrix.os }}
13
13
  strategy:
14
14
  matrix:
15
15
  os: ["ubuntu-latest", "windows-latest"]
16
- version: ['3.11']
16
+ version: ['3.11', '3.12']
17
17
  fail-fast: false
18
18
  steps:
19
19
  - uses: actions/checkout@v4
@@ -16,7 +16,7 @@ jobs:
16
16
  - name: Set up Python
17
17
  uses: actions/setup-python@v5
18
18
  with:
19
- python-version: "3.11"
19
+ python-version: "3.12"
20
20
  - name: Install pypa/build
21
21
  run: >-
22
22
  python3 -m
@@ -0,0 +1,57 @@
1
+ Metadata-Version: 2.4
2
+ Name: genie_python
3
+ Version: 25.2.2
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-Expression: BSD-3-Clause
8
+ Project-URL: Homepage, https://github.com/isiscomputinggroup/genie
9
+ Project-URL: Bug Reports, https://github.com/isiscomputinggroup/genie/issues
10
+ Project-URL: Source, https://github.com/isiscomputinggroup/genie
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.11
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: CaChannel
19
+ Requires-Dist: graypy
20
+ Requires-Dist: ipython
21
+ Requires-Dist: mysql-connector-python
22
+ Requires-Dist: numpy
23
+ Requires-Dist: p4p
24
+ Requires-Dist: psutil
25
+ Requires-Dist: pylint
26
+ Requires-Dist: pyright
27
+ Requires-Dist: pywin32; platform_system == "Windows"
28
+ Provides-Extra: plot
29
+ Requires-Dist: matplotlib==3.10.1; extra == "plot"
30
+ Requires-Dist: py4j; extra == "plot"
31
+ Requires-Dist: tornado; extra == "plot"
32
+ Provides-Extra: doc
33
+ Requires-Dist: sphinx; extra == "doc"
34
+ Requires-Dist: sphinx_rtd_theme; extra == "doc"
35
+ Requires-Dist: myst_parser; extra == "doc"
36
+ Requires-Dist: sphinx-autobuild; extra == "doc"
37
+ Provides-Extra: dev
38
+ Requires-Dist: genie_python[doc,plot]; extra == "dev"
39
+ Requires-Dist: mock; extra == "dev"
40
+ Requires-Dist: parameterized; extra == "dev"
41
+ Requires-Dist: pyhamcrest; extra == "dev"
42
+ Requires-Dist: pytest; extra == "dev"
43
+ Requires-Dist: pytest-cov; extra == "dev"
44
+ Requires-Dist: ruff>=0.6; extra == "dev"
45
+ Dynamic: license-file
46
+
47
+ # genie_python
48
+
49
+ Instrument control and scripting library at the ISIS Neutron & Muon source.
50
+
51
+ ---
52
+
53
+ Documentation: https://isiscomputinggroup.github.io/genie/genie_python
54
+
55
+ Source: https://github.com/ISISComputingGroup/genie
56
+
57
+ PyPi: https://pypi.org/project/genie_python/
@@ -9,7 +9,8 @@ dynamic = ["version"]
9
9
  description = "Instrument control & scripting for the ISIS Neutron & Muon source"
10
10
  readme = "README.md"
11
11
  requires-python = ">=3.11"
12
- license = {file = "LICENSE"}
12
+ license = "BSD-3-Clause"
13
+ license-files = ["LICENSE"]
13
14
 
14
15
  authors = [
15
16
  {name = "ISIS Experiment Controls", email = "ISISExperimentControls@stfc.ac.uk" }
@@ -21,8 +22,8 @@ maintainers = [
21
22
  classifiers = [
22
23
  "Development Status :: 5 - Production/Stable",
23
24
  "Intended Audience :: Developers",
24
- "License :: OSI Approved :: BSD License",
25
25
  "Programming Language :: Python :: 3.11",
26
+ "Programming Language :: Python :: 3.12",
26
27
  ]
27
28
 
28
29
  dependencies = [
@@ -55,7 +56,7 @@ dependencies = [
55
56
  # - It depends on a couple of heavyweight libs (py4j and tornado) that aren't necessary otherwise
56
57
  plot = [
57
58
  # When updating, check plotting works in GUI. Must keep pinned to a specific, tested version.
58
- "matplotlib==3.9.2",
59
+ "matplotlib==3.10.1",
59
60
  # Python <-> Java communication, to spawn matplotlib plots in GUI
60
61
  "py4j",
61
62
  # Tornado webserver used by custom backend
@@ -1,8 +1,13 @@
1
- # file generated by setuptools_scm
1
+ # file generated by setuptools-scm
2
2
  # don't change, don't track in version control
3
+
4
+ __all__ = ["__version__", "__version_tuple__", "version", "version_tuple"]
5
+
3
6
  TYPE_CHECKING = False
4
7
  if TYPE_CHECKING:
5
- from typing import Tuple, Union
8
+ from typing import Tuple
9
+ from typing import Union
10
+
6
11
  VERSION_TUPLE = Tuple[Union[int, str], ...]
7
12
  else:
8
13
  VERSION_TUPLE = object
@@ -12,5 +17,5 @@ __version__: str
12
17
  __version_tuple__: VERSION_TUPLE
13
18
  version_tuple: VERSION_TUPLE
14
19
 
15
- __version__ = version = '25.2.1.2'
16
- __version_tuple__ = version_tuple = (25, 2, 1, 2)
20
+ __version__ = version = '25.2.2'
21
+ __version_tuple__ = version_tuple = (25, 2, 2)
@@ -1,7 +1,8 @@
1
1
  from __future__ import absolute_import, print_function
2
2
 
3
3
  import datetime
4
- import imp
4
+ import importlib
5
+ import importlib.util
5
6
  import os
6
7
  import re
7
8
  import sys
@@ -14,7 +15,6 @@ import numpy.typing as npt
14
15
 
15
16
  from genie_python.genie_api_setup import __api as _genie_api
16
17
 
17
- os.environ["EPICS_CA_MAX_ARRAY_BYTES"] = "20000000"
18
18
  os.environ["FROM_IBEX"] = str(False)
19
19
 
20
20
  # for user import this functionality so they can do g.adv and g.sim
@@ -24,7 +24,7 @@ import genie_python.genie_simulate as sim # noqa F401
24
24
  import genie_python.genie_toggle_settings as toggle # noqa F401
25
25
 
26
26
  # Import required for g.my_pv_prefix
27
- from genie_python.genie_api_setup import (
27
+ from genie_python.genie_api_setup import ( # noqa E402
28
28
  get_user_script_dir,
29
29
  helparglist,
30
30
  log_command_and_handle_exception,
@@ -32,27 +32,29 @@ from genie_python.genie_api_setup import (
32
32
  set_user_script_dir,
33
33
  usercommand,
34
34
  )
35
- from genie_python.genie_script_checker import ScriptChecker
36
- from genie_python.genie_toggle_settings import ToggleSettings
37
- from genie_python.utilities import (
35
+ from genie_python.genie_script_checker import ScriptChecker # noqa E402
36
+ from genie_python.genie_toggle_settings import ToggleSettings # noqa E402
37
+ from genie_python.utilities import ( # noqa E402
38
38
  EnvironmentDetails,
39
39
  check_lowlimit_against_highlimit,
40
40
  get_correct_filepath_existing,
41
41
  get_correct_path,
42
42
  )
43
- from genie_python.version import VERSION
43
+ from genie_python.version import VERSION # noqa E402
44
44
 
45
45
  PVBaseValue = bool | int | float | str
46
46
  PVValue = PVBaseValue | list[PVBaseValue] | npt.NDArray | None
47
47
 
48
48
  print("\ngenie_python version " + VERSION)
49
49
 
50
- SUPPORTED_PYTHON_VERSION = (3, 11, 9)
51
- if sys.version_info[0:3] != SUPPORTED_PYTHON_VERSION[0:3]:
50
+ MIN_SUPPORTED_PYTHON_VERSION = (3, 11, 0)
51
+ MAX_SUPPORTED_PYTHON_VERSION = (3, 12, 999)
52
+
53
+ if not (MIN_SUPPORTED_PYTHON_VERSION <= sys.version_info[0:3] <= MAX_SUPPORTED_PYTHON_VERSION):
52
54
  message = (
53
- "WARNING: genie_python only guarantees support for "
54
- "Python version {0[0]}.{0[1]}.{0[2]}, you are running {1}".format(
55
- SUPPORTED_PYTHON_VERSION, sys.version
55
+ "WARNING: genie_python only supports "
56
+ "python versions {0[0]}.{0[1]}.{0[2]} to {1[0]}.{1[1]}.{1[2]}, you are running {2}".format(
57
+ MIN_SUPPORTED_PYTHON_VERSION, MAX_SUPPORTED_PYTHON_VERSION, sys.version
56
58
  )
57
59
  )
58
60
  print(message, file=sys.stderr)
@@ -1460,14 +1462,16 @@ def __load_module(name: str, directory: str) -> types.ModuleType:
1460
1462
  """
1461
1463
  This will reload the module if it has already been loaded.
1462
1464
  """
1463
- fpath = None
1464
- try:
1465
- fpath, pathname, description = imp.find_module(name, [directory])
1466
- return imp.load_module(name, fpath, pathname, description)
1467
- finally:
1468
- # Since we may exit via an exception, close fpath explicitly.
1469
- if fpath is not None:
1470
- fpath.close()
1465
+ spec = importlib.util.find_spec(name, directory)
1466
+ if spec is None:
1467
+ raise ValueError(f"Cannot find spec for module {name} in {directory}")
1468
+ module = importlib.util.module_from_spec(spec)
1469
+ sys.modules[name] = module
1470
+ loader = spec.loader
1471
+ if loader is None:
1472
+ raise ValueError("Module spec has no loader")
1473
+ loader.exec_module(module)
1474
+ return module
1471
1475
 
1472
1476
 
1473
1477
  @log_command_and_handle_exception
@@ -19,6 +19,7 @@ try:
19
19
  AlarmSeverity,
20
20
  dbf_type_to_DBR_STS,
21
21
  dbf_type_to_DBR_TIME,
22
+ dbf_type_to_text,
22
23
  )
23
24
  except ImportError:
24
25
  # Note: caffi dynamically added to dependencies by CaChannel if not using built backend.
@@ -27,6 +28,7 @@ except ImportError:
27
28
  AlarmSeverity,
28
29
  dbf_type_to_DBR_STS,
29
30
  dbf_type_to_DBR_TIME,
31
+ dbf_type_to_text,
30
32
  )
31
33
 
32
34
  if TYPE_CHECKING:
@@ -252,8 +254,10 @@ class CaChannelWrapper(object):
252
254
  chan = pv_map[name]
253
255
  else:
254
256
  chan = CaChannel(name)
255
- # noinspection PyTypeChecker
256
- CaChannelWrapper.installHandlers(chan)
257
+ # do not install handlers if server
258
+ if os.getenv("EPICS_CAS_INTF_ADDR_LIST") is None:
259
+ # noinspection PyTypeChecker
260
+ CaChannelWrapper.installHandlers(chan)
257
261
  chan.setTimeout(timeout)
258
262
  # Try to connect - throws if cannot
259
263
  CaChannelWrapper.connect_to_pv(chan)
@@ -549,3 +553,19 @@ class CaChannelWrapper(object):
549
553
 
550
554
  if not event.is_set():
551
555
  raise UnableToConnectToPVException(chan.name(), "Pend event timeout")
556
+
557
+ @staticmethod
558
+ def dbf_type_to_string(typ: int) -> str:
559
+ """
560
+ Return DB field type as text
561
+
562
+ Args:
563
+ typ: DB field type as integer
564
+
565
+ Returns: DB field type as string
566
+ Valid values:
567
+ DBF_STRING, DBF_CHAR, DBF_UCHAR, DBF_SHORT, DBF_USHORT, DBF_LONG,
568
+ DBF_ULONG, DBF_INT64, DBF_UINT64, DBF_FLOAT, DBF_DOUBLE, DBF_ENUM,
569
+ DBF_MENU, DBF_DEVICE, DBF_INLINK, DBF_OUTLINK, DBF_FWDLINK, DBF_NOACCESS
570
+ """
571
+ return dbf_type_to_text(typ)
@@ -458,9 +458,7 @@ class Dae(object):
458
458
  prepost: run pre and post commands [optional]
459
459
  """
460
460
  if self.get_run_state() == "ENDING" and not immediate:
461
- print(
462
- "Please specify the 'immediate=True' flag to end a run " "while in the ENDING state"
463
- )
461
+ print("Please specify the 'immediate=True' flag to end a run while in the ENDING state")
464
462
  return
465
463
 
466
464
  run_number = self.get_run_number()
@@ -601,8 +599,7 @@ class Dae(object):
601
599
  """
602
600
  if self.get_run_state() == "PAUSING" and not immediate:
603
601
  print(
604
- "Please specify the 'immediate=True' flag "
605
- "to pause a run while in the PAUSING state"
602
+ "Please specify the 'immediate=True' flag to pause a run while in the PAUSING state"
606
603
  )
607
604
  return
608
605
 
@@ -4,6 +4,7 @@ import contextlib
4
4
  import os
5
5
  import re
6
6
  import sys
7
+ import typing
7
8
  import urllib.parse
8
9
  import urllib.request
9
10
  from builtins import str
@@ -560,7 +561,7 @@ class API(object):
560
561
  for name, value in temp:
561
562
  self.set_block_value(name, value)
562
563
 
563
- def get_block_units(self, block_name: str) -> str:
564
+ def get_block_units(self, block_name: str) -> str | None:
564
565
  """
565
566
  Get the physical measurement units associated with a block name.
566
567
 
@@ -572,6 +573,7 @@ class API(object):
572
573
  -------
573
574
  units of the block
574
575
  """
576
+
575
577
  pv_name = self.get_pv_from_block(block_name)
576
578
  if "." in pv_name:
577
579
  # Remove any headers
@@ -588,7 +590,13 @@ class API(object):
588
590
  )
589
591
  )
590
592
 
591
- return Wrapper.get_pv_value(unit_name)
593
+ field_type = Wrapper.dbf_type_to_string(Wrapper.get_chan(pv_name).field_type())
594
+
595
+ if field_type in ["DBF_STRING", "DBF_CHAR", "DBF_UCHAR", "DBF_ENUM"]:
596
+ return None
597
+ # Only return block units if PV field type is _not_ STRING, CHAR, UCHAR or ENUM
598
+ # as they're unlikely to have .EGU fields
599
+ return typing.cast(str | None, Wrapper.get_pv_value(unit_name))
592
600
 
593
601
  def _get_pars(
594
602
  self, pv_prefix_identifier: str, get_names_from_blockserver: Callable[[], list[str]]
@@ -0,0 +1,57 @@
1
+ Metadata-Version: 2.4
2
+ Name: genie_python
3
+ Version: 25.2.2
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-Expression: BSD-3-Clause
8
+ Project-URL: Homepage, https://github.com/isiscomputinggroup/genie
9
+ Project-URL: Bug Reports, https://github.com/isiscomputinggroup/genie/issues
10
+ Project-URL: Source, https://github.com/isiscomputinggroup/genie
11
+ Classifier: Development Status :: 5 - Production/Stable
12
+ Classifier: Intended Audience :: Developers
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.11
16
+ Description-Content-Type: text/markdown
17
+ License-File: LICENSE
18
+ Requires-Dist: CaChannel
19
+ Requires-Dist: graypy
20
+ Requires-Dist: ipython
21
+ Requires-Dist: mysql-connector-python
22
+ Requires-Dist: numpy
23
+ Requires-Dist: p4p
24
+ Requires-Dist: psutil
25
+ Requires-Dist: pylint
26
+ Requires-Dist: pyright
27
+ Requires-Dist: pywin32; platform_system == "Windows"
28
+ Provides-Extra: plot
29
+ Requires-Dist: matplotlib==3.10.1; extra == "plot"
30
+ Requires-Dist: py4j; extra == "plot"
31
+ Requires-Dist: tornado; extra == "plot"
32
+ Provides-Extra: doc
33
+ Requires-Dist: sphinx; extra == "doc"
34
+ Requires-Dist: sphinx_rtd_theme; extra == "doc"
35
+ Requires-Dist: myst_parser; extra == "doc"
36
+ Requires-Dist: sphinx-autobuild; extra == "doc"
37
+ Provides-Extra: dev
38
+ Requires-Dist: genie_python[doc,plot]; extra == "dev"
39
+ Requires-Dist: mock; extra == "dev"
40
+ Requires-Dist: parameterized; extra == "dev"
41
+ Requires-Dist: pyhamcrest; extra == "dev"
42
+ Requires-Dist: pytest; extra == "dev"
43
+ Requires-Dist: pytest-cov; extra == "dev"
44
+ Requires-Dist: ruff>=0.6; extra == "dev"
45
+ Dynamic: license-file
46
+
47
+ # genie_python
48
+
49
+ Instrument control and scripting library at the ISIS Neutron & Muon source.
50
+
51
+ ---
52
+
53
+ Documentation: https://isiscomputinggroup.github.io/genie/genie_python
54
+
55
+ Source: https://github.com/ISISComputingGroup/genie
56
+
57
+ PyPi: https://pypi.org/project/genie_python/
@@ -8,6 +8,7 @@ ruff.toml
8
8
  .github/PULL_REQUEST_TEMPLATE.md
9
9
  .github/dependabot.yml
10
10
  .github/workflows/documentation.yml
11
+ .github/workflows/lint-and-test-nightly.yml
11
12
  .github/workflows/lint_and_test.yml
12
13
  .github/workflows/release.yml
13
14
  doc/conf.py
@@ -27,6 +27,6 @@ myst_parser
27
27
  sphinx-autobuild
28
28
 
29
29
  [plot]
30
- matplotlib==3.9.2
30
+ matplotlib==3.10.1
31
31
  py4j
32
32
  tornado
@@ -285,7 +285,7 @@ class TestGenieDAE(unittest.TestCase):
285
285
  ):
286
286
  self.dae.in_change = False
287
287
 
288
- self.assertRaisesRegexp(ValueError, "Change has already finished", self.dae.change_finish)
288
+ self.assertRaisesRegex(ValueError, "Change has already finished", self.dae.change_finish)
289
289
 
290
290
  def test_GIVEN_in_transition_WHEN_change_finish_called_THEN_value_error_with_correct_message_thrown(
291
291
  self,
@@ -293,10 +293,9 @@ class TestGenieDAE(unittest.TestCase):
293
293
  self.dae.in_change = True
294
294
  self.dae.in_transition = MagicMock(return_value=True)
295
295
 
296
- self.assertRaisesRegexp(
296
+ self.assertRaisesRegex(
297
297
  ValueError,
298
- "Another DAE change operation is currently in progress - values will be "
299
- "inconsistent",
298
+ "Another DAE change operation is currently in progress - values will be inconsistent",
300
299
  self.dae.change_finish,
301
300
  )
302
301
 
@@ -306,7 +305,7 @@ class TestGenieDAE(unittest.TestCase):
306
305
  self.dae.in_change = True
307
306
  self.dae.get_run_state = MagicMock(return_value="RUNNING")
308
307
 
309
- self.assertRaisesRegexp(
308
+ self.assertRaisesRegex(
310
309
  ValueError,
311
310
  "Instrument must be in SETUP when changing settings!",
312
311
  self.dae.change_finish,
@@ -23,6 +23,7 @@ from mock import MagicMock, patch
23
23
  from parameterized import parameterized
24
24
 
25
25
  from genie_python.channel_access_exceptions import UnableToConnectToPVException
26
+ from genie_python.genie_cachannel_wrapper import CaChannelWrapper as Wrapper
26
27
  from genie_python.genie_epics_api import API
27
28
 
28
29
 
@@ -419,7 +420,9 @@ class TestPvMethods(unittest.TestCase):
419
420
  raise
420
421
 
421
422
  @patch("genie_python.genie_epics_api.Wrapper")
422
- def test_GIVEN_mock_pv_WHEN_get_local_pv_value_THEN_pv_is_returned(self, pv_wrapper_mock):
423
+ def test_GIVEN_mock_pv_WHEN_get_local_pv_value_THEN_pv_is_returned(
424
+ self, pv_wrapper_mock: MagicMock
425
+ ):
423
426
  expected_value = 10
424
427
  pv_wrapper_mock.pv_exists.return_value = True
425
428
  pv_wrapper_mock.get_pv_value.return_value = expected_value
@@ -433,7 +436,7 @@ class TestPvMethods(unittest.TestCase):
433
436
 
434
437
  @patch("genie_python.genie_epics_api.Wrapper")
435
438
  def test_GIVEN_mock_pv_WHEN_get_value_of_local_pv_with_local_prefix_on_start_THEN_pv_is_returned_and_pv_asked_for_has_only_one_prefix(
436
- self, pv_wrapper_mock
439
+ self, pv_wrapper_mock: MagicMock
437
440
  ):
438
441
  expected_value = 10
439
442
  pv_wrapper_mock.pv_exists.return_value = True
@@ -447,7 +450,9 @@ class TestPvMethods(unittest.TestCase):
447
450
  pv_wrapper_mock.get_pv_value.assert_called_with(expected_pv_name, False, use_numpy=None)
448
451
 
449
452
  @patch("genie_python.genie_epics_api.Wrapper")
450
- def test_GIVEN_mock_pv_WHEN_get_global_pv_value_THEN_pv_is_returned(self, pv_wrapper_mock):
453
+ def test_GIVEN_mock_pv_WHEN_get_global_pv_value_THEN_pv_is_returned(
454
+ self, pv_wrapper_mock: MagicMock
455
+ ):
451
456
  expected_value = 10
452
457
  pv_wrapper_mock.pv_exists.return_value = True
453
458
  pv_wrapper_mock.get_pv_value.return_value = expected_value
@@ -460,7 +465,7 @@ class TestPvMethods(unittest.TestCase):
460
465
 
461
466
  @patch("genie_python.genie_epics_api.Wrapper")
462
467
  def test_GIVEN_mock_pv_WHEN_get_pv_value_but_pv_does_not_exist_THEN_exception(
463
- self, pv_wrapper_mock
468
+ self, pv_wrapper_mock: MagicMock
464
469
  ):
465
470
  pv_wrapper_mock.pv_exists.return_value = False
466
471
 
@@ -470,7 +475,7 @@ class TestPvMethods(unittest.TestCase):
470
475
 
471
476
  @patch("genie_python.genie_epics_api.Wrapper")
472
477
  def test_GIVEN_mock_pv_WHEN_get_pv_value_but_wrapper_exception_THEN_exception_thrown(
473
- self, pv_wrapper_mock
478
+ self, pv_wrapper_mock: MagicMock
474
479
  ):
475
480
  pv_wrapper_mock.get_pv_value.side_effect = ValueError()
476
481
 
@@ -483,7 +488,7 @@ class TestPvMethods(unittest.TestCase):
483
488
 
484
489
  @patch("genie_python.genie_epics_api.Wrapper")
485
490
  def test_GIVEN_mock_pv_WHEN_get_pv_value_wrapper_exception_on_first_trial_and_ok_on_second_THEN_value_returned(
486
- self, pv_wrapper_mock
491
+ self, pv_wrapper_mock: MagicMock
487
492
  ):
488
493
  expected_value = 10
489
494
  pv_wrapper_mock.pv_exists.return_value = True
@@ -502,7 +507,7 @@ class TestPvMethods(unittest.TestCase):
502
507
 
503
508
  @patch("genie_python.genie_epics_api.Wrapper")
504
509
  def test_GIVEN_mock_pv_WHEN_get_pv_value_raises_exception_except_on_last_trial_THEN_value_returned(
505
- self, pv_wrapper_mock
510
+ self, pv_wrapper_mock: MagicMock
506
511
  ):
507
512
  expected_value = 10
508
513
  pv_wrapper_mock.pv_exists.return_value = True
@@ -525,7 +530,7 @@ class TestPvMethods(unittest.TestCase):
525
530
  )
526
531
 
527
532
  @patch("genie_python.genie_epics_api.Wrapper")
528
- def test_GIVEN_mock_pv_WHEN_set_local_pv_value_THEN_pv_is_set(self, pv_wrapper_mock):
533
+ def test_GIVEN_mock_pv_WHEN_set_local_pv_value_THEN_pv_is_set(self, pv_wrapper_mock: MagicMock):
529
534
  expected_value = 10
530
535
  pv_name = "PV"
531
536
  expected_pv_name = "{}{}".format(self.instrument_prefix, pv_name)
@@ -538,7 +543,7 @@ class TestPvMethods(unittest.TestCase):
538
543
 
539
544
  @patch("genie_python.genie_epics_api.Wrapper")
540
545
  def test_GIVEN_mock_pv_WHEN_set_local_pv_value_with_inst_prefix_THEN_pv_is_set_pv_does_not_have_extra_prefix(
541
- self, pv_wrapper_mock
546
+ self, pv_wrapper_mock: MagicMock
542
547
  ):
543
548
  expected_value = 10
544
549
  pv_name = "PV"
@@ -551,7 +556,9 @@ class TestPvMethods(unittest.TestCase):
551
556
  )
552
557
 
553
558
  @patch("genie_python.genie_epics_api.Wrapper")
554
- def test_GIVEN_mock_pv_WHEN_set_global_pv_value_THEN_pv_is_set(self, pv_wrapper_mock):
559
+ def test_GIVEN_mock_pv_WHEN_set_global_pv_value_THEN_pv_is_set(
560
+ self, pv_wrapper_mock: MagicMock
561
+ ):
555
562
  expected_value = 10
556
563
  expected_pv_name = "PV"
557
564
 
@@ -563,7 +570,7 @@ class TestPvMethods(unittest.TestCase):
563
570
 
564
571
  @patch("genie_python.genie_epics_api.Wrapper")
565
572
  def test_GIVEN_mock_pv_WHEN_set_local_pv_value_but_wrapper_exceptions_THEN_exception_thrown(
566
- self, pv_wrapper_mock
573
+ self, pv_wrapper_mock: MagicMock
567
574
  ):
568
575
  pv_wrapper_mock.set_pv_value.side_effect = ValueError()
569
576
  expected_value = 10
@@ -584,7 +591,7 @@ class TestPvMethods(unittest.TestCase):
584
591
 
585
592
  @patch("genie_python.genie_epics_api.Wrapper")
586
593
  def test_GIVEN_mock_pv_WHEN_set_local_pv_value_but_wrapper_exception_on_first_trial_and_ok_on_second_THEN_pv_value_set(
587
- self, pv_wrapper_mock
594
+ self, pv_wrapper_mock: MagicMock
588
595
  ):
589
596
  expected_value = 10
590
597
  pv_name = "PV"
@@ -605,7 +612,7 @@ class TestPvMethods(unittest.TestCase):
605
612
 
606
613
  @patch("genie_python.genie_epics_api.Wrapper")
607
614
  def test_GIVEN_mock_pv_WHEN_set_local_pv_value_raises_exception_except_on_last_trial_THEN_pv_value_set_called_attempt_times(
608
- self, pv_wrapper_mock
615
+ self, pv_wrapper_mock: MagicMock
609
616
  ):
610
617
  expected_value = 10
611
618
  pv_name = "PV"
@@ -631,7 +638,7 @@ class TestPvMethods(unittest.TestCase):
631
638
 
632
639
  @patch("genie_python.genie_epics_api.Wrapper")
633
640
  def test_GIVEN_block_pointing_at_field_WHEN_get_block_units_THEN_units_field_is_called(
634
- self, pv_wrapper_mock
641
+ self, pv_wrapper_mock: MagicMock
635
642
  ):
636
643
  # Mock get_pv_from_block to return something with .SOMETHING on the end
637
644
  self.api.get_pv_from_block = MagicMock(return_value="PVNAME.SOMETHING")
@@ -645,7 +652,7 @@ class TestPvMethods(unittest.TestCase):
645
652
 
646
653
  @patch("genie_python.genie_epics_api.Wrapper")
647
654
  def test_GIVEN_block_already_pointing_at_unit_field_WHEN_get_block_units_THEN_units_field_is_called(
648
- self, pv_wrapper_mock
655
+ self, pv_wrapper_mock: MagicMock
649
656
  ):
650
657
  # Mock get_pv_from_block to return something with .EGU at the end
651
658
  self.api.get_pv_from_block = MagicMock(return_value="PVNAME.EGU")
@@ -659,7 +666,7 @@ class TestPvMethods(unittest.TestCase):
659
666
 
660
667
  @patch("genie_python.genie_epics_api.Wrapper")
661
668
  def test_GIVEN_block_not_pointing_at_field_WHEN_get_block_units_THEN_units_field_is_called(
662
- self, pv_wrapper_mock
669
+ self, pv_wrapper_mock: MagicMock
663
670
  ):
664
671
  # Mock get_pv_from_block to return something without .SOMETHING at the end
665
672
  self.api.get_pv_from_block = MagicMock(return_value="PVNAME")
@@ -673,7 +680,7 @@ class TestPvMethods(unittest.TestCase):
673
680
 
674
681
  @patch("genie_python.genie_epics_api.Wrapper")
675
682
  def test_GIVEN_block_not_found_WHEN_get_block_units_THEN_exception_is_raised(
676
- self, pv_wrapper_mock
683
+ self, pv_wrapper_mock: MagicMock
677
684
  ):
678
685
  # Mock get_pv_from_block to return something without .SOMETHING at the end
679
686
  self.api.get_pv_from_block = MagicMock(return_value="PVNAME")
@@ -687,7 +694,7 @@ class TestPvMethods(unittest.TestCase):
687
694
 
688
695
  @patch("genie_python.genie_epics_api.Wrapper")
689
696
  def test_GIVEN_pv_not_found_WHEN_get_block_units_THEN_exception_is_raised(
690
- self, pv_wrapper_mock
697
+ self, pv_wrapper_mock: MagicMock
691
698
  ):
692
699
  # Mock get_pv_from_block to return something without .SOMETHING at the end
693
700
  self.api.get_pv_from_block = MagicMock(return_value="PVNAME")
@@ -705,6 +712,33 @@ class TestPvMethods(unittest.TestCase):
705
712
  raises(UnableToConnectToPVException),
706
713
  )
707
714
 
715
+ # Test that when units of char-type PV (STRING, CHAR, UCHAR, ENUM) requested, None is returned
716
+ # (as these PVs don't usually have .EGU fields).
717
+ @parameterized.expand(
718
+ [
719
+ "DBF_STRING",
720
+ "DBF_CHAR",
721
+ "DBF_UCHAR",
722
+ "DBF_ENUM",
723
+ ]
724
+ )
725
+ @patch("genie_python.genie_epics_api.Wrapper")
726
+ def test_GIVEN_chartype_pv_WHEN_get_block_units_called_THEN_None_returned(
727
+ self, field_type: str, pv_wrapper_mock: MagicMock
728
+ ):
729
+ # Mock get_pv_from_block to return something with .SOMETHING on the end
730
+ self.api.get_pv_from_block = MagicMock(return_value="PVNAME.SOMETHING")
731
+
732
+ # Mock return value for DBF type (integer) to string from genie api
733
+ pv_wrapper_mock.dbf_type_to_string.return_value = field_type
734
+
735
+ # Call get_block_units
736
+ self.api.get_block_names = MagicMock(return_value=["TEST"])
737
+ test_units = self.api.get_block_units("TEST")
738
+
739
+ # Assert that returned units value is None
740
+ self.assertEqual(test_units, None)
741
+
708
742
 
709
743
  class TestSetBlockMethod(unittest.TestCase):
710
744
  @patch("genie_python.genie_epics_api.GetExperimentData")
@@ -719,7 +753,7 @@ class TestSetBlockMethod(unittest.TestCase):
719
753
 
720
754
  @patch("genie_python.genie_epics_api.Wrapper")
721
755
  def test_WHEN_set_block_value_called_with_wait_THEN_setpoint_set_and_wait_for_called(
722
- self, pv_wrapper
756
+ self, pv_wrapper: Wrapper
723
757
  ):
724
758
  self.api.waitfor = MagicMock()
725
759
 
@@ -731,7 +765,7 @@ class TestSetBlockMethod(unittest.TestCase):
731
765
 
732
766
  @patch("genie_python.genie_epics_api.Wrapper")
733
767
  def test_WHEN_set_block_value_called_with_wait_and_high_low_THEN_wait_for_called_with_high_low(
734
- self, pv_wrapper
768
+ self, pv_wrapper: Wrapper
735
769
  ):
736
770
  self.api.waitfor = MagicMock()
737
771
  block_name, set_point = "TEST_BLOCK", 10
@@ -746,7 +780,7 @@ class TestSetBlockMethod(unittest.TestCase):
746
780
 
747
781
  @patch("genie_python.genie_epics_api.Wrapper")
748
782
  def test_WHEN_set_block_value_called_with_wait_and_high_low_incorrect_order_THEN_wait_for_called_with_high_low_correct_order(
749
- self, pv_wrapper
783
+ self, pv_wrapper: Wrapper
750
784
  ):
751
785
  self.api.waitfor = MagicMock()
752
786
  block_name, set_point = "TEST_BLOCK", 10
@@ -761,7 +795,7 @@ class TestSetBlockMethod(unittest.TestCase):
761
795
 
762
796
  @patch("genie_python.genie_epics_api.Wrapper")
763
797
  def test_WHEN_set_block_value_called_with_wait_and_high_low_THEN_wait_for_called_with_high_low_correct_order(
764
- self, pv_wrapper
798
+ self, pv_wrapper: Wrapper
765
799
  ):
766
800
  self.api.waitfor = MagicMock()
767
801
  block_name, set_point = "TEST_BLOCK", 10
@@ -784,7 +818,14 @@ class TestSetBlockMethod(unittest.TestCase):
784
818
  @patch("genie_python.genie_epics_api.Wrapper")
785
819
  @patch("genie_python.genie_epics_api.print")
786
820
  def test_WHEN_set_block_value_called_with_wait_and_various_odd_high_lows_THEN_message_printed(
787
- self, _, low, high, val, should_warn, mock_print, pv_wrapper
821
+ self,
822
+ _,
823
+ low: int,
824
+ high: int,
825
+ val: int,
826
+ should_warn: bool,
827
+ mock_print: MagicMock,
828
+ pv_wrapper: Wrapper,
788
829
  ):
789
830
  self.api.waitfor = MagicMock()
790
831
  block_name, set_point = "TEST_BLOCK", 10
@@ -1,84 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: genie_python
3
- Version: 25.2.1.2
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/
@@ -1,84 +0,0 @@
1
- Metadata-Version: 2.2
2
- Name: genie_python
3
- Version: 25.2.1.2
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/
File without changes
File without changes
File without changes
File without changes