np-services 0.1.69__py3-none-any.whl → 0.1.70__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (207) hide show
  1. np_services/__init__.py +8 -8
  2. np_services/open_ephys.py +377 -378
  3. np_services/protocols.py +185 -185
  4. np_services/proxies.py +1489 -1489
  5. np_services/resources/mvr_connector.py +260 -260
  6. np_services/resources/zro.py +325 -325
  7. np_services/scripts/pretest.py +412 -389
  8. np_services/stim_computer_theme_changer.py +41 -41
  9. np_services/utils.py +167 -167
  10. {np_services-0.1.69.dist-info → np_services-0.1.70.dist-info}/METADATA +5 -5
  11. np_services-0.1.70.dist-info/RECORD +15 -0
  12. {np_services-0.1.69.dist-info → np_services-0.1.70.dist-info}/WHEEL +2 -1
  13. {np_services-0.1.69.dist-info → np_services-0.1.70.dist-info}/entry_points.txt +1 -1
  14. np_services-0.1.70.dist-info/top_level.txt +1 -0
  15. np_services/.mypy_cache/.gitignore +0 -2
  16. np_services/.mypy_cache/3.9/@plugins_snapshot.json +0 -1
  17. np_services/.mypy_cache/3.9/__future__.data.json +0 -1
  18. np_services/.mypy_cache/3.9/__future__.meta.json +0 -1
  19. np_services/.mypy_cache/3.9/_ast.data.json +0 -1
  20. np_services/.mypy_cache/3.9/_ast.meta.json +0 -1
  21. np_services/.mypy_cache/3.9/_codecs.data.json +0 -1
  22. np_services/.mypy_cache/3.9/_codecs.meta.json +0 -1
  23. np_services/.mypy_cache/3.9/_collections_abc.data.json +0 -1
  24. np_services/.mypy_cache/3.9/_collections_abc.meta.json +0 -1
  25. np_services/.mypy_cache/3.9/_ctypes.data.json +0 -1
  26. np_services/.mypy_cache/3.9/_ctypes.meta.json +0 -1
  27. np_services/.mypy_cache/3.9/_decimal.data.json +0 -1
  28. np_services/.mypy_cache/3.9/_decimal.meta.json +0 -1
  29. np_services/.mypy_cache/3.9/_random.data.json +0 -1
  30. np_services/.mypy_cache/3.9/_random.meta.json +0 -1
  31. np_services/.mypy_cache/3.9/_socket.data.json +0 -1
  32. np_services/.mypy_cache/3.9/_socket.meta.json +0 -1
  33. np_services/.mypy_cache/3.9/_thread.data.json +0 -1
  34. np_services/.mypy_cache/3.9/_thread.meta.json +0 -1
  35. np_services/.mypy_cache/3.9/_typeshed/__init__.data.json +0 -1
  36. np_services/.mypy_cache/3.9/_typeshed/__init__.meta.json +0 -1
  37. np_services/.mypy_cache/3.9/_warnings.data.json +0 -1
  38. np_services/.mypy_cache/3.9/_warnings.meta.json +0 -1
  39. np_services/.mypy_cache/3.9/_weakref.data.json +0 -1
  40. np_services/.mypy_cache/3.9/_weakref.meta.json +0 -1
  41. np_services/.mypy_cache/3.9/_weakrefset.data.json +0 -1
  42. np_services/.mypy_cache/3.9/_weakrefset.meta.json +0 -1
  43. np_services/.mypy_cache/3.9/_winapi.data.json +0 -1
  44. np_services/.mypy_cache/3.9/_winapi.meta.json +0 -1
  45. np_services/.mypy_cache/3.9/abc.data.json +0 -1
  46. np_services/.mypy_cache/3.9/abc.meta.json +0 -1
  47. np_services/.mypy_cache/3.9/array.data.json +0 -1
  48. np_services/.mypy_cache/3.9/array.meta.json +0 -1
  49. np_services/.mypy_cache/3.9/atexit.data.json +0 -1
  50. np_services/.mypy_cache/3.9/atexit.meta.json +0 -1
  51. np_services/.mypy_cache/3.9/builtins.data.json +0 -1
  52. np_services/.mypy_cache/3.9/builtins.meta.json +0 -1
  53. np_services/.mypy_cache/3.9/codecs.data.json +0 -1
  54. np_services/.mypy_cache/3.9/codecs.meta.json +0 -1
  55. np_services/.mypy_cache/3.9/collections/__init__.data.json +0 -1
  56. np_services/.mypy_cache/3.9/collections/__init__.meta.json +0 -1
  57. np_services/.mypy_cache/3.9/collections/abc.data.json +0 -1
  58. np_services/.mypy_cache/3.9/collections/abc.meta.json +0 -1
  59. np_services/.mypy_cache/3.9/contextlib.data.json +0 -1
  60. np_services/.mypy_cache/3.9/contextlib.meta.json +0 -1
  61. np_services/.mypy_cache/3.9/ctypes/__init__.data.json +0 -1
  62. np_services/.mypy_cache/3.9/ctypes/__init__.meta.json +0 -1
  63. np_services/.mypy_cache/3.9/datetime.data.json +0 -1
  64. np_services/.mypy_cache/3.9/datetime.meta.json +0 -1
  65. np_services/.mypy_cache/3.9/decimal.data.json +0 -1
  66. np_services/.mypy_cache/3.9/decimal.meta.json +0 -1
  67. np_services/.mypy_cache/3.9/email/__init__.data.json +0 -1
  68. np_services/.mypy_cache/3.9/email/__init__.meta.json +0 -1
  69. np_services/.mypy_cache/3.9/email/charset.data.json +0 -1
  70. np_services/.mypy_cache/3.9/email/charset.meta.json +0 -1
  71. np_services/.mypy_cache/3.9/email/contentmanager.data.json +0 -1
  72. np_services/.mypy_cache/3.9/email/contentmanager.meta.json +0 -1
  73. np_services/.mypy_cache/3.9/email/errors.data.json +0 -1
  74. np_services/.mypy_cache/3.9/email/errors.meta.json +0 -1
  75. np_services/.mypy_cache/3.9/email/header.data.json +0 -1
  76. np_services/.mypy_cache/3.9/email/header.meta.json +0 -1
  77. np_services/.mypy_cache/3.9/email/message.data.json +0 -1
  78. np_services/.mypy_cache/3.9/email/message.meta.json +0 -1
  79. np_services/.mypy_cache/3.9/email/policy.data.json +0 -1
  80. np_services/.mypy_cache/3.9/email/policy.meta.json +0 -1
  81. np_services/.mypy_cache/3.9/enum.data.json +0 -1
  82. np_services/.mypy_cache/3.9/enum.meta.json +0 -1
  83. np_services/.mypy_cache/3.9/errno.data.json +0 -1
  84. np_services/.mypy_cache/3.9/errno.meta.json +0 -1
  85. np_services/.mypy_cache/3.9/fractions.data.json +0 -1
  86. np_services/.mypy_cache/3.9/fractions.meta.json +0 -1
  87. np_services/.mypy_cache/3.9/genericpath.data.json +0 -1
  88. np_services/.mypy_cache/3.9/genericpath.meta.json +0 -1
  89. np_services/.mypy_cache/3.9/importlib/__init__.data.json +0 -1
  90. np_services/.mypy_cache/3.9/importlib/__init__.meta.json +0 -1
  91. np_services/.mypy_cache/3.9/importlib/abc.data.json +0 -1
  92. np_services/.mypy_cache/3.9/importlib/abc.meta.json +0 -1
  93. np_services/.mypy_cache/3.9/importlib/machinery.data.json +0 -1
  94. np_services/.mypy_cache/3.9/importlib/machinery.meta.json +0 -1
  95. np_services/.mypy_cache/3.9/importlib/metadata/__init__.data.json +0 -1
  96. np_services/.mypy_cache/3.9/importlib/metadata/__init__.meta.json +0 -1
  97. np_services/.mypy_cache/3.9/io.data.json +0 -1
  98. np_services/.mypy_cache/3.9/io.meta.json +0 -1
  99. np_services/.mypy_cache/3.9/json/__init__.data.json +0 -1
  100. np_services/.mypy_cache/3.9/json/__init__.meta.json +0 -1
  101. np_services/.mypy_cache/3.9/json/decoder.data.json +0 -1
  102. np_services/.mypy_cache/3.9/json/decoder.meta.json +0 -1
  103. np_services/.mypy_cache/3.9/json/encoder.data.json +0 -1
  104. np_services/.mypy_cache/3.9/json/encoder.meta.json +0 -1
  105. np_services/.mypy_cache/3.9/logging/__init__.data.json +0 -1
  106. np_services/.mypy_cache/3.9/logging/__init__.meta.json +0 -1
  107. np_services/.mypy_cache/3.9/math.data.json +0 -1
  108. np_services/.mypy_cache/3.9/math.meta.json +0 -1
  109. np_services/.mypy_cache/3.9/mmap.data.json +0 -1
  110. np_services/.mypy_cache/3.9/mmap.meta.json +0 -1
  111. np_services/.mypy_cache/3.9/np_services/__init__.data.json +0 -1
  112. np_services/.mypy_cache/3.9/np_services/__init__.meta.json +0 -1
  113. np_services/.mypy_cache/3.9/np_services/config.data.json +0 -1
  114. np_services/.mypy_cache/3.9/np_services/config.meta.json +0 -1
  115. np_services/.mypy_cache/3.9/np_services/protocols.data.json +0 -1
  116. np_services/.mypy_cache/3.9/np_services/protocols.meta.json +0 -1
  117. np_services/.mypy_cache/3.9/np_services/zro.data.json +0 -1
  118. np_services/.mypy_cache/3.9/np_services/zro.meta.json +0 -1
  119. np_services/.mypy_cache/3.9/ntpath.data.json +0 -1
  120. np_services/.mypy_cache/3.9/ntpath.meta.json +0 -1
  121. np_services/.mypy_cache/3.9/numbers.data.json +0 -1
  122. np_services/.mypy_cache/3.9/numbers.meta.json +0 -1
  123. np_services/.mypy_cache/3.9/os/__init__.data.json +0 -1
  124. np_services/.mypy_cache/3.9/os/__init__.meta.json +0 -1
  125. np_services/.mypy_cache/3.9/os/path.data.json +0 -1
  126. np_services/.mypy_cache/3.9/os/path.meta.json +0 -1
  127. np_services/.mypy_cache/3.9/pathlib.data.json +0 -1
  128. np_services/.mypy_cache/3.9/pathlib.meta.json +0 -1
  129. np_services/.mypy_cache/3.9/pickle.data.json +0 -1
  130. np_services/.mypy_cache/3.9/pickle.meta.json +0 -1
  131. np_services/.mypy_cache/3.9/platform.data.json +0 -1
  132. np_services/.mypy_cache/3.9/platform.meta.json +0 -1
  133. np_services/.mypy_cache/3.9/posixpath.data.json +0 -1
  134. np_services/.mypy_cache/3.9/posixpath.meta.json +0 -1
  135. np_services/.mypy_cache/3.9/random.data.json +0 -1
  136. np_services/.mypy_cache/3.9/random.meta.json +0 -1
  137. np_services/.mypy_cache/3.9/re.data.json +0 -1
  138. np_services/.mypy_cache/3.9/re.meta.json +0 -1
  139. np_services/.mypy_cache/3.9/shutil.data.json +0 -1
  140. np_services/.mypy_cache/3.9/shutil.meta.json +0 -1
  141. np_services/.mypy_cache/3.9/socket.data.json +0 -1
  142. np_services/.mypy_cache/3.9/socket.meta.json +0 -1
  143. np_services/.mypy_cache/3.9/sre_compile.data.json +0 -1
  144. np_services/.mypy_cache/3.9/sre_compile.meta.json +0 -1
  145. np_services/.mypy_cache/3.9/sre_constants.data.json +0 -1
  146. np_services/.mypy_cache/3.9/sre_constants.meta.json +0 -1
  147. np_services/.mypy_cache/3.9/sre_parse.data.json +0 -1
  148. np_services/.mypy_cache/3.9/sre_parse.meta.json +0 -1
  149. np_services/.mypy_cache/3.9/string.data.json +0 -1
  150. np_services/.mypy_cache/3.9/string.meta.json +0 -1
  151. np_services/.mypy_cache/3.9/subprocess.data.json +0 -1
  152. np_services/.mypy_cache/3.9/subprocess.meta.json +0 -1
  153. np_services/.mypy_cache/3.9/sys.data.json +0 -1
  154. np_services/.mypy_cache/3.9/sys.meta.json +0 -1
  155. np_services/.mypy_cache/3.9/threading.data.json +0 -1
  156. np_services/.mypy_cache/3.9/threading.meta.json +0 -1
  157. np_services/.mypy_cache/3.9/time.data.json +0 -1
  158. np_services/.mypy_cache/3.9/time.meta.json +0 -1
  159. np_services/.mypy_cache/3.9/types.data.json +0 -1
  160. np_services/.mypy_cache/3.9/types.meta.json +0 -1
  161. np_services/.mypy_cache/3.9/typing.data.json +0 -1
  162. np_services/.mypy_cache/3.9/typing.meta.json +0 -1
  163. np_services/.mypy_cache/3.9/typing_extensions.data.json +0 -1
  164. np_services/.mypy_cache/3.9/typing_extensions.meta.json +0 -1
  165. np_services/.mypy_cache/3.9/warnings.data.json +0 -1
  166. np_services/.mypy_cache/3.9/warnings.meta.json +0 -1
  167. np_services/.mypy_cache/3.9/weakref.data.json +0 -1
  168. np_services/.mypy_cache/3.9/weakref.meta.json +0 -1
  169. np_services/.mypy_cache/3.9/zmq/__init__.data.json +0 -1
  170. np_services/.mypy_cache/3.9/zmq/__init__.meta.json +0 -1
  171. np_services/.mypy_cache/3.9/zmq/_typing.data.json +0 -1
  172. np_services/.mypy_cache/3.9/zmq/_typing.meta.json +0 -1
  173. np_services/.mypy_cache/3.9/zmq/backend/__init__.data.json +0 -1
  174. np_services/.mypy_cache/3.9/zmq/backend/__init__.meta.json +0 -1
  175. np_services/.mypy_cache/3.9/zmq/backend/select.data.json +0 -1
  176. np_services/.mypy_cache/3.9/zmq/backend/select.meta.json +0 -1
  177. np_services/.mypy_cache/3.9/zmq/constants.data.json +0 -1
  178. np_services/.mypy_cache/3.9/zmq/constants.meta.json +0 -1
  179. np_services/.mypy_cache/3.9/zmq/error.data.json +0 -1
  180. np_services/.mypy_cache/3.9/zmq/error.meta.json +0 -1
  181. np_services/.mypy_cache/3.9/zmq/sugar/__init__.data.json +0 -1
  182. np_services/.mypy_cache/3.9/zmq/sugar/__init__.meta.json +0 -1
  183. np_services/.mypy_cache/3.9/zmq/sugar/attrsettr.data.json +0 -1
  184. np_services/.mypy_cache/3.9/zmq/sugar/attrsettr.meta.json +0 -1
  185. np_services/.mypy_cache/3.9/zmq/sugar/context.data.json +0 -1
  186. np_services/.mypy_cache/3.9/zmq/sugar/context.meta.json +0 -1
  187. np_services/.mypy_cache/3.9/zmq/sugar/frame.data.json +0 -1
  188. np_services/.mypy_cache/3.9/zmq/sugar/frame.meta.json +0 -1
  189. np_services/.mypy_cache/3.9/zmq/sugar/poll.data.json +0 -1
  190. np_services/.mypy_cache/3.9/zmq/sugar/poll.meta.json +0 -1
  191. np_services/.mypy_cache/3.9/zmq/sugar/socket.data.json +0 -1
  192. np_services/.mypy_cache/3.9/zmq/sugar/socket.meta.json +0 -1
  193. np_services/.mypy_cache/3.9/zmq/sugar/tracker.data.json +0 -1
  194. np_services/.mypy_cache/3.9/zmq/sugar/tracker.meta.json +0 -1
  195. np_services/.mypy_cache/3.9/zmq/sugar/version.data.json +0 -1
  196. np_services/.mypy_cache/3.9/zmq/sugar/version.meta.json +0 -1
  197. np_services/.mypy_cache/3.9/zmq/utils/__init__.data.json +0 -1
  198. np_services/.mypy_cache/3.9/zmq/utils/__init__.meta.json +0 -1
  199. np_services/.mypy_cache/3.9/zmq/utils/interop.data.json +0 -1
  200. np_services/.mypy_cache/3.9/zmq/utils/interop.meta.json +0 -1
  201. np_services/.mypy_cache/3.9/zmq/utils/jsonapi.data.json +0 -1
  202. np_services/.mypy_cache/3.9/zmq/utils/jsonapi.meta.json +0 -1
  203. np_services/.mypy_cache/CACHEDIR.TAG +0 -3
  204. np_services/resources/black_desktop.ps1 +0 -66
  205. np_services/resources/grey_desktop.ps1 +0 -66
  206. np_services/resources/reset_desktop.ps1 +0 -66
  207. np_services-0.1.69.dist-info/RECORD +0 -206
