apsbits 1.0.2__tar.gz → 1.0.3__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 (128) hide show
  1. {apsbits-1.0.2 → apsbits-1.0.3}/.github/workflows/code.yml +1 -1
  2. {apsbits-1.0.2/apsbits.egg-info → apsbits-1.0.3}/PKG-INFO +1 -1
  3. {apsbits-1.0.2 → apsbits-1.0.3/apsbits.egg-info}/PKG-INFO +1 -1
  4. {apsbits-1.0.2 → apsbits-1.0.3}/apsbits.egg-info/SOURCES.txt +3 -2
  5. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/_version.py +2 -2
  6. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/api/run_instrument.py +1 -1
  7. {apsbits-1.0.2/src/apsbits/demo_instrument → apsbits-1.0.3/src/apsbits}/configs/logging.yml +0 -1
  8. apsbits-1.0.2/src/apsbits/utils/make_devices.py → apsbits-1.0.3/src/apsbits/core/instrument_init.py +49 -81
  9. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/core/run_engine_init.py +4 -1
  10. apsbits-1.0.3/src/apsbits/demo_instrument/__init__.py +9 -0
  11. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/configs/iconfig.yml +0 -15
  12. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/plans/sim_plans.py +1 -1
  13. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/startup.py +22 -10
  14. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/tests/conftest.py +1 -1
  15. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/tests/test_delete_instrument.py +1 -1
  16. apsbits-1.0.3/src/apsbits/tests/test_make_devices.py +28 -0
  17. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/utils/controls_setup.py +2 -6
  18. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/utils/logging_setup.py +22 -9
  19. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/utils/sim_creator.py +0 -3
  20. apsbits-1.0.2/src/apsbits/demo_instrument/__init__.py +0 -22
  21. {apsbits-1.0.2 → apsbits-1.0.3}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
  22. {apsbits-1.0.2 → apsbits-1.0.3}/.github/ISSUE_TEMPLATE/config.yml +0 -0
  23. {apsbits-1.0.2 → apsbits-1.0.3}/.github/ISSUE_TEMPLATE/feature_request.md +0 -0
  24. {apsbits-1.0.2 → apsbits-1.0.3}/.github/ISSUE_TEMPLATE/other.md +0 -0
  25. {apsbits-1.0.2 → apsbits-1.0.3}/.github/ISSUE_TEMPLATE/question-issue-template.md +0 -0
  26. {apsbits-1.0.2 → apsbits-1.0.3}/.github/PULL_REQUEST_TEMPLATE.md +0 -0
  27. {apsbits-1.0.2 → apsbits-1.0.3}/.github/dependabot.yml +0 -0
  28. {apsbits-1.0.2 → apsbits-1.0.3}/.github/workflows/docs.yml +0 -0
  29. {apsbits-1.0.2 → apsbits-1.0.3}/.github/workflows/pypi.yml +0 -0
  30. {apsbits-1.0.2 → apsbits-1.0.3}/.gitignore +0 -0
  31. {apsbits-1.0.2 → apsbits-1.0.3}/.pre-commit-config.yaml +0 -0
  32. {apsbits-1.0.2 → apsbits-1.0.3}/HISTORY.rst +0 -0
  33. {apsbits-1.0.2 → apsbits-1.0.3}/LICENSE +0 -0
  34. {apsbits-1.0.2 → apsbits-1.0.3}/README.md +0 -0
  35. {apsbits-1.0.2 → apsbits-1.0.3}/apsbits.egg-info/dependency_links.txt +0 -0
  36. {apsbits-1.0.2 → apsbits-1.0.3}/apsbits.egg-info/entry_points.txt +0 -0
  37. {apsbits-1.0.2 → apsbits-1.0.3}/apsbits.egg-info/requires.txt +0 -0
  38. {apsbits-1.0.2 → apsbits-1.0.3}/apsbits.egg-info/top_level.txt +0 -0
  39. {apsbits-1.0.2 → apsbits-1.0.3}/docs/Makefile +0 -0
  40. {apsbits-1.0.2 → apsbits-1.0.3}/docs/make.bat +0 -0
  41. {apsbits-1.0.2 → apsbits-1.0.3}/docs/resources/create-repository-name.webp +0 -0
  42. {apsbits-1.0.2 → apsbits-1.0.3}/docs/resources/create-repository-owner.webp +0 -0
  43. {apsbits-1.0.2 → apsbits-1.0.3}/docs/resources/demo.ipynb +0 -0
  44. {apsbits-1.0.2 → apsbits-1.0.3}/docs/resources/use-this-template-button.webp +0 -0
  45. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/_static/.gitkeep +0 -0
  46. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/api.rst +0 -0
  47. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/core.rst +0 -0
  48. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/demo_instrument.rst +0 -0
  49. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/demo_qserver.rst +0 -0
  50. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.core.best_effort_init.rst +0 -0
  51. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.core.catalog_init.rst +0 -0
  52. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.core.run_engine_init.rst +0 -0
  53. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_instrument.callbacks.nexus_data_file_writer.rst +0 -0
  54. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_instrument.callbacks.rst +0 -0
  55. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_instrument.callbacks.spec_data_file_writer.rst +0 -0
  56. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_instrument.configs.rst +0 -0
  57. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_instrument.devices.rst +0 -0
  58. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_instrument.plans.dm_plans.rst +0 -0
  59. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_instrument.plans.rst +0 -0
  60. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_instrument.plans.sim_plans.rst +0 -0
  61. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_instrument.rst +0 -0
  62. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_instrument.startup.rst +0 -0
  63. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.demo_qserver.rst +0 -0
  64. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.utils.aps_functions.rst +0 -0
  65. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.utils.config_loaders.rst +0 -0
  66. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.utils.controls_setup.rst +0 -0
  67. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.utils.helper_functions.rst +0 -0
  68. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.utils.logging_setup.rst +0 -0
  69. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.utils.metadata.rst +0 -0
  70. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/generated/apsbits.utils.stored_dict.rst +0 -0
  71. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/index.rst +0 -0
  72. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/api/utils.rst +0 -0
  73. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/bits_overview.rst +0 -0
  74. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/conf.py +0 -0
  75. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/deprecated/console.rst +0 -0
  76. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/deprecated/logging_config.rst +0 -0
  77. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/deprecated/notebook.rst +0 -0
  78. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/deprecated/script.rst +0 -0
  79. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/guides/creating_devices.rst +0 -0
  80. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/guides/creating_instrument.rst +0 -0
  81. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/guides/developing_bits.rst +0 -0
  82. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/guides/dm.md +0 -0
  83. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/guides/index.rst +0 -0
  84. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/guides/qserver.rst +0 -0
  85. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/guides/qserver_service.rst +0 -0
  86. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/guides/sessions.rst +0 -0
  87. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/guides/setting_iconfig.rst +0 -0
  88. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/guides/template_creation.rst +0 -0
  89. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/history.rst +0 -0
  90. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/index.rst +0 -0
  91. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/install.rst +0 -0
  92. {apsbits-1.0.2 → apsbits-1.0.3}/docs/source/license.rst +0 -0
  93. {apsbits-1.0.2 → apsbits-1.0.3}/pyproject.toml +0 -0
  94. {apsbits-1.0.2 → apsbits-1.0.3}/setup.cfg +0 -0
  95. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/__init__.py +0 -0
  96. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/api/__init__.py +0 -0
  97. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/api/create_new_instrument.py +0 -0
  98. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/api/delete_instrument.py +0 -0
  99. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/core/__init__.py +0 -0
  100. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/core/best_effort_init.py +0 -0
  101. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/core/catalog_init.py +0 -0
  102. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/README.md +0 -0
  103. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/callbacks/__init__.py +0 -0
  104. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/callbacks/nexus_data_file_writer.py +0 -0
  105. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/callbacks/spec_data_file_writer.py +0 -0
  106. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/configs/__init__.py +0 -0
  107. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/configs/devices.yml +0 -0
  108. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/configs/devices_aps_only.yml +0 -0
  109. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/devices/__init__.py +0 -0
  110. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/plans/__init__.py +0 -0
  111. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/plans/dm_plans.py +0 -0
  112. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/suspenders/__init__.py +0 -0
  113. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_instrument/utils/__init__.py +0 -0
  114. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_qserver/qs-config.yml +0 -0
  115. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_qserver/qs_host.sh +0 -0
  116. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/demo_qserver/user_group_permissions.yaml +0 -0
  117. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/tests/__init__.py +0 -0
  118. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/tests/test_config.py +0 -0
  119. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/tests/test_device_factories.py +0 -0
  120. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/tests/test_general.py +0 -0
  121. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/tests/test_run_instrument.py +0 -0
  122. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/tests/test_stored_dict.py +0 -0
  123. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/utils/__init__.py +0 -0
  124. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/utils/aps_functions.py +0 -0
  125. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/utils/config_loaders.py +0 -0
  126. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/utils/helper_functions.py +0 -0
  127. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/utils/metadata.py +0 -0
  128. {apsbits-1.0.2 → apsbits-1.0.3}/src/apsbits/utils/stored_dict.py +0 -0
