genie-python 15.1.0rc2__tar.gz → 25.2.1__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 (86) hide show
  1. genie_python-25.2.1/.github/dependabot.yml +6 -0
  2. {genie_python-15.1.0rc2 → genie_python-25.2.1}/.github/workflows/release.yml +1 -1
  3. {genie_python-15.1.0rc2 → genie_python-25.2.1}/.gitignore +3 -0
  4. {genie_python-15.1.0rc2/src/genie_python.egg-info → genie_python-25.2.1}/PKG-INFO +2 -2
  5. {genie_python-15.1.0rc2 → genie_python-25.2.1}/doc/genie_python.rst +4 -0
  6. {genie_python-15.1.0rc2 → genie_python-25.2.1}/pyproject.toml +2 -1
  7. {genie_python-15.1.0rc2 → genie_python-25.2.1}/ruff.toml +0 -2
  8. genie_python-25.2.1/src/genie_python/_version.py +16 -0
  9. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie.py +3 -3
  10. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_advanced.py +13 -0
  11. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_epics_api.py +8 -2
  12. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_experimental_data.py +11 -11
  13. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_simulate_impl.py +4 -0
  14. genie_python-25.2.1/src/genie_python/testing_utils/__init__.py +4 -0
  15. genie_python-25.2.1/src/genie_python/testing_utils/script_checker.py +63 -0
  16. genie_python-25.2.1/src/genie_python/version.py +6 -0
  17. {genie_python-15.1.0rc2 → genie_python-25.2.1/src/genie_python.egg-info}/PKG-INFO +2 -2
  18. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python.egg-info/SOURCES.txt +4 -0
  19. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_genie_epics_api.py +3 -0
  20. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_script_checker.py +43 -74
  21. genie_python-15.1.0rc2/src/genie_python/version.py +0 -1
  22. {genie_python-15.1.0rc2 → genie_python-25.2.1}/.git-blame-ignore-revs +0 -0
  23. {genie_python-15.1.0rc2 → genie_python-25.2.1}/.gitattributes +0 -0
  24. {genie_python-15.1.0rc2 → genie_python-25.2.1}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  25. {genie_python-15.1.0rc2 → genie_python-25.2.1}/.github/workflows/documentation.yml +0 -0
  26. {genie_python-15.1.0rc2 → genie_python-25.2.1}/.github/workflows/lint_and_test.yml +0 -0
  27. {genie_python-15.1.0rc2 → genie_python-25.2.1}/LICENSE +0 -0
  28. {genie_python-15.1.0rc2 → genie_python-25.2.1}/README.md +0 -0
  29. {genie_python-15.1.0rc2 → genie_python-25.2.1}/doc/conf.py +0 -0
  30. {genie_python-15.1.0rc2 → genie_python-25.2.1}/setup.cfg +0 -0
  31. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/.pylintrc +0 -0
  32. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/__init__.py +0 -0
  33. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/block_names.py +0 -0
  34. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/channel_access_exceptions.py +0 -0
  35. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_alerts.py +0 -0
  36. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_api_setup.py +0 -0
  37. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_blockserver.py +0 -0
  38. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_cachannel_wrapper.py +0 -0
  39. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_change_cache.py +0 -0
  40. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_dae.py +0 -0
  41. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_logging.py +0 -0
  42. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_p4p_wrapper.py +0 -0
  43. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_plot.py +0 -0
  44. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_pre_post_cmd_manager.py +0 -0
  45. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_pv_connection_protocol.py +0 -0
  46. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_script_checker.py +0 -0
  47. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_script_generator.py +0 -0
  48. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_simulate.py +0 -0
  49. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_startup.py +0 -0
  50. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_toggle_settings.py +0 -0
  51. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_wait_for_move.py +0 -0
  52. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/genie_waitfor.py +0 -0
  53. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/matplotlib_backend/__init__.py +0 -0
  54. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/matplotlib_backend/ibex_websocket_backend.py +0 -0
  55. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/mysql_abstraction_layer.py +0 -0
  56. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/scanning_instrument_pylint_plugin.py +0 -0
  57. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/typings/CaChannel/CaChannel.pyi +0 -0
  58. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/typings/CaChannel/__init__.pyi +0 -0
  59. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/typings/CaChannel/_version.pyi +0 -0
  60. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/typings/CaChannel/ca.pyi +0 -0
  61. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python/utilities.py +0 -0
  62. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python.egg-info/dependency_links.txt +0 -0
  63. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python.egg-info/requires.txt +0 -0
  64. {genie_python-15.1.0rc2 → genie_python-25.2.1}/src/genie_python.egg-info/top_level.txt +0 -0
  65. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/__init__.py +0 -0
  66. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/py3_test_genie_experimental_data.py +0 -0
  67. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_block_names.py +0 -0
  68. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_genie.py +0 -0
  69. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_genie_alerts.py +0 -0
  70. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_genie_api_setup.py +0 -0
  71. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_genie_blockserver_tests.py +0 -0
  72. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_genie_change_cache.py +0 -0
  73. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_genie_dae.py +0 -0
  74. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_genie_wait_for_move.py +0 -0
  75. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_genie_waitfor.py +0 -0
  76. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_matplotlib_backend.py +0 -0
  77. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_mysql_abstraction_layer.py +0 -0
  78. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_script_generator.py +0 -0
  79. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_scripts/error.py +0 -0
  80. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_scripts/error_for_script_checker.py +0 -0
  81. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_scripts/valid.py +0 -0
  82. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_scripts/valid_python_2.py +0 -0
  83. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_scripts/valid_to_import.py +0 -0
  84. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_simulation.py +0 -0
  85. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_utilities.py +0 -0
  86. {genie_python-15.1.0rc2 → genie_python-25.2.1}/tests/test_utils_with_unicode_literals.py +0 -0
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "daily"
@@ -67,7 +67,7 @@ jobs:
67
67
  name: python-package-distributions