@@ -1,42 +1,42 @@
1
- import pathlib
2
- from typing import ClassVar
3
-
4
- import fabric
5
- import np_config
6
-
7
- from np_services.proxies import ScriptCamstim
8
-
9
- class DesktopThemeChanger(ScriptCamstim):
10
- """Base class for setting the background wallpaper on a remote machine,
11
- then hiding all desktop icons, hiding the taskbar, minimizing all windows"""
12
- local_file: ClassVar[str | pathlib.Path]
13
- remote_file: ClassVar[str | pathlib.Path]
14
-
15
- extra_args: ClassVar[list[str]] = []
16
- ssh: ClassVar[fabric.Connection]
17
- user: ClassVar[str] = 'svc_neuropix'
18
- password: ClassVar[str] = np_config.fetch('logins')['svc_neuropix']['password']
19
-
20
- # @classmethod
21
- # def initialize(cls):
22
- # super().initialize()
23
- # cls.get_ssh().put(cls.local_file, cls.remote_file)
24
-
25
- @classmethod
26
- def start(cls):
27
- cls.get_ssh().run(f'powershell.exe -ExecutionPolicy bypass {cls.remote_file}')
28
-
29
- class DarkDesktopChanger(DesktopThemeChanger):
30
- local_file = pathlib.Path(__file__).parent / 'resources' / 'black_wallpaper.ps1'
31
- # remote_file: ClassVar[str | pathlib.Path] = 'c:/users/svc_neuropix/desktop/black_wallpaper.ps1'
32
- remote_file: ClassVar[str | pathlib.Path] = R'\\allen\programs\mindscope\workgroups\dynamicrouting\ben\black_wallpaper.ps1'
33
-
34
- class GreyDesktopChanger(DesktopThemeChanger):
35
- local_file = pathlib.Path(__file__).parent / 'resources' / 'grey_wallpaper.ps1'
36
- # remote_file: ClassVar[str | pathlib.Path] = 'c:/users/svc_neuropix/desktop/grey_wallpaper.ps1'
37
- remote_file: ClassVar[str | pathlib.Path] = R'\\allen\programs\mindscope\workgroups\dynamicrouting\ben\grey_wallpaper.ps1'
38
-
39
- class DesktopResetter(DesktopThemeChanger):
40
- local_file = pathlib.Path(__file__).parent / 'resources' / 'reset_wallpaper.ps1'
41
- # remote_file: ClassVar[str | pathlib.Path] = 'c:/users/svc_neuropix/desktop/reset_wallpaper.ps1'
1
+ import pathlib
2
+ from typing import ClassVar
3
+
4
+ import fabric
5
+ import np_config
6
+
7
+ from np_services.proxies import ScriptCamstim
8
+
9
+ class DesktopThemeChanger(ScriptCamstim):
10
+ """Base class for setting the background wallpaper on a remote machine,
11
+ then hiding all desktop icons, hiding the taskbar, minimizing all windows"""
12
+ local_file: ClassVar[str | pathlib.Path]
13
+ remote_file: ClassVar[str | pathlib.Path]
14
+
15
+ extra_args: ClassVar[list[str]] = []
16
+ ssh: ClassVar[fabric.Connection]
17
+ user: ClassVar[str] = 'svc_neuropix'
18
+ password: ClassVar[str] = np_config.fetch('logins')['svc_neuropix']['password']
19
+
20
+ # @classmethod
21
+ # def initialize(cls):
22
+ # super().initialize()
23
+ # cls.get_ssh().put(cls.local_file, cls.remote_file)
24
+
25
+ @classmethod
26
+ def start(cls):
27
+ cls.get_ssh().run(f'powershell.exe -ExecutionPolicy bypass {cls.remote_file}')
28
+
29
+ class DarkDesktopChanger(DesktopThemeChanger):
30
+ local_file = pathlib.Path(__file__).parent / 'resources' / 'black_wallpaper.ps1'
31
+ # remote_file: ClassVar[str | pathlib.Path] = 'c:/users/svc_neuropix/desktop/black_wallpaper.ps1'
32
+ remote_file: ClassVar[str | pathlib.Path] = R'\\allen\programs\mindscope\workgroups\dynamicrouting\ben\black_wallpaper.ps1'
33
+
34
+ class GreyDesktopChanger(DesktopThemeChanger):
35
+ local_file = pathlib.Path(__file__).parent / 'resources' / 'grey_wallpaper.ps1'
36
+ # remote_file: ClassVar[str | pathlib.Path] = 'c:/users/svc_neuropix/desktop/grey_wallpaper.ps1'
37
+ remote_file: ClassVar[str | pathlib.Path] = R'\\allen\programs\mindscope\workgroups\dynamicrouting\ben\grey_wallpaper.ps1'
38
+
39
+ class DesktopResetter(DesktopThemeChanger):
40
+ local_file = pathlib.Path(__file__).parent / 'resources' / 'reset_wallpaper.ps1'
41
+ # remote_file: ClassVar[str | pathlib.Path] = 'c:/users/svc_neuropix/desktop/reset_wallpaper.ps1'
42
42
  remote_file: ClassVar[str | pathlib.Path] = R'\\allen\programs\mindscope\workgroups\dynamicrouting\ben\reset_wallpaper.ps1'