@@ -136,7 +136,7 @@ jobs:
136
136
  shell: bash -l {0}
137
137
  run: |
138
138
  set -vxeuo pipefail
139
- ipython -c "from apsbits.demo_instrument.startup import *; RE(make_devices())"
139
+ ipython -c "from apsbits.demo_instrument.startup import *"
140
140
 
141
141
  # https://coveralls-python.readthedocs.io/en/latest/usage/configuration.html#github-actions-support
142
142
  coveralls:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apsbits
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: Model of a Bluesky Data Acquisition Instrument in console, notebook, & queueserver.
5
5
  Author-email: Eric Codrea <ecodrea@anl.gov>, Pete Jemian <prjemian+instrument@gmail.com>, Rafael Vescovi <rvescovi@anl.gov>
6
6
  Maintainer-email: Eric Codrea <ecodrea@anl.gov>, Pete Jemian <prjemian+instrument@gmail.com>, Rafael Vescovi <rvescovi@anl.gov>
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: apsbits
3
- Version: 1.0.2
3
+ Version: 1.0.3
4
4
  Summary: Model of a Bluesky Data Acquisition Instrument in console, notebook, & queueserver.
5
5
  Author-email: Eric Codrea <ecodrea@anl.gov>, Pete Jemian <prjemian+instrument@gmail.com>, Rafael Vescovi <rvescovi@anl.gov>