68
68
  path: dist/
69
69
  - name: Sign the dists with Sigstore
70
- uses: sigstore/gh-action-sigstore-python@v2.1.1
70
+ uses: sigstore/gh-action-sigstore-python@v3.0.0
71
71
  with:
72
72
  inputs: >-
73
73
  ./dist/*.tar.gz
@@ -162,3 +162,6 @@ cython_debug/
162
162
  .idea/
163
163
 
164
164
  _build/
165
+
166
+ # setuptools_scm-generated file
167
+ src/genie_python/_version.py
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: genie_python
3
- Version: 15.1.0rc2
3
+ Version: 25.2.1
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>
@@ -18,4 +18,8 @@ Commands
18
18
  .. automodule:: genie_advanced
19
19
  :members:
20
20
 
21
+ .. automodule:: genie_alerts
22
+ :members:
21
23
 
24
+ .. automodule:: genie_toggle_settings
25
+ :members:
@@ -1,5 +1,5 @@
1
1
  [build-system]
2
- requires = ["setuptools", "setuptools_scm>=8"]
2
+ requires = ["setuptools>=64", "setuptools_scm>=8"]
3
3
  build-backend = "setuptools.build_meta"
4
4
 
5
5
 
@@ -119,5 +119,6 @@ reportUntypedClassDecorator = true
119
119
  reportUntypedFunctionDecorator = true
120
120
 
121
121
  [tool.setuptools_scm]
122
+ version_file = "src/genie_python/_version.py"
122
123
 
123
124
  [tool.build_sphinx]
@@ -23,8 +23,6 @@ ignore = [
23
23
  "D406", # Section name should end with a newline ("{name}")
24
24
  "D407", # Missing dashed underline after section ("{name}")
25
25
  "N999", # Ignore this because the repo itself would need to be renamed
26
- "ANN101", # ignore this until its removed in future versions
27
- "ANN102", # ignore this until its removed in future versions
28
26
  "ANN401", # explicit ANY type is allowed
29
27
  ]
30
28
  [lint.per-file-ignores]
@@ -0,0 +1,16 @@
1
+ # file generated by setuptools_scm
2
+ # don't change, don't track in version control
3
+ TYPE_CHECKING = False
4
+ if TYPE_CHECKING:
5
+ from typing import Tuple, Union
6
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
7
+ else:
8
+ VERSION_TUPLE = object
9
+
10
+ version: str
11
+ __version__: str
12
+ __version_tuple__: VERSION_TUPLE
13
+ version_tuple: VERSION_TUPLE
14
+
15
+ __version__ = version = '25.2.1'
16
+ __version_tuple__ = version_tuple = (25, 2, 1)
@@ -47,7 +47,7 @@ PVValue = PVBaseValue | list[PVBaseValue] | npt.NDArray | None
47
47
 
48
48
  print("\ngenie_python version " + VERSION)
49
49
 
50
- SUPPORTED_PYTHON_VERSION = (3, 11, 6)
50
+ SUPPORTED_PYTHON_VERSION = (3, 11, 9)
51
51
  if sys.version_info[0:3] != SUPPORTED_PYTHON_VERSION[0:3]:
52
52
  message = (
53
53
  "WARNING: genie_python only guarantees support for "
@@ -114,13 +114,13 @@ def get_block_units(block_name: str) -> str | dict | None:
114
114
  @helparglist("...")
115
115
  @log_command_and_handle_exception
116
116
  def cset(
117
- *args: str,
117
+ *args: PVValue,
118
118
  runcontrol: bool | None = None,
119
119
  lowlimit: float | None = None,
120
120
  highlimit: float | None = None,
121
121
  wait: bool | None = None,
122
122
  verbose: bool | None = None,
123
- **kwargs: bool | int | float | str | None,
123
+ **kwargs: PVValue,
124
124
  ) -> None:
125
125
  """
126
126
  Sets the setpoint and runcontrol settings for blocks.
@@ -328,6 +328,19 @@ def get_instrument() -> str | None:
328
328
  return __api.get_instrument()
329
329
 
330
330
 
331
+ @usercommand
332
+ @helparglist("")
333
+ @log_command_and_handle_exception
334
+ def get_instrument_full_name() -> str | None:
335
+ """
336
+ Gets the full name of the local instrument
337
+
338
+ Returns:
339
+ the full name of the machine
340
+ """
341
+ return __api.get_instrument_full_name()
342
+
343
+
331
344
  @usercommand
332
345
  @helparglist("verbose")
333
346
  @log_command_and_handle_exception
@@ -74,7 +74,7 @@ class API(object):
74
74
  else:
75
75
  self._environment_details = environment_details
76
76
 
77
- Wrapper.errorLogFunc = self.logger.log_ca_msg
77
+ Wrapper.error_log_func = self.logger.log_ca_msg
78
78
 
79
79
  # disable CA error messages to console from disconnected PVs
80
80
  import ctypes
@@ -323,12 +323,18 @@ class API(object):
323
323
 
324
324
  Args:
325
325
  name: the PV name
326
- value: the value to set
326
+ value: the value to set. If this is None, do nothing.
327
327
  wait: wait for the value to be set before returning
328
328
  is_local (bool, optional): whether to automatically prepend the
329
329
  local inst prefix to the PV name
330
330
  attempts: number of attempts to try to set the pv value
331
331
  """
332
+ if value is None:
333
+ self.logger.log_info_msg(
334
+ f"set_pv_value called with name={name} value={value} wait={wait}"
335
+ f" is_local={is_local} attempts={attempts} ignoring because value is None"
336
+ )
337
+ return
332
338
  if is_local:
333
339
  if not name.startswith(self.inst_prefix):
334
340
  name = self.prefix_pv_name(name)
@@ -7,8 +7,8 @@ from typing import TypedDict
7
7
  from genie_python.mysql_abstraction_layer import SQLAbstraction
8
8
 
9
9
  SELECT_FOR_EXP_DETAILS = """
10
- SELECT e.experimentID, u.name as userName, r.name as roleName,"""
11
- """ t.startDate, e.duration FROM `experimentteams` t
10
+ SELECT e.experimentID, u.name as userName, r.name as roleName,
11
+ t.startDate, e.duration FROM `experimentteams` t
12
12
  JOIN experiment e ON e.experimentID = t.experimentID
13
13
  JOIN user u ON u.userID = t.userID
14
14
  JOIN role r ON r.roleID = t.roleID
@@ -94,10 +94,10 @@ class GetExperimentData:
94
94
  self._pretty_print(exp_data)
95
95
  else:
96
96
  raise NotFoundError(
97
- f'Found no experiments that match the given criteria '
98
- f'(RB: {rb if rb != "%" else "Any"}, '
99
- f'User: {user if user != "%" else "Any"}, '
100
- f'Role: {role if role != "%" else "Any"}).\n'
97
+ f"Found no experiments that match the given criteria "
98
+ f"(RB: {rb if rb != '%' else 'Any'}, "
99
+ f"User: {user if user != '%' else 'Any'}, "
100
+ f"Role: {role if role != '%' else 'Any'}).\n"
101
101
  )
102
102
 
103
103
  return exp_data
@@ -169,11 +169,11 @@ class GetExperimentData:
169
169
 
170
170
  for exp in exp_data:
171
171
  print(
172
- f'Experiment RB number: {exp["rb_number"]:{rb_padding}} | '
173
- f'User: {exp["user"]:{user_padding}} | '
174
- f'Role: {exp["role"]:{role_padding}} | '
175
- f'Start date: {exp["start_date"]} | '
176
- f'Duration: {exp["duration"]}'
172
+ f"Experiment RB number: {exp['rb_number']:{rb_padding}} | "
173
+ f"User: {exp['user']:{user_padding}} | "
174
+ f"Role: {exp['role']:{role_padding}} | "
175
+ f"Start date: {exp['start_date']} | "
176
+ f"Duration: {exp['duration']}"
177
177
  )
178
178
 
179
179
 
@@ -2,6 +2,7 @@ from __future__ import absolute_import, print_function
2
2
 
3
3
  import inspect
4
4
  import os
5
+ import socket
5
6
  import xml.etree.ElementTree as ET
6
7
  from builtins import object, str
7
8
  from collections import OrderedDict
@@ -1263,3 +1264,6 @@ class API(object):
1263
1264
 
1264
1265
  def get_block_units(self, block: str) -> str:
1265
1266
  return "mm"
1267
+
1268
+ def get_instrument_full_name(self) -> str:
1269
+ return socket.gethostname()
@@ -0,0 +1,4 @@
1
+ """
2
+ This private module exists to allow testing utility code to be shared between genie_python's
3
+ unit tests, and the external system tests.
4
+ """
@@ -0,0 +1,63 @@
1
+ import os
2
+ import tempfile
3
+ from types import TracebackType
4
+ from typing import IO
5
+
6
+ from genie_python.genie_script_checker import ScriptChecker
7
+
8
+
9
+ def write_to_temp_file(message: list[str], suffix: str = "", dir: str = "") -> IO[bytes]:
10
+ """
11
+ write to temporary file for test check_script
12
+
13
+ Args:
14
+ message: message to write to file
15
+ suffix: filename suffix
16
+ dir: directory to write into
17
+
18
+ Returns:
19
+ temporary file
20
+ """
21
+ temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=suffix, dir=dir)
22
+ for line in message:
23
+ temp_file.write(line.encode("utf-8"))
24
+ temp_file.close()
25
+ return temp_file
26
+
27
+
28
+ class CreateTempScriptAndReturnErrors:
29
+ def __init__(
30
+ self,
31
+ script_checker: ScriptChecker,
32
+ machine: str,
33
+ script: list[str],
34
+ warnings_as_error: bool = True,
35
+ no_pyright: bool = False,
36
+ no_pylint: bool = False,
37
+ dir: str = "",
38
+ ) -> None:
39
+ self.script = script
40
+ self.machine = machine
41
+ self.dir = dir
42
+ self.warnings_as_error = warnings_as_error
43
+ self.no_pyright = no_pyright
44
+ self.no_pylint = no_pylint
45
+ self.script_checker = script_checker
46
+
47
+ def __enter__(self) -> list[str]:
48
+ self.temp_script_file = write_to_temp_file(self.script, dir=self.dir)
49
+ return self.script_checker.check_script(
50
+ self.temp_script_file.name,
51
+ self.machine,
52
+ warnings_as_error=self.warnings_as_error,
53
+ no_pyright=self.no_pyright,
54
+ no_pylint=self.no_pylint,
55
+ )
56
+
57
+ def __exit__(
58
+ self,
59
+ exc_type: type[BaseException] | None,
60
+ exc_value: BaseException | None,
61
+ exc_traceback: TracebackType,
62
+ ) -> None:
63
+ os.unlink(self.temp_script_file.name)
@@ -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
@@ -1,6 +1,6 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.2
2
2
  Name: genie_python
3
- Version: 15.1.0rc2
3
+ Version: 25.2.1
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>
@@ -6,6 +6,7 @@ README.md
6
6
  pyproject.toml
7
7
  ruff.toml
8
8
  .github/PULL_REQUEST_TEMPLATE.md
9
+ .github/dependabot.yml
9
10
  .github/workflows/documentation.yml
10
11
  .github/workflows/lint_and_test.yml
11
12
  .github/workflows/release.yml
@@ -13,6 +14,7 @@ doc/conf.py
13
14
  doc/genie_python.rst
14
15
  src/genie_python/.pylintrc
15
16
  src/genie_python/__init__.py
17
+ src/genie_python/_version.py
16
18
  src/genie_python/block_names.py
17
19
  src/genie_python/channel_access_exceptions.py
18
20
  src/genie_python/genie.py
@@ -49,6 +51,8 @@ src/genie_python.egg-info/requires.txt
49
51
  src/genie_python.egg-info/top_level.txt
50
52
  src/genie_python/matplotlib_backend/__init__.py
51
53
  src/genie_python/matplotlib_backend/ibex_websocket_backend.py
54
+ src/genie_python/testing_utils/__init__.py
55
+ src/genie_python/testing_utils/script_checker.py
52
56
  src/genie_python/typings/CaChannel/CaChannel.pyi
53
57
  src/genie_python/typings/CaChannel/__init__.pyi
54
58
  src/genie_python/typings/CaChannel/_version.pyi
@@ -173,6 +173,9 @@ class TestEpicsApiSequence(unittest.TestCase):
173
173
 
174
174
  self.assertEqual(self.api.get_pv_alarm("DISCONNECTED_PV"), "UNKNOWN")
175
175
 
176
+ def test_GIVEN_api_is_imported_THEN_error_log_func_overwritten_on_wrapper(self):
177
+ self.assertEqual(self.mock_wrapper.error_log_func, self.api.logger.log_ca_msg)
178
+
176
179
 
177
180
  class TestEpicsApiSetInstrumentName(unittest.TestCase):
178
181
  def setUp(self):
@@ -26,52 +26,13 @@ import astroid
26
26
 
27
27
  from genie_python.genie_epics_api import API
28
28
  from genie_python.genie_script_checker import ScriptChecker
29
-
30
-
31
- def write_to_file(message, suffix="", dir=""):
32
- """
33
- write to temporary file for test check_script
34
- :param message: message to write to file
35
- :return: returns temporary file
36
- """
37
- temp_file = tempfile.NamedTemporaryFile(delete=False, suffix=suffix, dir=dir)
38
- for line in message:
39
- temp_file.write(line.encode("utf-8"))
40
- temp_file.close()
41
- return temp_file
29
+ from genie_python.testing_utils.script_checker import (
30
+ CreateTempScriptAndReturnErrors,
31
+ write_to_temp_file,
32
+ )
42
33
 
43
34
 
44
35
  class TestScriptChecker(unittest.TestCase):
45
- class _CreateTempScriptAndReturnErrors:
46
- def __init__(
47
- self,
48
- script_checker,
49
- script,
50
- warnings_as_error=True,
51
- no_pyright=False,
52
- no_pylint=False,
53
- dir="",
54
- ):
55
- self.script = script
56
- self.dir = dir
57
- self.warnings_as_error = warnings_as_error
58
- self.no_pyright = no_pyright
59
- self.no_pylint = no_pylint
60
- self.script_checker = script_checker
61
-
62
- def __enter__(self):
63
- self.temp_script_file = write_to_file(self.script, dir=self.dir)
64
- return self.script_checker.checker.check_script(
65
- self.temp_script_file.name,
66
- self.script_checker.machine,
67
- warnings_as_error=self.warnings_as_error,
68
- no_pyright=self.no_pyright,
69
- no_pylint=self.no_pylint,
70
- )
71
-
72
- def __exit__(self, exc_type, exc_value, exc_traceback):
73
- os.unlink(self.temp_script_file.name)
74
-
75
36
  def setUp(self):
76
37
  self.checker = ScriptChecker()
77
38
  self.api = API("", None)
@@ -86,7 +47,7 @@ class TestScriptChecker(unittest.TestCase):
86
47
 
87
48
  def assertSymbolsDefined(self, script_lines, expected_symbols):
88
49
  dir_path = tempfile.mkdtemp()
89
- write_to_file(script_lines, suffix=".py", dir=dir_path)
50
+ write_to_temp_file(script_lines, suffix=".py", dir=dir_path)
90
51
  result = self.checker.get_inst_attributes(dir_path)
91
52
  shutil.rmtree(dir_path)
92
53
  self.assertEqual(result, expected_symbols)
@@ -98,7 +59,7 @@ class TestScriptChecker(unittest.TestCase):
98
59
  " g.end\n",
99
60
  ]
100
61
 
101
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
62
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
102
63
  self.assertEqual(
103
64
  errors, ["W: 4: Statement seems to have no effect (pointless-statement)"]
104
65
  )
@@ -106,7 +67,7 @@ class TestScriptChecker(unittest.TestCase):
106
67
  def test_GIVEN_end_as_start_of_another_word_WHEN_check_THEN_no_error_message(self):
107
68
  script_lines = ["from genie_python import genie as g\n" "def test():\n", " endAngle = 1"]
108
69
 
109
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
70
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
110
71
  self.assertEqual(errors, [])
111
72
 
112
73
  def test_GIVEN_end_as_end_of_another_word_WHEN_check_THEN_no_error_message(self):
@@ -115,13 +76,15 @@ class TestScriptChecker(unittest.TestCase):
115
76
  " angle_end = 1",
116
77
  ]
117
78
 
118
- with self._CreateTempScriptAndReturnErrors(self, script_lines, no_pyright=True) as errors:
79
+ with CreateTempScriptAndReturnErrors(
80
+ self.checker, self.machine, script_lines, no_pyright=True
81
+ ) as errors:
119
82
  self.assertEqual(errors, [])
120
83
 
121
84
  def test_GIVEN_end_without_brackets_at_start_of_line_WHEN_check_THEN_error_message(self):
122
85
  script_lines = ["from genie_python import genie as g\n" "def test():\n" " g.end"]
123
86
 
124
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
87
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
125
88
  self.assertEqual(
126
89
  errors, ["W: 3: Statement seems to have no effect (pointless-statement)"]
127
90
  )
@@ -131,7 +94,7 @@ class TestScriptChecker(unittest.TestCase):
131
94
  ):
132
95
  script_lines = ["from genie_python import genie as g\n" "g.begin(); g.end "]
133
96
 
134
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
97
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
135
98
  self.assertEqual(
136
99
  errors, ["W: 2: Statement seems to have no effect (pointless-statement)"]
137
100
  )
@@ -139,13 +102,13 @@ class TestScriptChecker(unittest.TestCase):
139
102
  def test_GIVEN_end_in_string_without_brackets_WHEN_check_THEN_no_message(self):
140
103
  script_lines = ["def test():\n" ' " a string containing end "']
141
104
 
142
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
105
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
143
106
  self.assertEqual(errors, [])
144
107
 
145
108
  def test_GIVEN_end_in_comment_without_brackets_WHEN_check_THEN_no_message(self):
146
109
  script_lines = ["def test():\n", ' "stuff" # end "']
147
110
 
148
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
111
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
149
112
  self.assertEqual(errors, [])
150
113
 
151
114
  def test_GIVEN_g_assignment_WHEN_check_THEN_warning_message(self):
@@ -229,13 +192,13 @@ class TestScriptChecker(unittest.TestCase):
229
192
  def test_GIVEN_g_assignment_with_2_symbols_before_number_WHEN_check_THEN_warning_message(self):
230
193
  script_lines = ["from genie_python import genie as g\n", "def test():\n", " g+=12"]
231
194
 
232
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
195
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
233
196
  self.assertEqual(errors, ["W: 3: 'g' assignment in line 3"])
234
197
 
235
198
  def test_GIVEN_variable_assignment_with_g__WHEN_check_THEN_no_message(self):
236
199
  script_lines = ["going=13"]
237
200
 
238
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
201
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
239
202
  self.assertEqual(errors, [])
240
203
 
241
204
  def test_GIVEN_function_with_g_WHEN_check_THEN_warn_user(self):
@@ -243,7 +206,7 @@ class TestScriptChecker(unittest.TestCase):
243
206
  "from genie_python import genie as g\n" "def test():\n" " g.test_function()\n"
244
207
  ]
245
208
 
246
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
209
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
247
210
  self.assertEqual(
248
211
  errors,
249
212
  ["E: 3: Module 'genie_python.genie' has no 'test_function' member (no-member)"],
@@ -255,7 +218,7 @@ class TestScriptChecker(unittest.TestCase):
255
218
  " g=17",
256
219
  ]
257
220
 
258
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
221
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
259
222
  self.assertEqual(
260
223
  errors, ["W: 3: 'g' assignment in line 3", "W: 4: 'g' assignment in line 4"]
261
224
  )
@@ -265,7 +228,7 @@ class TestScriptChecker(unittest.TestCase):
265
228
  "from genie_python import genie as g\n" "def test():\n" " g.aitfor_time(10)"
266
229
  ]
267
230
 
268
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
231
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
269
232
  self.assertEqual(
270
233
  errors,
271
234
  [
@@ -409,7 +372,7 @@ class TestScriptChecker(unittest.TestCase):
409
372
  script_lines = ["my_expr ="]
410
373
  expected = "E: 1: Parsing failed: 'invalid syntax"
411
374
 
412
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
375
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
413
376
  self.assertTrue(
414
377
  errors[0].startswith(expected),
415
378
  f"Result was {errors}, expected first line to start with {expected}",
@@ -418,20 +381,20 @@ class TestScriptChecker(unittest.TestCase):
418
381
  def test_GIVEN_valid_python_expr_WHEN_call_check_THEN_no_error(self):
419
382
  script_lines = ["my_expr = {}"]
420
383
 
421
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
384
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
422
385
  self.assertEqual(errors, [])
423
386
 
424
387
  def test_GIVEN_valid_python_class_WHEN_call_check_THEN_no_error(self):
425
388
  script_lines = ["class MyClass():", "pass"]
426
389
 
427
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
390
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
428
391
  self.assertEqual(errors, [])
429
392
 
430
393
  def test_GIVEN_invalid_python_class_WHEN_call_check_THEN_error(self):
431
394
  script_lines = ["class MyClass():"]
432
395
  expected = "E: 1: Parsing failed: 'expected an indented block"
433
396
 
434
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
397
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
435
398
  self.assertTrue(
436
399
  errors[0].startswith(expected),
437
400
  f'Result was "{errors[0]}", expected first line to start with "{expected}"',
@@ -476,7 +439,7 @@ class TestScriptChecker(unittest.TestCase):
476
439
 
477
440
  expected = "E: 2: Argument of type"
478
441
 
479
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
442
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
480
443
  self.assertTrue(errors[0].startswith(expected))
481
444
 
482
445
  def test_GIVEN_invalid_var_type_THEN_pyright_throws_exception(self):
@@ -484,7 +447,7 @@ class TestScriptChecker(unittest.TestCase):
484
447
 
485
448
  expected = "not assignable"
486
449
 
487
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
450
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
488
451
  self.assertTrue(expected in errors[0])
489
452
 
490
453
  def test_GIVEN_new_directory_WHEN_pyright_script_checker_called_THEN_pyright_json_created_then_destroyed_after_use(
@@ -512,7 +475,7 @@ class TestScriptChecker(unittest.TestCase):
512
475
 
513
476
  expected = "E: 3: Argument of type"
514
477
 
515
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
478
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
516
479
  self.assertTrue(errors[0].startswith(expected))
517
480
 
518
481
  # Test that if linter fails then pyright does not run
@@ -530,7 +493,7 @@ class TestScriptChecker(unittest.TestCase):
530
493
  ]
531
494
  expected = "E: 1: Parsing failed: 'invalid syntax"
532
495
 
533
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
496
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
534
497
  self.assertTrue(
535
498
  errors[0].startswith(expected) and len(errors) == 1
536
499
  ) # Will be count of 2 if pyright still runs
@@ -546,7 +509,9 @@ class TestScriptChecker(unittest.TestCase):
546
509
  " g.begin(1,2,3,4,5,6,7,8,9)\n",
547
510
  ]
548
511
 
549
- with self._CreateTempScriptAndReturnErrors(self, script_lines, no_pyright=True) as errors:
512
+ with CreateTempScriptAndReturnErrors(
513
+ self.checker, self.machine, script_lines, no_pyright=True
514
+ ) as errors:
550
515
  self.assertEqual(errors, [])
551
516
 
552
517
  # Pyright config checks
@@ -554,7 +519,7 @@ class TestScriptChecker(unittest.TestCase):
554
519
  def test_GIVEN_unused_variable_in_script_WHEN_pyright_script_checker_called_THEN_no_error(self):
555
520
  script_lines = ["a = 10\n"]
556
521
 
557
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
522
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
558
523
  self.assertEqual(errors, [])
559
524
 
560
525
  def test_GIVEN_trying_to_access_member_of_optional_type_var_WHEN_pyright_script_checker_called_THEN_no_error(
@@ -566,7 +531,7 @@ class TestScriptChecker(unittest.TestCase):
566
531
  " a.upper()\n",
567
532
  ]
568
533
 
569
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
534
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
570
535
  self.assertEqual(errors, [])
571
536
 
572
537
  def test_GIVEN_trying_to_index_var_of_optional_type_WHEN_pyright_script_checker_called_THEN_no_error(
@@ -578,7 +543,7 @@ class TestScriptChecker(unittest.TestCase):
578
543
  " return elements[0]\n",
579
544
  ]
580
545
 
581
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
546
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
582
547
  self.assertEqual(errors, [])
583
548
 
584
549
  def test_GIVEN_trying_to_call_var_of_optional_type_WHEN_pyright_script_checker_called_THEN_no_error(
@@ -590,7 +555,7 @@ class TestScriptChecker(unittest.TestCase):
590
555
  " callback()\n",
591
556
  ]
592
557
 
593
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
558
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
594
559
  self.assertEqual(errors, [])
595
560
 
596
561
  def test_GIVEN_trying_to_iterate_over_var_of_optional_type_WHEN_pyright_script_checker_called_THEN_no_error(
@@ -602,7 +567,7 @@ class TestScriptChecker(unittest.TestCase):
602
567
  " pass\n",
603
568
  ]
604
569
 
605
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
570
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
606
571
  self.assertEqual(errors, [])
607
572
 
608
573
  def test_GIVEN_trying_to_define_function_with_none_type_args_type_WHEN_pyright_script_checker_called_THEN_no_error(
@@ -610,7 +575,7 @@ class TestScriptChecker(unittest.TestCase):
610
575
  ):
611
576
  script_lines = ["def none_func(arg: int = None):\n" " print(arg)\n"]
612
577
 
613
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
578
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
614
579
  self.assertEqual(errors, [])
615
580
 
616
581
  def test_GIVEN_trying_to_use_optional_operand__WHEN_pyright_script_checker_called_THEN_no_error(
@@ -618,7 +583,7 @@ class TestScriptChecker(unittest.TestCase):
618
583
  ):
619
584
  script_lines = ["def none_func(arg1: int, arg2: int = None):\n" " print(arg2 + arg1)\n"]
620
585
 
621
- with self._CreateTempScriptAndReturnErrors(self, script_lines) as errors:
586
+ with CreateTempScriptAndReturnErrors(self.checker, self.machine, script_lines) as errors:
622
587
  self.assertEqual(errors, [])
623
588
 
624
589
  def test_GIVEN_trying_to_use_undefined_variable_WHEN_pyright_script_checker_called_THEN_no_error(
@@ -626,11 +591,15 @@ class TestScriptChecker(unittest.TestCase):
626
591
  ):
627
592
  script_lines = ["def func():\n" " print(arg)\n"]
628
593
 
629
- with self._CreateTempScriptAndReturnErrors(self, script_lines, no_pylint=True) as errors:
594
+ with CreateTempScriptAndReturnErrors(
595
+ self.checker, self.machine, script_lines, no_pylint=True
596
+ ) as errors:
630
597
  self.assertEqual(errors, [])
631
598
 
632
599
  def test_GIVEN_unused_import_WHEN_pyright_script_checker_called_THEN_no_error(self):
633
600
  script_lines = ["import genie\n"]
634
601
 
635
- with self._CreateTempScriptAndReturnErrors(self, script_lines, no_pylint=True) as errors:
602
+ with CreateTempScriptAndReturnErrors(
603
+ self.checker, self.machine, script_lines, no_pylint=True
604
+ ) as errors:
636
605
  self.assertEqual(errors, [])
@@ -1 +0,0 @@
1
- VERSION = "0.0.0.qualifier"
File without changes