np_services/utils.py CHANGED
@@ -1,168 +1,168 @@
1
- import contextlib
2
- import datetime
3
- import functools
4
- import logging
5
- import math
6
- import os
7
- import pathlib
8
- import shutil
9
- import subprocess
10
- import sys
11
- import time
12
- from typing import Any, Generator, Literal, Mapping, Optional, Sequence, Type
13
-
14
- import np_config
15
- import np_logging
16
-
17
- import np_services.protocols as protocols
18
- import np_services.resources.zro as zro
19
-
20
- logger = np_logging.getLogger(__name__)
21
-
22
-
23
- def config_from_zk(rig: Optional[Literal[0, 1, 2]] = None) -> Mapping[str, Any]:
24
- "Common `services` config plus rig-specific `services`"
25
- common_config = np_config.from_zk("/projects/np_workflows/defaults/configuration")[
26
- "services"
27
- ]
28
-
29
- if rig:
30
- rig_config = np_config.Rig(rig).config["services"]
31
- else:
32
- rig_config = np_config.Rig().config["services"]
33
-
34
- for k, v in rig_config.items():
35
- common_config[k] = common_config.get(k, {}) | v
36
- return common_config
37
-
38
-
39
- def start_rsc_app(host, app_id) -> None:
40
- rsc_node = zro.Proxy(host, 6000)
41
- if rsc_node.p_status().get(app_id) == 0:
42
- logger.info("Launching %s on %s via RSC", app_id, host)
43
- rsc_node.p_start(app_id)
44
- time.sleep(1)
45
- if rsc_node.p_status().get(app_id) == 0:
46
- logger.warning("%s not confirmed as launched - may be slow to start", app_id)
47
- return
48
- logger.info("%s is running on %s", app_id, host)
49
-
50
- def kill_rsc_app(host, app_id) -> None:
51
- "Does the same as the `kill` action in the RSC gui"
52
- rsc_node = zro.Proxy(host, 6000)
53
- rsc_node.p_stop(app_id)
54
- time.sleep(1)
55
- if rsc_node.p_status().get(app_id) != 0:
56
- logger.warning("%s not confirmed as killed - may be slow to shutdown", app_id)
57
- return
58
- logger.info("%s killed on %s", app_id, host)
59
-
60
-
61
- def start_rsc_apps() -> None:
62
- rsc_app_ids_required = np_config.Rig().config["rsc_app_ids_required"]
63
- rig = np_config.Rig()
64
- for host in (rig.Sync, rig.Stim, rig.Mon, rig.Acq):
65
- rsc_node = zro.Proxy(host, 6000)
66
- status = rsc_node.p_status()
67
- if any(
68
- apps_required_in_node := [_ for _ in rsc_app_ids_required if _ in status]
69
- ):
70
- for app in apps_required_in_node:
71
- rsc_node.p_start(app)
72
-
73
- @contextlib.contextmanager
74
- def stop_on_error(*objs: protocols.Stoppable, reraise=True):
75
- for obj in objs:
76
- if not isinstance(obj, protocols.Stoppable):
77
- raise TypeError(f"{obj} does not support stop()")
78
- try:
79
- yield
80
- except Exception as exc:
81
- with contextlib.suppress(Exception):
82
- for obj in objs:
83
- obj.stop()
84
- logger.info("%s interrupted by error and stopped", obj.__name__)
85
- obj.exc = exc
86
- if reraise:
87
- raise exc
88
- logger.error("Error suppressed: continuing despite raised exception", exc_info=exc)
89
-
90
- def is_online(host: str) -> bool:
91
- "Use OS's `ping` cmd to check if `host` is online."
92
- command = ["ping", "-n" if "win" in sys.platform else "-c", "1", host]
93
- try:
94
- return subprocess.call(command, stdout=subprocess.PIPE, timeout=1.0) == 0
95
- except subprocess.TimeoutExpired:
96
- return False
97
-
98
-
99
- def unc_to_local(path: pathlib.Path) -> pathlib.Path:
100
- "Convert UNC path to local path if on Windows."
101
- if "win" not in sys.platform:
102
- return path
103
- comp = os.environ["COMPUTERNAME"]
104
- if comp in path.drive:
105
- drive = path.drive.split("\\")[-1]
106
- drive = drive[:-1] if drive[-1] == "$" else drive
107
- drive = drive + ":" if drive[-1] != ":" else drive
108
- drive += "\\"
109
- path = pathlib.Path(drive, path.relative_to(path.drive))
110
- return path
111
-
112
-
113
- def free_gb(path: str | bytes | os.PathLike) -> float:
114
- "Return free space at `path`, to .1 GB. Raises FileNotFoundError if `path` not accessible."
115
- path = pathlib.Path(path)
116
- path = unc_to_local(path)
117
- return round(shutil.disk_usage(path).free / 1e9, 1)
118
-
119
-
120
- def get_files_created_between(
121
- path: str | bytes | os.PathLike,
122
- glob: str = "*",
123
- start: float | datetime.datetime = 0,
124
- end: Optional[float | datetime.datetime] = None,
125
- ) -> list[pathlib.Path]:
126
- path = pathlib.Path(path)
127
- if not path.is_dir():
128
- path = path.parent
129
- if not end:
130
- end = time.time()
131
- start = start.timestamp() if isinstance(start, datetime.datetime) else start
132
- end = end.timestamp() if isinstance(end, datetime.datetime) else end
133
- ctime = lambda x: x.stat().st_ctime
134
- files = (file for file in path.glob(glob) if int(start) <= ctime(file) <= end)
135
- return sorted(files, key=ctime)
136
-
137
-
138
- def is_file_growing(path: str | bytes | os.PathLike) -> bool:
139
- "Compares size of most recent .sync data file at two time-points - will block for up to 20s depending on file-size."
140
- path = pathlib.Path(path)
141
- size_0 = path.stat().st_size
142
- # for sync: file is appended periodically in chunks that scale non-linearly with size
143
- if ".sync" == path.suffix:
144
- time.sleep(2 * math.log10(size_0))
145
- else:
146
- time.sleep(0.5 * math.log10(size_0))
147
- if path.stat().st_size == size_0:
148
- return False
149
- return True
150
-
151
-
152
- def normalize_time(t) -> str:
153
- """
154
- >>> normalize_time(datetime.datetime(2023, 2, 14, 13, 30, 00))
155
- '20230214133000'
156
- >>> normalize_time(1676410200.0)
157
- '20230214133000'
158
- >>> normalize_time(1676410200)
159
- '20230214133000'
160
- >>> normalize_time('1676410200.0')
161
- '20230214133000'
162
- >>> normalize_time('1676410200')
163
- '20230214133000'
164
- >>> normalize_time('2023-02-14T13:30:00')
165
- '20230214133000'
166
- """
167
- # moved to np_config Feb 2023
1
+ import contextlib
2
+ import datetime
3
+ import functools
4
+ import logging
5
+ import math
6
+ import os
7
+ import pathlib
8
+ import shutil
9
+ import subprocess
10
+ import sys
11
+ import time
12
+ from typing import Any, Generator, Literal, Mapping, Optional, Sequence, Type
13
+
14
+ import np_config
15
+ import np_logging
16
+
17
+ import np_services.protocols as protocols
18
+ import np_services.resources.zro as zro
19
+
20
+ logger = np_logging.getLogger(__name__)
21
+
22
+
23
+ def config_from_zk(rig: Optional[Literal[0, 1, 2]] = None) -> Mapping[str, Any]:
24
+ "Common `services` config plus rig-specific `services`"
25
+ common_config = np_config.from_zk("/projects/np_workflows/defaults/configuration")[
26
+ "services"
27
+ ]
28
+
29
+ if rig:
30
+ rig_config = np_config.Rig(rig).config["services"]
31
+ else:
32
+ rig_config = np_config.Rig().config["services"]
33
+
34
+ for k, v in rig_config.items():
35
+ common_config[k] = common_config.get(k, {}) | v
36
+ return common_config
37
+
38
+
39
+ def start_rsc_app(host, app_id) -> None:
40
+ rsc_node = zro.Proxy(host, 6000)
41
+ if rsc_node.p_status().get(app_id) == 0:
42
+ logger.info("Launching %s on %s via RSC", app_id, host)
43
+ rsc_node.p_start(app_id)
44
+ time.sleep(1)
45
+ if rsc_node.p_status().get(app_id) == 0:
46
+ logger.warning("%s not confirmed as launched - may be slow to start", app_id)
47
+ return
48
+ logger.info("%s is running on %s", app_id, host)
49
+
50
+ def kill_rsc_app(host, app_id) -> None:
51
+ "Does the same as the `kill` action in the RSC gui"
52
+ rsc_node = zro.Proxy(host, 6000)
53
+ rsc_node.p_stop(app_id)
54
+ time.sleep(1)
55
+ if rsc_node.p_status().get(app_id) != 0:
56
+ logger.warning("%s not confirmed as killed - may be slow to shutdown", app_id)
57
+ return
58
+ logger.info("%s killed on %s", app_id, host)
59
+
60
+
61
+ def start_rsc_apps() -> None:
62
+ rsc_app_ids_required = np_config.Rig().config["rsc_app_ids_required"]
63
+ rig = np_config.Rig()
64
+ for host in (rig.Sync, rig.Stim, rig.Mon, rig.Acq):
65
+ rsc_node = zro.Proxy(host, 6000)
66
+ status = rsc_node.p_status()
67
+ if any(
68
+ apps_required_in_node := [_ for _ in rsc_app_ids_required if _ in status]
69
+ ):
70
+ for app in apps_required_in_node:
71
+ rsc_node.p_start(app)
72
+
73
+ @contextlib.contextmanager
74
+ def stop_on_error(*objs: protocols.Stoppable, reraise=True):
75
+ for obj in objs:
76
+ if not isinstance(obj, protocols.Stoppable):
77
+ raise TypeError(f"{obj} does not support stop()")
78
+ try:
79
+ yield
80
+ except Exception as exc:
81
+ with contextlib.suppress(Exception):
82
+ for obj in objs:
83
+ obj.stop()
84
+ logger.info("%s interrupted by error and stopped", obj.__name__)
85
+ obj.exc = exc
86
+ if reraise:
87
+ raise exc
88
+ logger.error("Error suppressed: continuing despite raised exception", exc_info=exc)
89
+
90
+ def is_online(host: str) -> bool:
91
+ "Use OS's `ping` cmd to check if `host` is online."
92
+ command = ["ping", "-n" if "win" in sys.platform else "-c", "1", host]
93
+ try:
94
+ return subprocess.call(command, stdout=subprocess.PIPE, timeout=1.0) == 0
95
+ except subprocess.TimeoutExpired:
96
+ return False
97
+
98
+
99
+ def unc_to_local(path: pathlib.Path) -> pathlib.Path:
100
+ "Convert UNC path to local path if on Windows."
101
+ if "win" not in sys.platform:
102
+ return path
103
+ comp = os.environ["COMPUTERNAME"]
104
+ if comp in path.drive:
105
+ drive = path.drive.split("\\")[-1]
106
+ drive = drive[:-1] if drive[-1] == "$" else drive
107
+ drive = drive + ":" if drive[-1] != ":" else drive
108
+ drive += "\\"
109
+ path = pathlib.Path(drive, path.relative_to(path.drive))
110
+ return path
111
+
112
+
113
+ def free_gb(path: str | bytes | os.PathLike) -> float:
114
+ "Return free space at `path`, to .1 GB. Raises FileNotFoundError if `path` not accessible."
115
+ path = pathlib.Path(path)
116
+ path = unc_to_local(path)
117
+ return round(shutil.disk_usage(path).free / 1e9, 1)
118
+
119
+
120
+ def get_files_created_between(
121
+ path: str | bytes | os.PathLike,
122
+ glob: str = "*",
123
+ start: float | datetime.datetime = 0,
124
+ end: Optional[float | datetime.datetime] = None,
125
+ ) -> list[pathlib.Path]:
126
+ path = pathlib.Path(path)
127
+ if not path.is_dir():
128
+ path = path.parent
129
+ if not end:
130
+ end = time.time()
131
+ start = start.timestamp() if isinstance(start, datetime.datetime) else start
132
+ end = end.timestamp() if isinstance(end, datetime.datetime) else end
133
+ ctime = lambda x: x.stat().st_ctime
134
+ files = (file for file in path.glob(glob) if int(start) <= ctime(file) <= end)
135
+ return sorted(files, key=ctime)
136
+
137
+
138
+ def is_file_growing(path: str | bytes | os.PathLike) -> bool:
139
+ "Compares size of most recent .sync data file at two time-points - will block for up to 20s depending on file-size."
140
+ path = pathlib.Path(path)
141
+ size_0 = path.stat().st_size
142
+ # for sync: file is appended periodically in chunks that scale non-linearly with size
143
+ if ".sync" == path.suffix:
144
+ time.sleep(2 * math.log10(size_0))
145
+ else:
146
+ time.sleep(0.5 * math.log10(size_0))
147
+ if path.stat().st_size == size_0:
148
+ return False
149
+ return True
150
+
151
+
152
+ def normalize_time(t) -> str:
153
+ """
154
+ >>> normalize_time(datetime.datetime(2023, 2, 14, 13, 30, 00))
155
+ '20230214133000'
156
+ >>> normalize_time(1676410200.0)
157
+ '20230214133000'
158
+ >>> normalize_time(1676410200)
159
+ '20230214133000'
160
+ >>> normalize_time('1676410200.0')
161
+ '20230214133000'
162
+ >>> normalize_time('1676410200')
163
+ '20230214133000'
164
+ >>> normalize_time('2023-02-14T13:30:00')
165
+ '20230214133000'
166
+ """
167
+ # moved to np_config Feb 2023
168
168
  return np_config.normalize_time(t)