6
6
  Maintainer-email: Eric Codrea <ecodrea@anl.gov>, Pete Jemian <prjemian+instrument@gmail.com>, Rafael Vescovi <rvescovi@anl.gov>
@@ -80,9 +80,11 @@ src/apsbits/api/__init__.py
80
80
  src/apsbits/api/create_new_instrument.py
81
81
  src/apsbits/api/delete_instrument.py
82
82
  src/apsbits/api/run_instrument.py
83
+ src/apsbits/configs/logging.yml
83
84
  src/apsbits/core/__init__.py
84
85
  src/apsbits/core/best_effort_init.py
85
86
  src/apsbits/core/catalog_init.py
87
+ src/apsbits/core/instrument_init.py
86
88
  src/apsbits/core/run_engine_init.py
87
89
  src/apsbits/demo_instrument/README.md
88
90
  src/apsbits/demo_instrument/__init__.py
@@ -94,7 +96,6 @@ src/apsbits/demo_instrument/configs/__init__.py
94
96
  src/apsbits/demo_instrument/configs/devices.yml
95
97
  src/apsbits/demo_instrument/configs/devices_aps_only.yml
96
98
  src/apsbits/demo_instrument/configs/iconfig.yml
97
- src/apsbits/demo_instrument/configs/logging.yml
98
99
  src/apsbits/demo_instrument/devices/__init__.py
99
100
  src/apsbits/demo_instrument/plans/__init__.py
100
101
  src/apsbits/demo_instrument/plans/dm_plans.py
@@ -110,6 +111,7 @@ src/apsbits/tests/test_config.py
110
111
  src/apsbits/tests/test_delete_instrument.py
111
112
  src/apsbits/tests/test_device_factories.py
112
113
  src/apsbits/tests/test_general.py
114
+ src/apsbits/tests/test_make_devices.py
113
115
  src/apsbits/tests/test_run_instrument.py
114
116
  src/apsbits/tests/test_stored_dict.py
115
117
  src/apsbits/utils/__init__.py
@@ -118,7 +120,6 @@ src/apsbits/utils/config_loaders.py
118
120
  src/apsbits/utils/controls_setup.py
119
121
  src/apsbits/utils/helper_functions.py
120
122
  src/apsbits/utils/logging_setup.py
121
- src/apsbits/utils/make_devices.py
122
123
  src/apsbits/utils/metadata.py
123
124
  src/apsbits/utils/sim_creator.py
124
125
  src/apsbits/utils/stored_dict.py
@@ -17,5 +17,5 @@ __version__: str
17
17
  __version_tuple__: VERSION_TUPLE
18
18
  version_tuple: VERSION_TUPLE
19
19
 
20
- __version__ = version = '1.0.2'
21
- __version_tuple__ = version_tuple = (1, 0, 2)
20
+ __version__ = version = '1.0.3'
21
+ __version_tuple__ = version_tuple = (1, 0, 3)
@@ -16,7 +16,7 @@ from typing import Dict
16
16
  from typing import Optional
17
17
  from typing import Tuple
18
18
 