@@ -1,12 +1,13 @@
1
- Metadata-Version: 2.1
1
+ Metadata-Version: 2.4
2
2
  Name: np-services
3
- Version: 0.1.69
3
+ Version: 0.1.70
4
4
  Summary: Tools for interfacing with devices and services used in Mindscope Neuropixels experiments at the Allen Institute.
5
- Author-Email: bjhardcastle <ben.hardcastle@alleninstitute.org>
5
+ Author-email: bjhardcastle <ben.hardcastle@alleninstitute.org>
6
6
  Classifier: Programming Language :: Python :: 3
7
7
  Classifier: License :: OSI Approved :: MIT License
8
8
  Classifier: Operating System :: OS Independent
9
9
  Requires-Python: <4.0,>=3.11
10
+ Description-Content-Type: text/markdown
10
11
  Requires-Dist: requests<3,>=2
11
12
  Requires-Dist: np-session>=0.6.40
12
13
  Requires-Dist: pyzmq
@@ -19,7 +20,6 @@ Requires-Dist: npc-sync>=0.1.13
19
20
  Requires-Dist: npc-ephys>=0.1.7
20
21
  Requires-Dist: npc-stim>=0.1.5
21
22
  Requires-Dist: npc-mvr>=0.1.2
22
- Description-Content-Type: text/markdown
23
23
 
24
24
  # service usage
25
- ![Services](./services.drawio.svg)
25
+ ![Services](./services.drawio.svg)
@@ -0,0 +1,15 @@
1
+ np_services/__init__.py,sha256=LV0k1Xgx9KP4r0EpSbTEhofHT53UO7E-GFG7Wgl7st0,291
2
+ np_services/open_ephys.py,sha256=30zpg31MkfomresRaUSLAVjN2jRpMQvWNlkBcmM5pJM,10623
3
+ np_services/protocols.py,sha256=bky_SreNzsDITb8RG6NiwMV1oqa7wJiuyDUvKn-Z4hg,5366
4
+ np_services/proxies.py,sha256=4hx1blCb5cN8kidOT9byEUpivOysvM36F_rCCuoKSRw,54422
5
+ np_services/stim_computer_theme_changer.py,sha256=y_v-m0h35m5n1kGWF_p_pRi6hKz_tHsrOKhzpWt8msw,1993
6
+ np_services/utils.py,sha256=w7uZX6IHcLO65aKPCHqRn_2Wr1qMjgKeaqhvaHxMFjE,5603
7
+ np_services/resources/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
8
+ np_services/resources/mvr_connector.py,sha256=2kRSKiWdF1CgALvsK3EAy8Xia659yJ8taCLzbaTpe14,7970
9
+ np_services/resources/zro.py,sha256=-1a6knlpLnNb-muJsebeW4hZmDnUXj6ThdbHm8641JA,9921
10
+ np_services/scripts/pretest.py,sha256=5n7DnJpWlubAQKwOqOhGj1xr18R4uu-IQXV4ABTyAtg,15596
11
+ np_services-0.1.70.dist-info/METADATA,sha256=dsvTLyZWLDKmIbZX3Qnn66NvVSt1-K4kARy3TDm6Fvk,881
12
+ np_services-0.1.70.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
13
+ np_services-0.1.70.dist-info/entry_points.txt,sha256=I4h7Ci2KAFSwWRSd6-ZBTpyTbEQMCBe86zwhnROd6Oc,84
14
+ np_services-0.1.70.dist-info/top_level.txt,sha256=JT1ozakOjqY1JyPkaLl69-9du_eSxA2KsfUKjuzQ9zc,12
15
+ np_services-0.1.70.dist-info/RECORD,,
@@ -1,4 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: pdm-backend (2.3.0)
2
+ Generator: setuptools (80.10.2)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
+
@@ -1,3 +1,3 @@
1
1
  [console_scripts]