19
- from apsbits.utils.controls_setup import oregistry as Registry
19
+ from apsbits.core.instrument_init import oregistry as Registry
20
20
 
21
21
 
22
22
  def run_instrument_startup(package_name: str) -> Tuple[bool, Optional[Dict[str, Any]]]:
@@ -37,5 +37,4 @@ modules:
37
37
  bluesky.RE: warning
38
38
  caproto: warning
39
39
  databroker: warning
40
- instrument: bsdev
41
40
  ophyd: warning
@@ -21,10 +21,8 @@ from apstools.plans import run_blocking_function
21
21
  from apstools.utils import dynamic_import
22
22
  from bluesky import plan_stubs as bps
23
23
 
24
- from apsbits.utils.aps_functions import host_on_aps_subnet
25
24
  from apsbits.utils.config_loaders import get_config
26
25
  from apsbits.utils.config_loaders import load_config_yaml
27
- from apsbits.utils.controls_setup import oregistry # noqa: F401
28
26
 
29
27
  logger = logging.getLogger(__name__)
30
28
  logger.bsdev(__file__)
@@ -32,27 +30,21 @@ logger.bsdev(__file__)
32
30
  MAIN_NAMESPACE = "__main__"
33
31
 
34
32
 
35
- def _get_make_devices_log_level() -> int:
36
- """(internal) User choice for log level used in 'make_devices()'."""
37
- level = get_config().get("MAKE_DEVICES", {}).get("LOG_LEVEL", "info")
38
- if isinstance(level, str):
39
- # Allow log level as str or int in iconfig.yml.
40
- level = logging._nameToLevel[level.upper()]
41
- return level
42
-
43
-
44
33
  def make_devices(
45
- *, pause: float = 1, clear: bool = True, file: str | pathlib.Path | None = None
34
+ *,
35
+ pause: float = 1,
36
+ clear: bool = True,
37
+ file: str,
38
+ path: str | pathlib.Path | None = None,
46
39
  ):
47
40
  """
48
41
  (plan stub) Create the ophyd-style controls for this instrument.
49
42
 
50
- Feel free to modify this plan to suit the needs of your instrument.
51
-
52
43
  EXAMPLE::
53
44
 
54
- RE(make_devices()) # Use default iconfig.yml
55
- RE(make_devices(file="custom_devices.yml")) # Use custom devices file
45
+ RE(make_devices(file="custom_devices.yml")) #Use custom devices file
46
+ RE(make_devices(path="custom_device_path",
47
+ file="custom_devices.yml")) #Use custom path to find device file
56
48
 
57
49
  PARAMETERS
58
50
 
@@ -65,78 +57,54 @@ def make_devices(
65
57
  If provided, this file will be used instead of the default iconfig.yml.
66
58
  If None (default), uses the standard iconfig.yml configuration.
67
59
 
60
+ path: str | pathlib.Path | None
68
61
  """
62
+
69
63
  logger.debug("(Re)Loading local control objects.")
70
64
 
71
65
  if clear:
72
- log_level = _get_make_devices_log_level()
73
-
74
66
  main_namespace = sys.modules[MAIN_NAMESPACE]
67
+
68
+ # Clear the oregistry and remove any devices registered previously.
75
69
  for dev_name in oregistry.device_names:
76
70
  # Remove from __main__ namespace any devices registered previously.
77
71
  if hasattr(main_namespace, dev_name):
78
- logger.log(log_level, "Removing %r from %r", dev_name, MAIN_NAMESPACE)
72
+ logger.info("Removing %r from %r", dev_name, MAIN_NAMESPACE)
73
+
79
74
  delattr(main_namespace, dev_name)
80
75
 
81
76
  oregistry.clear()
82
77
 
83
- if file is not None:
84
- # Use the provided file directly
85
- device_path = pathlib.Path(file)
86
- if not device_path.exists():
87
- logger.error("Device file not found: %s", device_path)
88
- return
89
- logger.info("Loading device file: %s", device_path)
90
- try:
91
- yield from run_blocking_function(_loader, device_path, main=True)
92
- except Exception as e:
93
- logger.error("Error loading device file %s: %s", device_path, str(e))
94
- return
78
+ if path is not None and file is None:
79
+ raise ValueError(
80
+ "When a custom path is provided, a specific device file must"
81
+ " also be provided"
82
+ )
83
+
84
+ if path is not None:
85
+ configs_path = pathlib.Path(path)
86
+ print(f"\n\nConfigs path: {configs_path}\n\n")
87
+
95
88
  else:
96
- # Use standard iconfig.yml configuration
97
89
  iconfig = get_config()
98
-
99
90
  instrument_path = pathlib.Path(iconfig.get("INSTRUMENT_PATH")).parent
100
91
  configs_path = instrument_path / "configs"
101
92
 
102
- # Get device files and ensure it's a list
103
- device_files = iconfig.get("DEVICES_FILES", [])
104
- if isinstance(device_files, str):
105
- device_files = [device_files]
106
- logger.debug("Loading device files: %r", device_files)
107
-
108
- # Load each device file
109
- for device_file in device_files:
110
- device_path = configs_path / device_file
111
- if not device_path.exists():
112
- logger.error("Device file not found: %s", device_path)
113
- continue
114
- logger.info("Loading device file: %s", device_path)
115
- try:
116
- yield from run_blocking_function(_loader, device_path, main=True)
117
- except Exception as e:
118
- logger.error("Error loading device file %s: %s", device_path, str(e))
119
- continue
120
-
121
- # Handle APS-specific device files if on APS subnet
122
- aps_control_devices_files = iconfig.get("APS_DEVICES_FILES", [])
123
- if isinstance(aps_control_devices_files, str):
124
- aps_control_devices_files = [aps_control_devices_files]
125
-
126
- if aps_control_devices_files and host_on_aps_subnet():
127
- for device_file in aps_control_devices_files:
128
- device_path = configs_path / device_file
129
- if not device_path.exists():
130
- logger.error("APS device file not found: %s", device_path)
131
- continue
132
- logger.info("Loading APS device file: %s", device_path)
133
- try:
134
- yield from run_blocking_function(_loader, device_path, main=True)
135
- except Exception as e:
136
- logger.error(
137
- "Error loading APS device file %s: %s", device_path, str(e)
138
- )
139
- continue
93
+ device_file = file
94
+
95
+ logger.debug("Loading device files: %r", device_file)
96
+
97
+ # Load each device file
98
+ device_path = configs_path / device_file
99
+ if not device_path.exists():
100
+ logger.error("Device file not found: %s", device_path)
101
+
102
+ else:
103
+ logger.info("Loading device file: %s", device_path)
104
+ try:
105
+ yield from run_blocking_function(namespace_loader, device_path, main=True)
106
+ except Exception as e:
107
+ logger.error("Error loading device file %s: %s", device_path, str(e))
140
108
 
141
109
  if pause > 0:
142
110
  logger.debug(
@@ -145,12 +113,10 @@ def make_devices(
145
113
  )
146
114
  yield from bps.sleep(pause)
147
115
 
148
- # Configure any of the controls here, or in plan stubs
149
-
150
116
 
151
- def _loader(yaml_device_file, main=True):
117
+ def namespace_loader(yaml_device_file, main=True):
152
118
  """
153
- Load our ophyd-style controls as described in a YAML file.
119
+ Load our ophyd-style controls as described in a YAML file into the main namespace.
154
120
 
155
121
  PARAMETERS
156
122
 
@@ -162,15 +128,15 @@ def _loader(yaml_device_file, main=True):
162
128
  """
163
129
  logger.debug("Devices file %r.", str(yaml_device_file))
164
130
  t0 = time.time()
165
- _instr.load(yaml_device_file)
166
- logger.info("Devices loaded in %.3f s.", time.time() - t0)
167
131
 
168
- if main:
169
- log_level = _get_make_devices_log_level()
132
+ instrument.load(yaml_device_file)
170
133
 
134
+ logger.info("Devices loaded in %.3f s.", time.time() - t0)
135
+ if main:
171
136
  main_namespace = sys.modules[MAIN_NAMESPACE]
172
137
  for label in oregistry.device_names:
173
- logger.log(log_level, "Adding ophyd device %r to main namespace", label)
138
+ logger.info("Adding ophyd device %r to main namespace", label)
139
+
174
140
  setattr(main_namespace, label, oregistry[label])
175
141
 
176
142
 
@@ -208,4 +174,6 @@ class Instrument(guarneri.Instrument):
208
174
  return devices
209
175
 
210
176
 
211
- _instr = Instrument({}, registry=oregistry) # singleton
177
+ instrument = Instrument({}) # singleton
178
+ oregistry = instrument.devices
179
+ """Registry of all ophyd-style Devices and Signals."""
@@ -34,6 +34,7 @@ def init_RE(
34
34
  iconfig: Dict[str, Any],
35
35
  bec_instance: Optional[Any] = None,
36
36
  cat_instance: Optional[Any] = None,
37
+ **kwargs: Any,
37
38
  ) -> Tuple[bluesky.RunEngine, bluesky.SupplementalData]:
38
39
  """
39
40
  Initialize and configure a Bluesky RunEngine instance.
@@ -55,6 +56,8 @@ def init_RE(
55
56
  to the RunEngine. Defaults to None.
56
57
  cat_instance (Optional[Any]): Instance of a databroker catalog for subscribing
57
58
  to the RunEngine. Defaults to None.
59
+ **kwargs: Additional keyword arguments passed to the RunEngine constructor.
60
+ For example, run_returns_result=True.
58
61
 
59
62
  Returns:
60
63
  Tuple[bluesky.RunEngine, bluesky.SupplementalData]: A tuple containing the
@@ -75,7 +78,7 @@ def init_RE(
75
78
  set_control_layer(control_layer=control_layer)
76
79
  set_timeouts(timeouts=iconfig.get("OPHYD", {}).get("TIMEOUTS", {}))
77
80
 
78
- RE = bluesky.RunEngine()
81
+ RE = bluesky.RunEngine(**kwargs)
79
82
  """The Bluesky RunEngine object."""
80
83
 
81
84
  sd = bluesky.SupplementalData()
@@ -0,0 +1,9 @@
1
+ """
2
+ Demo instrument package.
3
+
4
+ This package provides a demo instrument implementation for testing and development.
5
+ """
6
+
7
+ from apsbits.utils.logging_setup import configure_logging
8
+
9
+ configure_logging()
@@ -29,9 +29,6 @@ RUN_ENGINE:
29
29
  ### Default: False
30
30
  USE_PROGRESS_BAR: false
31
31
 
32
- # Command-line tools, such as %wa, %ct, ...
33
- USE_BLUESKY_MAGICS: true
34
-
35
32
  ### Best Effort Callback Configurations
36
33
  ### Defaults: all true
37
34
  ### except no plots in queueserver
@@ -56,16 +53,6 @@ SPEC_DATA_FILES:
56
53
  ### Use bash shell, deactivate all conda environments, source this file:
57
54
  DM_SETUP_FILE: "/home/dm/etc/dm.setup.sh"
58
55
 
59
- ### Local OPHYD Device Control Yaml
60
- DEVICES_FILES:
61
- - devices.yml
62
- APS_DEVICES_FILES:
63
- - devices_aps_only.yml
64
-
65
- # Log when devices are added to console (__main__ namespace)
66
- MAKE_DEVICES:
67
- LOG_LEVEL: info
68
-
69
56
  # ----------------------------------
70
57
 
71
58
  OPHYD:
@@ -80,6 +67,4 @@ OPHYD:
80
67
  PV_WRITE: *TIMEOUT
81
68
  PV_CONNECTION: *TIMEOUT
82
69
 
83
- # Control detail of exception traces in IPython (console and notebook).
84
- # Options are: 'Plain', 'Context', 'Verbose', 'Minimal', 'Docs'
85
70
  XMODE_DEBUG_LEVEL: Plain
@@ -15,7 +15,7 @@ import logging
15
15
  from bluesky import plan_stubs as bps
16
16
  from bluesky import plans as bp
17
17
 
18
- from apsbits.utils.controls_setup import oregistry
18
+ from apsbits.core.instrument_init import oregistry
19
19
 
20
20
  logger = logging.getLogger(__name__)
21
21
  logger.bsdev(__file__)
@@ -10,32 +10,45 @@ Includes:
10
10
  """
11
11
 
12
12
  import logging
13
+ from pathlib import Path
13
14
 
14
15
  from apsbits.core.best_effort_init import init_bec_peaks
15
16
  from apsbits.core.catalog_init import init_catalog
17
+ from apsbits.core.instrument_init import make_devices
18
+ from apsbits.core.instrument_init import oregistry
16
19
  from apsbits.core.run_engine_init import init_RE
17
20
  from apsbits.utils.aps_functions import aps_dm_setup
21
+ from apsbits.utils.aps_functions import host_on_aps_subnet
18
22
  from apsbits.utils.config_loaders import get_config
19
- from apsbits.utils.controls_setup import oregistry
23
+ from apsbits.utils.config_loaders import load_config
20
24
  from apsbits.utils.helper_functions import register_bluesky_magics
21
25
  from apsbits.utils.helper_functions import running_in_queueserver
22
- from apsbits.utils.make_devices import make_devices
23
26
 
24
27
  logger = logging.getLogger(__name__)
25
28
  logger.bsdev(__file__)
26
29
 
27
- oregistry.clear() # Discard oregistry items loaded above.
30
+ # Get the path to the instrument package
31
+ instrument_path = Path(__file__).parent
32
+
33
+ # Load configuration to be used by the instrument.
34
+ iconfig_path = instrument_path / "configs" / "iconfig.yml"
35
+ load_config(iconfig_path)
28
36
 
29
37
  # Get the configuration
30
38
  iconfig = get_config()
31
39
 
40
+ logger.info("Starting Instrument with iconfig: %s", iconfig_path)
41
+
42
+ # Discard oregistry items loaded above.
43
+ oregistry.clear()
44
+
32
45
  # Configure the session with callbacks, devices, and plans.
33
46
  aps_dm_setup(iconfig.get("DM_SETUP_FILE"))
34
47
 
35
- if iconfig.get("USE_BLUESKY_MAGICS", False):
36
- register_bluesky_magics()
48
+ # Command-line tools, such as %wa, %ct, ...
49
+ register_bluesky_magics()
37
50
 
38
- # Initialize core components
51
+ # Initialize core bluesky components
39
52
  bec, peaks = init_bec_peaks(iconfig)
40
53
  cat = init_catalog(iconfig)
41
54
  RE, sd = init_RE(iconfig, bec_instance=bec, cat_instance=cat)
@@ -54,9 +67,6 @@ if iconfig.get("SPEC_DATA_FILES", {}).get("ENABLE", False):
54
67
 
55
68
  init_specwriter_with_RE(RE)
56
69
 
57
- # Import all plans
58
- from .plans import * # noqa
59
-
60
70
  # These imports must come after the above setup.
61
71
  if running_in_queueserver():
62
72
  ### To make all the standard plans available in QS, import by '*', otherwise import
@@ -72,5 +82,7 @@ else:
72
82
  from bluesky import plan_stubs as bps # noqa: F401
73
83
  from bluesky import plans as bp # noqa: F401
74
84
 
85
+ RE(make_devices(clear=False, file="devices.yml")) # Create the devices.
75
86
 
76
- RE(make_devices(clear=False))
87
+ if host_on_aps_subnet():
88
+ RE(make_devices(clear=False, file="device_aps_only.yml"))
@@ -35,5 +35,5 @@ def runengine_with_devices() -> Any:
35
35
  iconfig_path = instrument_path / "configs" / "iconfig.yml"
36
36
  load_config(iconfig_path)
37
37
 
38
- RE(make_devices())
38
+ RE(make_devices(file="devices.yml"))
39
39
  return RE
@@ -351,7 +351,7 @@ def test_copy_instrument(tmp_path: Path, mock_demo_dirs: tuple[Path, Path]) -> N
351
351
  content = startup_file.read_text()
352
352
  assert "Start Bluesky Data Acquisition sessions of all kinds." in content
353
353
  assert "from apsbits.core.best_effort_init import init_bec_peaks" in content
354
- assert "RE(make_devices(clear=False))" in content
354
+ assert 'RE(make_devices(clear=False, file="devices.yml"))' in content
355
355
 
356
356
 
357
357
  def test_create_qserver(tmp_path: Path, mock_demo_dirs: tuple[Path, Path]) -> None:
@@ -0,0 +1,28 @@
1
+ """
2
+ Test to check if the make_devices function works as expected.
3
+ """
4
+
5
+ import logging
6
+
7
+ from apsbits.demo_instrument.startup import RE
8
+ from apsbits.demo_instrument.startup import make_devices
9
+
10
+
11
+ def test_make_devices_file_name(caplog):
12
+ """
13
+ Test to check if the make_devices function works as expected.
14
+ """
15
+
16
+ # Set the log level to capture INFO messages
17
+ caplog.set_level(logging.INFO)
18
+
19
+ # Run your function
20
+ RE(make_devices(file="devices.yml"))
21
+
22
+ # Expected device names
23
+ expected_devices = ["sim_motor", "shutter", "sim_det"]
24
+
25
+ # Check if all expected device messages are in the log output
26
+ for device in expected_devices:
27
+ expected_message = f"Adding ophyd device '{device}' to main namespace"
28
+ assert any(expected_message in record.message for record in caplog.records)
@@ -15,7 +15,8 @@ from typing import Optional
15
15
 
16
16
  import ophyd
17
17
  from ophyd.signal import EpicsSignalBase
18
- from ophydregistry import Registry
18
+
19
+ from apsbits.core.instrument_init import oregistry
19
20
 
20
21
  logger = logging.getLogger(__name__)
21
22
  logger.bsdev(__file__)
@@ -101,8 +102,3 @@ def set_timeouts(timeouts):
101
102
  write_timeout=timeouts.get("PV_WRITE", DEFAULT_TIMEOUT),
102
103
  connection_timeout=timeouts.get("PV_CONNECTION", DEFAULT_TIMEOUT),
103
104
  )