2
2
  pretest = np_services.scripts.pretest:main
3
-
3
+ task = poethepoet:main
@@ -0,0 +1 @@
1
+ np_services
@@ -1,2 +0,0 @@
1
- # Automatically created by mypy
2
- *
@@ -1 +0,0 @@
1
- {".class": "MypyFile", "_fullname": "__future__", "future_import_flags": [], "is_partial_stub_package": false, "is_stub": true, "names": {".class": "SymbolTable", "TypeAlias": {".class": "SymbolTableNode", "cross_ref": "typing_extensions.TypeAlias", "kind": "Gdef", "module_hidden": true, "module_public": false}, "_Feature": {".class": "SymbolTableNode", "kind": "Gdef", "module_public": false, "node": {".class": "TypeInfo", "_promote": [], "abstract_attributes": [], "bases": ["builtins.object"], "declared_metaclass": null, "defn": {".class": "ClassDef", "fullname": "__future__._Feature", "name": "_Feature", "type_vars": []}, "deletable_attributes": [], "flags": [], "fullname": "__future__._Feature", "has_param_spec_type": false, "metaclass_type": null, "metadata": {}, "module_name": "__future__", "mro": ["__future__._Feature", "builtins.object"], "names": {".class": "SymbolTable", "__init__": {".class": "SymbolTableNode", "kind": "Mdef", "node": {".class": "FuncDef", "abstract_status": 0, "arg_kinds": [0, 0, 0, 0], "arg_names": ["self", "optionalRelease", "mandatoryRelease", "compiler_flag"], "flags": [], "fullname": "__future__._Feature.__init__", "name": "__init__", "type": {".class": "CallableType", "arg_kinds": [0, 0, 0, 0], "arg_names": ["self", "optionalRelease", "mandatoryRelease", "compiler_flag"], "arg_types": ["__future__._Feature", {".class": "TypeAliasType", "args": [], "type_ref": "__future__._VersionInfo"}, {".class": "UnionType", "items": [{".class": "TypeAliasType", "args": [], "type_ref": "__future__._VersionInfo"}, {".class": "NoneType"}]}, "builtins.int"], "bound_args": [], "def_extras": {"first_arg": "self"}, "fallback": "builtins.function", "from_concatenate": false, "implicit": false, "is_ellipsis_args": false, "name": "__init__ of _Feature", "ret_type": {".class": "NoneType"}, "type_guard": null, "unpack_kwargs": false, "variables": []}}}, "compiler_flag": {".class": "SymbolTableNode", "kind": "Mdef", "node": {".class": "Var", "flags": ["is_initialized_in_class", "is_ready"], "fullname": "__future__._Feature.compiler_flag", "name": "compiler_flag", "type": "builtins.int"}}, "getMandatoryRelease": {".class": "SymbolTableNode", "kind": "Mdef", "node": {".class": "FuncDef", "abstract_status": 0, "arg_kinds": [0], "arg_names": ["self"], "flags": [], "fullname": "__future__._Feature.getMandatoryRelease", "name": "getMandatoryRelease", "type": {".class": "CallableType", "arg_kinds": [0], "arg_names": ["self"], "arg_types": ["__future__._Feature"], "bound_args": [], "def_extras": {"first_arg": "self"}, "fallback": "builtins.function", "from_concatenate": false, "implicit": false, "is_ellipsis_args": false, "name": "getMandatoryRelease of _Feature", "ret_type": {".class": "UnionType", "items": [{".class": "TypeAliasType", "args": [], "type_ref": "__future__._VersionInfo"}, {".class": "NoneType"}]}, "type_guard": null, "unpack_kwargs": false, "variables": []}}}, "getOptionalRelease": {".class": "SymbolTableNode", "kind": "Mdef", "node": {".class": "FuncDef", "abstract_status": 0, "arg_kinds": [0], "arg_names": ["self"], "flags": [], "fullname": "__future__._Feature.getOptionalRelease", "name": "getOptionalRelease", "type": {".class": "CallableType", "arg_kinds": [0], "arg_names": ["self"], "arg_types": ["__future__._Feature"], "bound_args": [], "def_extras": {"first_arg": "self"}, "fallback": "builtins.function", "from_concatenate": false, "implicit": false, "is_ellipsis_args": false, "name": "getOptionalRelease of _Feature", "ret_type": {".class": "TypeAliasType", "args": [], "type_ref": "__future__._VersionInfo"}, "type_guard": null, "unpack_kwargs": false, "variables": []}}}}, "slots": null, "tuple_type": null, "type_vars": [], "typeddict_type": null}}, "_VersionInfo": {".class": "SymbolTableNode", "kind": "Gdef", "module_public": false, "node": {".class": "TypeAlias", "alias_tvars": [], "column": 0, "fullname": "__future__._VersionInfo", "line": 3, "no_args": false, "normalized": false, "target": {".class": "TupleType", "implicit": false, "items": ["builtins.int", "builtins.int", "builtins.int", "builtins.str", "builtins.int"], "partial_fallback": {".class": "Instance", "args": [{".class": "AnyType", "missing_import_name": null, "source_any": null, "type_of_any": 6}], "type_ref": "builtins.tuple"}}}}, "__all__": {".class": "SymbolTableNode", "kind": "Gdef", "module_public": false, "node": {".class": "Var", "flags": ["is_inferred", "has_explicit_value"], "fullname": "__future__.__all__", "name": "__all__", "type": {".class": "Instance", "args": ["builtins.str"], "type_ref": "builtins.list"}}}, "__annotations__": {".class": "SymbolTableNode", "kind": "Gdef", "module_public": false, "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.__annotations__", "name": "__annotations__", "type": {".class": "Instance", "args": ["builtins.str", {".class": "AnyType", "missing_import_name": null, "source_any": null, "type_of_any": 6}], "type_ref": "builtins.dict"}}}, "__doc__": {".class": "SymbolTableNode", "kind": "Gdef", "module_public": false, "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.__doc__", "name": "__doc__", "type": "builtins.str"}}, "__file__": {".class": "SymbolTableNode", "kind": "Gdef", "module_public": false, "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.__file__", "name": "__file__", "type": "builtins.str"}}, "__name__": {".class": "SymbolTableNode", "kind": "Gdef", "module_public": false, "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.__name__", "name": "__name__", "type": "builtins.str"}}, "__package__": {".class": "SymbolTableNode", "kind": "Gdef", "module_public": false, "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.__package__", "name": "__package__", "type": "builtins.str"}}, "absolute_import": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.absolute_import", "name": "absolute_import", "type": "__future__._Feature"}}, "all_feature_names": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.all_feature_names", "name": "all_feature_names", "type": {".class": "Instance", "args": ["builtins.str"], "type_ref": "builtins.list"}}}, "annotations": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.annotations", "name": "annotations", "type": "__future__._Feature"}}, "barry_as_FLUFL": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.barry_as_FLUFL", "name": "barry_as_FLUFL", "type": "__future__._Feature"}}, "division": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.division", "name": "division", "type": "__future__._Feature"}}, "generator_stop": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.generator_stop", "name": "generator_stop", "type": "__future__._Feature"}}, "generators": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.generators", "name": "generators", "type": "__future__._Feature"}}, "nested_scopes": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.nested_scopes", "name": "nested_scopes", "type": "__future__._Feature"}}, "print_function": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.print_function", "name": "print_function", "type": "__future__._Feature"}}, "unicode_literals": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.unicode_literals", "name": "unicode_literals", "type": "__future__._Feature"}}, "with_statement": {".class": "SymbolTableNode", "kind": "Gdef", "node": {".class": "Var", "flags": ["is_ready"], "fullname": "__future__.with_statement", "name": "with_statement", "type": "__future__._Feature"}}}, "path": "C:\\Users\\ben.hardcastle\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\np-workflows-S6vpCEsL-py3.9\\lib\\site-packages\\mypy\\typeshed\\stdlib\\__future__.pyi"}
@@ -1 +0,0 @@
1
- {"data_mtime": 1675300530, "dep_lines": [1, 1, 1, 1], "dep_prios": [5, 5, 30, 30], "dependencies": ["typing_extensions", "builtins", "abc", "typing"], "hash": "b3e63c2093f92f412cc06fd0491ff110db6df5d102d08b4bfdab25680d5498c1", "id": "__future__", "ignore_all": true, "interface_hash": "ada412cc312c48519ba6e5e78d2a06593177b9f49c1d84f8560913c257d35f7b", "mtime": 1674086803, "options": {"allow_redefinition": false, "allow_untyped_globals": false, "always_false": [], "always_true": [], "bazel": false, "check_untyped_defs": false, "disable_bytearray_promotion": false, "disable_error_code": [], "disable_memoryview_promotion": false, "disabled_error_codes": [], "disallow_any_decorated": false, "disallow_any_explicit": false, "disallow_any_expr": false, "disallow_any_generics": false, "disallow_any_unimported": false, "disallow_incomplete_defs": false, "disallow_subclassing_any": false, "disallow_untyped_calls": false, "disallow_untyped_decorators": false, "disallow_untyped_defs": false, "enable_error_code": [], "enabled_error_codes": [], "follow_imports": "silent", "follow_imports_for_stubs": false, "ignore_errors": false, "ignore_missing_imports": true, "implicit_optional": false, "implicit_reexport": true, "local_partial_types": false, "mypyc": false, "platform": "win32", "plugins": [], "strict_concatenate": false, "strict_equality": false, "strict_optional": true, "warn_no_return": true, "warn_return_any": false, "warn_unreachable": false, "warn_unused_ignores": false}, "path": "C:\\Users\\ben.hardcastle\\AppData\\Local\\pypoetry\\Cache\\virtualenvs\\np-workflows-S6vpCEsL-py3.9\\lib\\site-packages\\mypy\\typeshed\\stdlib\\__future__.pyi", "plugin_data": null, "size": 951, "suppressed": [], "version_id": "0.991"}