104
-
105
-
106
- oregistry = Registry(auto_register=True)
107
- """Registry of all ophyd-style Devices and Signals."""
108
- oregistry.warn_duplicates = False
@@ -26,9 +26,7 @@ MB = 1024 * kB
26
26
 
27
27
  BRIEF_DATE = "%a-%H:%M:%S"
28
28
  BRIEF_FORMAT = "%(levelname)-.1s %(asctime)s.%(msecs)03d: %(message)s"
29
- DEFAULT_CONFIG_FILE = (
30
- pathlib.Path(__file__).parent.parent / "demo_instrument" / "configs" / "logging.yml"
31
- )
29
+ DEFAULT_CONFIG_FILE = pathlib.Path(__file__).parent.parent / "configs" / "logging.yml"
32
30
 
33
31
 
34
32
  # Add your custom logging level at the top-level, before configure_logging()
@@ -86,7 +84,7 @@ def addLoggingLevel(levelName, levelNum, methodName=None):
86
84
  addLoggingLevel("BSDEV", logging.INFO - 5)
87
85
 
88
86
 
89
- def configure_logging():
87
+ def configure_logging(extra_logging_configs_path=None):
90
88
  """Configure logging as described in file."""
91
89
  from apsbits.utils.config_loaders import load_config_yaml
92
90
 
@@ -94,13 +92,10 @@ def configure_logging():
94
92
  logger = logging.getLogger(__name__).root
95
93
  logger.debug("logger=%r", logger)
96
94
 
97
- config_file = os.environ.get("BLUESKY_INSTRUMENT_CONFIG_FILE")
98
- if config_file is None:
99
- config_file = DEFAULT_CONFIG_FILE
100
- else:
101
- config_file = pathlib.Path(config_file)
95
+ config_file = DEFAULT_CONFIG_FILE
102
96
 
103
97
  logging_configuration = load_config_yaml(config_file)
98
+
104
99
  for part, cfg in logging_configuration.items():
105
100
  logging.debug("%r - %s", part, cfg)
106
101
 
@@ -116,6 +111,24 @@ def configure_logging():
116
111
  elif part == "modules":
117
112
  _setup_module_logging(cfg)
118
113
 
114
+ if extra_logging_configs_path is not None:
115
+ logging_configuration = load_config_yaml(extra_logging_configs_path)
116
+
117
+ for part, cfg in logging_configuration.items():
118
+ logging.debug("%r - %s", part, cfg)
119
+
120
+ if part == "console_logs":
121
+ _setup_console_logger(logger, cfg)
122
+
123
+ elif part == "file_logs":
124
+ _setup_file_logger(logger, cfg)
125
+
126
+ elif part == "ipython_logs":
127
+ _setup_ipython_logger(logger, cfg)
128
+
129
+ elif part == "modules":
130
+ _setup_module_logging(cfg)
131
+
119
132
 
120
133
  def _setup_console_logger(logger, cfg):
121
134
  """
@@ -21,8 +21,6 @@ import logging
21
21
 
22
22
  from apstools.utils import dynamic_import
23
23
 
24
- from apsbits.utils.controls_setup import oregistry
25
-
26
24
  logger = logging.getLogger(__name__)
27
25
  logger.bsdev(__file__)
28
26
 
@@ -53,7 +51,6 @@ def predefined_device(*, name="", creator=""):
53
51
  if name != "":
54
52
  device.name = name
55
53
  logger.debug(device)
56
- oregistry.register(device)
57
54
  yield device
58
55
 
59
56
 
@@ -1,22 +0,0 @@
1
- """
2
- Demo instrument package.
3
-
4
- This package provides a demo instrument implementation for testing and development.
5
- """
6
-
7
- import logging
8
- from pathlib import Path
9
-
10
- from apsbits.utils.config_loaders import load_config
11
-
12
- logger = logging.getLogger(__name__)
13
- logger.bsdev(__file__)
14
-
15
- # Get the path to the instrument package
16
- instrument_path = Path(__file__).parent
17
-
18
- # Load configuration
19
- iconfig_path = instrument_path / "configs" / "iconfig.yml"
20
- load_config(iconfig_path)
21
-
22
- logger.info("Starting Instrument with iconfig: %s", iconfig_path)
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes