PyroLab 0.3.1__tar.gz → 0.4.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (75) hide show
  1. pyrolab-0.4.0/MANIFEST.in +4 -0
  2. {PyroLab-0.3.1 → pyrolab-0.4.0}/NOTICE.txt +1 -1
  3. pyrolab-0.4.0/PKG-INFO +299 -0
  4. {PyroLab-0.3.1 → pyrolab-0.4.0}/README.md +18 -8
  5. {PyroLab-0.3.1 → pyrolab-0.4.0}/pyproject.toml +33 -14
  6. {PyroLab-0.3.1/src → pyrolab-0.4.0}/pyrolab/__init__.py +56 -7
  7. {PyroLab-0.3.1/src → pyrolab-0.4.0}/pyrolab/api.py +6 -6
  8. {PyroLab-0.3.1/src → pyrolab-0.4.0}/pyrolab/cli.py +220 -98
  9. {PyroLab-0.3.1/src → pyrolab-0.4.0}/pyrolab/configure.py +109 -71
  10. pyrolab-0.4.0/pyrolab/data/wordlist.txt +9890 -0
  11. pyrolab-0.4.0/pyrolab/drivers/VISAResourceExtensions.py +273 -0
  12. pyrolab-0.4.0/pyrolab/drivers/__init__.py +162 -0
  13. pyrolab-0.4.0/pyrolab/drivers/arduino/__init__.py +16 -0
  14. pyrolab-0.4.0/pyrolab/drivers/arduino/arduino.py +190 -0
  15. pyrolab-0.4.0/pyrolab/drivers/cameras/__init__.py +16 -0
  16. pyrolab-0.4.0/pyrolab/drivers/cameras/amcam.py +61 -0
  17. pyrolab-0.4.0/pyrolab/drivers/cameras/sciTSI.py +215 -0
  18. pyrolab-0.4.0/pyrolab/drivers/cameras/thorcam.py +611 -0
  19. pyrolab-0.4.0/pyrolab/drivers/cameras/uc480.py +420 -0
  20. pyrolab-0.4.0/pyrolab/drivers/fpgas/__init__.py +16 -0
  21. pyrolab-0.4.0/pyrolab/drivers/fpgas/analogdiscovery.py +310 -0
  22. pyrolab-0.4.0/pyrolab/drivers/function_generators/__init__.py +16 -0
  23. pyrolab-0.4.0/pyrolab/drivers/function_generators/smcv100b.py +389 -0
  24. pyrolab-0.4.0/pyrolab/drivers/lasers/__init__.py +16 -0
  25. pyrolab-0.4.0/pyrolab/drivers/lasers/ppcl55x.py +653 -0
  26. pyrolab-0.4.0/pyrolab/drivers/lasers/sachertec.py +108 -0
  27. pyrolab-0.4.0/pyrolab/drivers/lasers/tsl550.py +1540 -0
  28. pyrolab-0.4.0/pyrolab/drivers/motion/KMTS25E.py +92 -0
  29. pyrolab-0.4.0/pyrolab/drivers/motion/__init__.py +16 -0
  30. pyrolab-0.4.0/pyrolab/drivers/motion/kinesis/__init__.py +65 -0
  31. pyrolab-0.4.0/pyrolab/drivers/motion/kinesis/bpc303.py +465 -0
  32. pyrolab-0.4.0/pyrolab/drivers/motion/kinesis/kdc101.py +819 -0
  33. pyrolab-0.4.0/pyrolab/drivers/motion/max31x.py +247 -0
  34. pyrolab-0.4.0/pyrolab/drivers/motion/prm1z8.py +54 -0
  35. pyrolab-0.4.0/pyrolab/drivers/motion/z8xx.py +144 -0
  36. pyrolab-0.4.0/pyrolab/drivers/sample.py +300 -0
  37. pyrolab-0.4.0/pyrolab/drivers/scopes/__init__.py +16 -0
  38. pyrolab-0.4.0/pyrolab/drivers/scopes/rohdeschwarz.py +579 -0
  39. pyrolab-0.4.0/pyrolab/drivers/smu/__init__.py +16 -0
  40. pyrolab-0.4.0/pyrolab/drivers/smu/keysight.py +397 -0
  41. {PyroLab-0.3.1/src → pyrolab-0.4.0}/pyrolab/manager.py +138 -85
  42. {PyroLab-0.3.1/src → pyrolab-0.4.0}/pyrolab/nameserver.py +28 -16
  43. {PyroLab-0.3.1/src → pyrolab-0.4.0}/pyrolab/pyrolabd.py +37 -19
  44. {PyroLab-0.3.1/src → pyrolab-0.4.0}/pyrolab/server.py +69 -57
  45. {PyroLab-0.3.1/src → pyrolab-0.4.0}/pyrolab/service.py +13 -7
  46. {PyroLab-0.3.1/src → pyrolab-0.4.0}/pyrolab/utils.py +13 -5
  47. pyrolab-0.4.0/pyrolab.egg-info/PKG-INFO +299 -0
  48. pyrolab-0.4.0/pyrolab.egg-info/SOURCES.txt +62 -0
  49. {PyroLab-0.3.1/src/PyroLab.egg-info → pyrolab-0.4.0/pyrolab.egg-info}/entry_points.txt +0 -1
  50. pyrolab-0.4.0/pyrolab.egg-info/requires.txt +46 -0
  51. pyrolab-0.4.0/pyrolab.egg-info/top_level.txt +1 -0
  52. pyrolab-0.4.0/tests/test_code_interface.py +29 -0
  53. pyrolab-0.4.0/tests/test_configure.py +150 -0
  54. pyrolab-0.4.0/tests/test_daemon.py +24 -0
  55. pyrolab-0.4.0/tests/test_errors.py +0 -0
  56. pyrolab-0.4.0/tests/test_manager.py +0 -0
  57. pyrolab-0.4.0/tests/test_nameserver.py +0 -0
  58. pyrolab-0.4.0/tests/test_pyrolabd.py +0 -0
  59. pyrolab-0.4.0/tests/test_service.py +0 -0
  60. pyrolab-0.4.0/tests/test_utils.py +0 -0
  61. pyrolab-0.4.0/tests/testsrv.py +21 -0
  62. PyroLab-0.3.1/AUTHORS.txt +0 -20
  63. PyroLab-0.3.1/MANIFEST.in +0 -1
  64. PyroLab-0.3.1/PKG-INFO +0 -930
  65. PyroLab-0.3.1/src/PyroLab.egg-info/PKG-INFO +0 -930
  66. PyroLab-0.3.1/src/PyroLab.egg-info/SOURCES.txt +0 -26
  67. PyroLab-0.3.1/src/PyroLab.egg-info/requires.txt +0 -33
  68. PyroLab-0.3.1/src/PyroLab.egg-info/top_level.txt +0 -2
  69. PyroLab-0.3.1/src/pyromonitor/__init__.py +0 -68
  70. PyroLab-0.3.1/src/pyromonitor/cli.py +0 -77
  71. PyroLab-0.3.1/src/pyromonitor/config.py +0 -19
  72. PyroLab-0.3.1/src/pyromonitor/lister.py +0 -131
  73. {PyroLab-0.3.1 → pyrolab-0.4.0}/LICENSE +0 -0
  74. {PyroLab-0.3.1/src/PyroLab.egg-info → pyrolab-0.4.0/pyrolab.egg-info}/dependency_links.txt +0 -0
  75. {PyroLab-0.3.1 → pyrolab-0.4.0}/setup.cfg +0 -0
@@ -0,0 +1,4 @@
1
+ include NOTICE.txt AUTHORS.txt
2
+ graft pyrolab/
3
+ prune pyrolab/data/local/
4
+ global-exclude *.py[cod]
@@ -31,7 +31,7 @@ PPCL55X
31
31
  The code found in the following files were included in Pyrolab with some
32
32
  modifications:
33
33
 
34
- pyrolab/drivers/lasers/pplaser.py
34
+ pyrolab/drivers/lasers/ppcl55x.py
35
35
 
36
36
  The original source is available at
37
37
  https://www.pure-photonics.com/s/ITLA_v3-CUSTOMER.PY
pyrolab-0.4.0/PKG-INFO ADDED
@@ -0,0 +1,299 @@
1
+ Metadata-Version: 2.4
2
+ Name: pyrolab
3
+ Version: 0.4.0
4
+ Summary: A framework for using remote lab instruments as local resources built on Pyro5.
5
+ Author-email: Sequoia Ploeg <sequoiap4@gmail.com>, BYU CamachoLab <camacho@byu.edu>
6
+ Maintainer-email: Sequoia Ploeg <sequoiap4@gmail.com>, BYU CamachoLab <camacho@byu.edu>
7
+ License: GPL-3.0+
8
+ Project-URL: Homepage, https://pyrolab.readthedocs.io/en/latest/
9
+ Project-URL: Documentation, https://pyrolab.readthedocs.io/en/latest/
10
+ Project-URL: Source, https://github.com/BYUCamachoLab/pyrolab
11
+ Project-URL: Bug Reports, https://github.com/BYUCamachoLab/pyrolab/issues
12
+ Project-URL: Research Group, https://camacholab.byu.edu/
13
+ Keywords: PyroLab,Pyro5,Pyro,lab,instrument,remote,resources,framework,laboratory,instrumentation,hardware,science,remote,network,integration
14
+ Classifier: Development Status :: 4 - Beta
15
+ Classifier: Intended Audience :: Education
16
+ Classifier: Intended Audience :: Science/Research
17
+ Classifier: Intended Audience :: Developers
18
+ Classifier: Topic :: Scientific/Engineering
19
+ Classifier: License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)
20
+ Classifier: Programming Language :: Python :: 3
21
+ Classifier: Programming Language :: Python :: 3.9
22
+ Classifier: Programming Language :: Python :: 3.10
23
+ Classifier: Programming Language :: Python :: 3.11
24
+ Classifier: Programming Language :: Python :: 3.12
25
+ Classifier: Programming Language :: Python :: 3.13
26
+ Classifier: Programming Language :: Python :: 3 :: Only
27
+ Classifier: Operating System :: MacOS
28
+ Classifier: Operating System :: Microsoft :: Windows
29
+ Classifier: Operating System :: POSIX :: Linux
30
+ Classifier: Operating System :: OS Independent
31
+ Requires-Python: >=3.9
32
+ Description-Content-Type: text/markdown
33
+ License-File: LICENSE
34
+ License-File: NOTICE.txt
35
+ Requires-Dist: numpy
36
+ Requires-Dist: scipy
37
+ Requires-Dist: Pyro5
38
+ Requires-Dist: pydantic<2.0.0,>=1.9.1
39
+ Requires-Dist: pyyaml
40
+ Requires-Dist: deprecation
41
+ Requires-Dist: typer
42
+ Requires-Dist: colorama
43
+ Requires-Dist: tabulate
44
+ Requires-Dist: requests
45
+ Requires-Dist: packaging>=23.0
46
+ Provides-Extra: tsl550
47
+ Requires-Dist: pyserial; extra == "tsl550"
48
+ Provides-Extra: ppcl55x
49
+ Requires-Dist: pyserial; extra == "ppcl55x"
50
+ Provides-Extra: rto
51
+ Requires-Dist: pyvisa; extra == "rto"
52
+ Requires-Dist: pyvisa-py; extra == "rto"
53
+ Provides-Extra: arduino
54
+ Requires-Dist: pyfirmata; extra == "arduino"
55
+ Provides-Extra: test
56
+ Requires-Dist: pytest; extra == "test"
57
+ Requires-Dist: coverage; extra == "test"
58
+ Provides-Extra: dev
59
+ Requires-Dist: notebook; extra == "dev"
60
+ Requires-Dist: pytest; extra == "dev"
61
+ Requires-Dist: mypy; extra == "dev"
62
+ Requires-Dist: coverage; extra == "dev"
63
+ Requires-Dist: flake8>=4.0.1; extra == "dev"
64
+ Requires-Dist: isort>=5.10.1; extra == "dev"
65
+ Requires-Dist: black>=22.1.0; extra == "dev"
66
+ Requires-Dist: autopep8>=1.6.0; extra == "dev"
67
+ Requires-Dist: twine>=4.0.0; extra == "dev"
68
+ Requires-Dist: build>=0.10.0; extra == "dev"
69
+ Requires-Dist: pre-commit; extra == "dev"
70
+ Requires-Dist: bump2version~=1.0.1; extra == "dev"
71
+ Provides-Extra: docs
72
+ Requires-Dist: jupyter-book==1.0.3; extra == "docs"
73
+ Requires-Dist: numpydoc==1.5.0; extra == "docs"
74
+ Dynamic: license-file
75
+
76
+ <p align="center">
77
+ <img src="https://raw.githubusercontent.com/BYUCamachoLab/pyrolab/master/docs/_static/images/pyrolab_logo.svg" width="40%" alt="PyroLab">
78
+ </p>
79
+
80
+ ---
81
+
82
+ <p align="center">
83
+ <img alt="Development version" src="https://img.shields.io/badge/master-v0.4.0-informational">
84
+ <a href="https://pypi.python.org/pypi/pyrolab"><img alt="PyPI Version" src="https://img.shields.io/pypi/v/pyrolab.svg"></a>
85
+ <img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/pyrolab">
86
+ <a href="https://pyrolab.readthedocs.io/"><img alt="Documentation Status" src="https://readthedocs.org/projects/pyrolab/badge/?version=latest"></a>
87
+ <a href="https://pypi.python.org/pypi/pyrolab/"><img alt="License" src="https://img.shields.io/pypi/l/pyrolab.svg"></a>
88
+ <a href="https://github.com/BYUCamachoLab/pyrolab/commits/master"><img alt="Latest Commit" src="https://img.shields.io/github/last-commit/BYUCamachoLab/pyrolab.svg"></a>
89
+ </p>
90
+
91
+ A framework for using remote lab instruments as local resources, built on Pyro5.
92
+
93
+ Developed by Sequoia Ploeg (for [CamachoLab](https://camacholab.byu.edu/),
94
+ Brigham Young University).
95
+
96
+ ## About
97
+ This project aims to allow all laboratory instruments to be accessed as
98
+ local objects from a remote machine. Instruments that don't natively
99
+ support such access, such as those required to be connected by a USB cable
100
+ (or similar), are wrapped with a Pyro5 interface. However, this library may
101
+ contain other instruments that are already internet-capable and don't rely
102
+ on Pyro5. That's alright; we're just trying to create a minimal-dependency,
103
+ one-stop-shop for laboratory instruments!
104
+
105
+ **Note:** while the software says "OS Independent", some of the servers *are*
106
+ OS-specific. For example, ThorLabs DLL's only work on Windows. However, you could
107
+ use PyroLab to connect to those devices from any operating system.
108
+
109
+ ## Installation
110
+
111
+ PyroLab is pip installable:
112
+
113
+ ```
114
+ pip install pyrolab
115
+ ```
116
+
117
+ PyroLab declares several "extras", depending on which instruments you need
118
+ to support:
119
+
120
+ ```
121
+ pip install pyrolab[tsl550, oscope]
122
+ ```
123
+
124
+ The full list of supported extras is:
125
+ - ``tsl550`` (Santec lasers)
126
+ - ``ppcl55x`` (PurePhotonics lasers)
127
+ - ``rto`` (Rohde & Schwarz oscilloscopes)
128
+ - ``arduino`` (Arduino)
129
+ - ``test`` (PyroLab unit testing)
130
+ <!-- - ``thorlabs`` (ThorLabs motion controllers) -->
131
+ <!-- - ``adiscovery`` (Analog Discovery boards from Digilent) -->
132
+ <!-- - ``monitor`` (PyroMonitor web application) -->
133
+
134
+ You can also clone the repository, navigate to the toplevel, and install in
135
+ editable mode (make sure you have pip >= 21.1):
136
+
137
+ ```
138
+ pip install -e .
139
+ ```
140
+
141
+ ## Web Monitor
142
+
143
+ There's a web application that can monitor your PyroLab nameserver and
144
+ provide an easy-to-access status board. It's a Flask app that can be served
145
+ using a production grade server. Install it using pip:
146
+
147
+ ```
148
+ pip install pyromonitor
149
+ ```
150
+
151
+ To run:
152
+
153
+ ```
154
+ pyromonitor up
155
+ ```
156
+
157
+ ## Example
158
+
159
+ ### Local Instruments
160
+
161
+ Locally available instruments just import drivers without using any of the
162
+ other features of PyroLab.
163
+
164
+ ```
165
+ from pyrolab.drivers.lasers.tsl550 import TSL550
166
+
167
+ laser = TSL550("COM4")
168
+ laser.on()
169
+ laser.power_dBm(12)
170
+ laser.open_shutter()
171
+ laser.sweep_set_mode(continuous=True, twoway=True, trigger=False, const_freq_step=False)
172
+ ```
173
+
174
+ ### Remote Instruments
175
+
176
+ First, make sure all configurations on the nameserver computer, instrument
177
+ server computer, and client are correct (with the proper keys, if configured,
178
+ etc.).
179
+
180
+ Run a nameserver:
181
+
182
+ ```python
183
+ from pyrolab.api import start_ns_loop
184
+ start_ns_loop()
185
+ ```
186
+
187
+ Provide a service:
188
+
189
+ ```python
190
+ from pyrolab.api import Daemon, locate_ns
191
+ from pyrolab.drivers.sample import SampleService
192
+
193
+ daemon = Daemon()
194
+ ns = locate_ns(host="localhost")
195
+ uri = daemon.register(SampleService)
196
+ ns.register("test.SampleService", uri)
197
+
198
+ try:
199
+ daemon.requestLoop()
200
+ finally:
201
+ ns.remove("test.SampleService")
202
+ ```
203
+
204
+ Connect using a remote client:
205
+
206
+ ```python
207
+ from pyrolab.api import locate_ns, Proxy
208
+
209
+ ns = locate_ns(host="localhost")
210
+ uri = ns.lookup("test.SampleService")
211
+
212
+ with Proxy(uri) as service:
213
+ resp = service.echo("Hello, server!")
214
+ print(type(resp), resp)
215
+ ```
216
+
217
+ ## Instrument Server Configuration
218
+
219
+ PyroLab stores information about instruments and servers when it closes. This
220
+ means that once PyroLab has been configured once, each time it is restarted,
221
+ it will remember and reload the previous configuration. Hence, once a server
222
+ is set up, unless the available instruments, nameserver, or other
223
+ configurations change, PyroLab will automatically work when started, every
224
+ time!
225
+
226
+ For an example of how a new PyroLab instrument server should be configured the
227
+ first time it's run, see ``examples/library-catalog/config.yaml``.
228
+
229
+ ## FAQ's
230
+ 1. **Another instrument library? What about all the others?**
231
+ In our experience, many of the other libraries are buggy or have difficulty
232
+ with network connections. So, our approach was to rely on a well developed
233
+ and time-tested framework (Pyro) instead of worrying about developing and
234
+ supporting our own custom set of servers.
235
+
236
+ 2. **Is this a standalone software that automatically supports all the advertised
237
+ instruments?**
238
+ No; many of these instruments depend on other software already being
239
+ installed. In particular, ThorLabs equipment depends on ThorLabs software
240
+ already being installed on the computer connected to the physical hardware
241
+ (but not on the remote computer!). As much as possible, though, we try to
242
+ make the drivers standalone capable.
243
+
244
+ ## For Developers
245
+
246
+ Since the passing of data is, by definition, between hosts and over IP, PyroLab
247
+ avoids the use of complex Python objects for return values that will be
248
+ transmitted to remote machines. Since serialization is complicated, and
249
+ security is even harder, we resort to using only basic Python types when
250
+ interfacing with hardware (i.e., Python lists, ints, tuples, and not NumPy
251
+ arrays, matplotlib plot objects, custom objects, etc.).
252
+
253
+ ## Releasing
254
+
255
+ Make sure you have committed a changelog file under ``docs/changelog`` titled
256
+ ``<major>.<minor>.<patch>-changelog.md`` before bumping version. Also, the git
257
+ directory should be clean (no uncommitted changes).
258
+
259
+ To bump version prior to a release, run one of the following commands:
260
+
261
+ ```
262
+ bumpversion major
263
+ bumpversion minor
264
+ bumpversion patch
265
+ ```
266
+
267
+ This will automatically create a git tag in the repository with the
268
+ corrresponding version number and commit the modified files (where version
269
+ numbers were updated). Pushing the tags (a manual process) to the remote will
270
+ automatically create a new release. Releases are automatically published to
271
+ PyPI and GitHub when git tags matching the "v*" pattern are created
272
+ (e.g. "v0.4.0"), as bumpversion does.
273
+
274
+ After bumping version, you can view the tags on the local machine by running
275
+ ``git tag``. To push the tags to the remote server and trigger the release
276
+ workflow, you can run ``git push origin <tagname>``.
277
+
278
+ For code quality, please run isort and black before committing (note that the
279
+ latest release of isort may not work through VSCode's integrated terminal, and
280
+ it's safest to run it separately through another terminal).
281
+
282
+ ## Building the Docs
283
+
284
+ Much of the API documentation is autogenerated from the source code. Gitignores
285
+ are in place to prevent you from committing autogenerated pages.
286
+
287
+ To build the docs, navigate to the ``docs/`` directory and run:
288
+
289
+ ```
290
+ pip install -r requirements.txt
291
+ make html
292
+ ```
293
+
294
+ ## Building the Package
295
+
296
+ You can test the build and view the bundled artifacts using
297
+ [build](https://pypi.org/project/build/). It's recommended you build locally
298
+ before pushing to PyPI. In particular, double check the included files and make
299
+ sure only the required files are there by modifying MANIFEST.in as necessary.
@@ -5,7 +5,7 @@
5
5
  ---
6
6
 
7
7
  <p align="center">
8
- <img alt="Development version" src="https://img.shields.io/badge/master-v0.3.1-informational">
8
+ <img alt="Development version" src="https://img.shields.io/badge/master-v0.4.0-informational">
9
9
  <a href="https://pypi.python.org/pypi/pyrolab"><img alt="PyPI Version" src="https://img.shields.io/pypi/v/pyrolab.svg"></a>
10
10
  <img alt="PyPI - Python Version" src="https://img.shields.io/pypi/pyversions/pyrolab">
11
11
  <a href="https://pyrolab.readthedocs.io/"><img alt="Documentation Status" src="https://readthedocs.org/projects/pyrolab/badge/?version=latest"></a>
@@ -47,10 +47,14 @@ pip install pyrolab[tsl550, oscope]
47
47
  ```
48
48
 
49
49
  The full list of supported extras is:
50
- - tsl550
51
- - oscope
52
- - arduino
53
- - monitor
50
+ - ``tsl550`` (Santec lasers)
51
+ - ``ppcl55x`` (PurePhotonics lasers)
52
+ - ``rto`` (Rohde & Schwarz oscilloscopes)
53
+ - ``arduino`` (Arduino)
54
+ - ``test`` (PyroLab unit testing)
55
+ <!-- - ``thorlabs`` (ThorLabs motion controllers) -->
56
+ <!-- - ``adiscovery`` (Analog Discovery boards from Digilent) -->
57
+ <!-- - ``monitor`` (PyroMonitor web application) -->
54
58
 
55
59
  You can also clone the repository, navigate to the toplevel, and install in
56
60
  editable mode (make sure you have pip >= 21.1):
@@ -61,9 +65,15 @@ pip install -e .
61
65
 
62
66
  ## Web Monitor
63
67
 
64
- PyroLab comes with a web application that can monitor your nameserver and
68
+ There's a web application that can monitor your PyroLab nameserver and
65
69
  provide an easy-to-access status board. It's a Flask app that can be served
66
- using a production grade server. To run:
70
+ using a production grade server. Install it using pip:
71
+
72
+ ```
73
+ pip install pyromonitor
74
+ ```
75
+
76
+ To run:
67
77
 
68
78
  ```
69
79
  pyromonitor up
@@ -184,7 +194,7 @@ corrresponding version number and commit the modified files (where version
184
194
  numbers were updated). Pushing the tags (a manual process) to the remote will
185
195
  automatically create a new release. Releases are automatically published to
186
196
  PyPI and GitHub when git tags matching the "v*" pattern are created
187
- (e.g. "v0.3.1"), as bumpversion does.
197
+ (e.g. "v0.4.0"), as bumpversion does.
188
198
 
189
199
  After bumping version, you can view the tags on the local machine by running
190
200
  ``git tag``. To push the tags to the remote server and trigger the release
@@ -1,10 +1,10 @@
1
1
  [project]
2
- name = "PyroLab"
3
- version = "0.3.1"
4
- description = "A framework for using remote lab instruments as local resources built on Pyro5"
2
+ name = "pyrolab"
3
+ version = "0.4.0"
4
+ description = "A framework for using remote lab instruments as local resources built on Pyro5."
5
5
  readme = "README.md"
6
- requires-python = ">=3.7"
7
- license = {file = "LICENSE"}
6
+ requires-python = ">=3.9"
7
+ license = {text = "GPL-3.0+"}
8
8
  keywords = [
9
9
  "PyroLab",
10
10
  "Pyro5",
@@ -47,11 +47,11 @@ classifiers = [
47
47
  "Topic :: Scientific/Engineering",
48
48
  "License :: OSI Approved :: GNU General Public License v3 or later (GPLv3+)",
49
49
  "Programming Language :: Python :: 3",
50
- "Programming Language :: Python :: 3.7",
51
- "Programming Language :: Python :: 3.8",
52
50
  "Programming Language :: Python :: 3.9",
53
51
  "Programming Language :: Python :: 3.10",
54
52
  "Programming Language :: Python :: 3.11",
53
+ "Programming Language :: Python :: 3.12",
54
+ "Programming Language :: Python :: 3.13",
55
55
  "Programming Language :: Python :: 3 :: Only",
56
56
  "Operating System :: MacOS",
57
57
  "Operating System :: Microsoft :: Windows",
@@ -63,7 +63,7 @@ dependencies = [
63
63
  "numpy",
64
64
  "scipy",
65
65
  "Pyro5",
66
- "pydantic",
66
+ "pydantic >= 1.9.1, < 2.0.0",
67
67
  "pyyaml",
68
68
  "deprecation",
69
69
  "typer",
@@ -81,10 +81,34 @@ dependencies = [
81
81
  [project.optional-dependencies]
82
82
  tsl550 = ["pyserial"]
83
83
  ppcl55x = ["pyserial"]
84
+ # thorlabs = ["thorlabs_kinesis@git+https://github.com/BYUCamachoLab/thorlabs-kinesis"]
84
85
  rto = ["pyvisa", "pyvisa-py"]
85
86
  arduino = ["pyfirmata"]
86
- monitor = ["flask", "omegaconf", "waitress"]
87
+ # adiscovery = ["WF_SDK@git+https://github.com/Digilent/WaveForms-SDK-Getting-Started-PY#egg=WF_SDK"]
88
+ # monitor = ["pyromonitor@git+https://github.com/BYUCamachoLab/pyromonitor"]
87
89
  test = ["pytest", "coverage"]
90
+ dev = [
91
+ "notebook",
92
+ "pytest",
93
+ "mypy",
94
+ "coverage",
95
+ "flake8 >= 4.0.1",
96
+ "isort >= 5.10.1",
97
+ "black >= 22.1.0",
98
+ "autopep8 >= 1.6.0",
99
+ "twine >= 4.0.0",
100
+ "build >= 0.10.0",
101
+ "pre-commit",
102
+ "bump2version ~= 1.0.1",
103
+ ]
104
+ docs = [
105
+ "jupyter-book == 1.0.3",
106
+ "numpydoc==1.5.0",
107
+ ]
108
+
109
+ [tool.setuptools.packages.find]
110
+ include = ["pyrolab"]
111
+ namespaces = false
88
112
 
89
113
  [project.urls]
90
114
  "Homepage" = "https://pyrolab.readthedocs.io/en/latest/"
@@ -95,11 +119,6 @@ test = ["pytest", "coverage"]
95
119
 
96
120
  [project.scripts]
97
121
  pyrolab = "pyrolab.cli:app"
98
- pyromonitor = "pyromonitor.cli:app"
99
-
100
- [tool.setuptools.packages.find]
101
- where = ["src"]
102
- include = ["pyrolab", "pyromonitor"]
103
122
 
104
123
  [tool.pytest.ini_options]
105
124
  minversion = "6.0"
@@ -27,6 +27,12 @@ import os
27
27
  import pathlib
28
28
  import platform
29
29
  import sys
30
+ import atexit
31
+ import fileinput
32
+ import re
33
+ from typing import Callable, Iterable
34
+ from time import strptime
35
+ from pathlib import Path
30
36
 
31
37
  # Check if Python version is supported
32
38
  pyversion = sys.version_info
@@ -42,11 +48,11 @@ if pyversion < (3, 7, 0):
42
48
  __name__ = "PyroLab"
43
49
  __author__ = "CamachoLab"
44
50
  __copyright__ = "Copyright 2020, The PyroLab Project"
45
- __version__ = "0.3.1"
51
+ __version__ = "0.4.0"
46
52
  __license__ = "GPLv3+"
47
53
  __maintainer__ = "Sequoia Ploeg"
48
54
  __maintainer_email__ = "sequoia.ploeg@byu.edu"
49
- __status__ = "Development" # "Production"
55
+ __status__ = "Development" # "Production"
50
56
  __project_url__ = "https://github.com/sequoiap/pyrolab"
51
57
  __forum_url__ = "https://github.com/sequoiap/pyrolab/issues"
52
58
  __website_url__ = "https://camacholab.byu.edu/"
@@ -66,6 +72,7 @@ if pyversion < (3, 9, 0):
66
72
  base_path = pathlib.Path(__file__).resolve().parent
67
73
  else:
68
74
  from importlib.resources import files
75
+
69
76
  base_path = files("pyrolab")
70
77
  base_path = base_path / "data" / "local"
71
78
 
@@ -78,6 +85,7 @@ NAMESERVER_STORAGE.mkdir(parents=True, exist_ok=True)
78
85
 
79
86
  PYROLAB_LOGDIR = PYROLAB_DATA_DIR / "logs"
80
87
  PYROLAB_LOGDIR.mkdir(parents=True, exist_ok=True)
88
+ PYROLAB_MASTERLOG = PYROLAB_LOGDIR / "pyrolab.log"
81
89
 
82
90
  LOCKFILE = PYROLAB_DATA_DIR / "pyrolabd.lock"
83
91
  USER_CONFIG_FILE = PYROLAB_DATA_DIR / "user_configuration.yaml"
@@ -98,11 +106,14 @@ def get_loglevel() -> int:
98
106
  return loglevel
99
107
 
100
108
 
101
- if len(logging.root.handlers) == 0:
109
+ if len(logging.root.handlers) == 0:
102
110
  logfile = PYROLAB_LOGDIR / f"pyrolab_{os.getpid()}.log"
103
111
  root = logging.getLogger()
104
- h = logging.handlers.RotatingFileHandler(logfile, 'a', 30000, 10)
105
- f = logging.Formatter('[%(asctime)s.%(msecs)03d] %(process)-5s %(processName)-10s %(name)-12s %(levelname)-8s %(message)s', datefmt="%Y-%m-%d %H:%M:%S")
112
+ h = logging.handlers.RotatingFileHandler(logfile, "a", 30000, 10)
113
+ f = logging.Formatter(
114
+ "[%(asctime)s.%(msecs)03d] %(levelname)-8s %(process)-5s %(processName)-16s %(name)-20s %(message)s",
115
+ datefmt="%Y-%m-%d %H:%M:%S",
116
+ )
106
117
  h.setFormatter(f)
107
118
  root.addHandler(h)
108
119
  root.setLevel(get_loglevel())
@@ -124,10 +135,10 @@ try:
124
135
 
125
136
  url = "https://pypi.org/pypi/pyrolab/json"
126
137
  with requests.Session() as s:
127
- s.mount('https://pypi.org', HTTPAdapter(max_retries=3))
138
+ s.mount("https://pypi.org", HTTPAdapter(max_retries=3))
128
139
  resp = s.get(url).text
129
140
 
130
- v = json.loads(resp)['info']['version']
141
+ v = json.loads(resp)["info"]["version"]
131
142
  curver = parse(__version__)
132
143
  latest = parse(v)
133
144
 
@@ -139,3 +150,41 @@ try:
139
150
  log.info(message)
140
151
  except:
141
152
  pass
153
+
154
+
155
+ def try_itr(func: Callable, itr: Iterable, *exceptions, **kwargs):
156
+ """
157
+ Tests a function on an iterable, yields iterable if no exception is raised.
158
+ """
159
+ for elem in itr:
160
+ try:
161
+ func(elem, **kwargs)
162
+ yield elem
163
+ except exceptions:
164
+ pass
165
+
166
+
167
+ # @atexit.register
168
+ # def condense_logs():
169
+ # """
170
+ # Cleans up the logfile directory every once in a while.
171
+
172
+ # Runs at exit or when "pyrolab down" is called. Condenses all process log
173
+ # files into a single logfile that is sorted by timestamp.
174
+ # """
175
+ # f_names = list(PYROLAB_LOGDIR.glob("*.*"))
176
+ # lines = list(fileinput.input(f_names))
177
+ # t_fmt = "%Y-%m-%d %H:%M:%S.%f" # format of time stamps
178
+ # t_pat = re.compile(r"\[(.+?)\]") # pattern to extract timestamp
179
+ # lines = list(
180
+ # try_itr(
181
+ # lambda l: strptime(t_pat.search(l).group(1), t_fmt), lines, AttributeError
182
+ # )
183
+ # )
184
+ # with PYROLAB_MASTERLOG.open(mode="w") as f:
185
+ # for l in sorted(lines, key=lambda l: strptime(t_pat.search(l).group(1), t_fmt)):
186
+ # f.write(l)
187
+ # if PYROLAB_MASTERLOG in f_names:
188
+ # f_names.remove(PYROLAB_MASTERLOG)
189
+ # for f in f_names:
190
+ # f.unlink()
@@ -14,11 +14,11 @@ from Pyro5.core import locate_ns
14
14
  from Pyro5.server import behavior, expose, oneway, serve
15
15
  from pyrolab import USER_CONFIG_FILE
16
16
  from pyrolab.configure import (
17
- PyroLabConfiguration,
18
- NameServerConfiguration,
19
- DaemonConfiguration,
20
- ServiceConfiguration,
21
- reset_config,
17
+ PyroLabConfiguration,
18
+ NameServerConfiguration,
19
+ DaemonConfiguration,
20
+ ServiceConfiguration,
21
+ reset_config,
22
22
  update_config,
23
23
  )
24
24
  from pyrolab.server import Daemon, LockableDaemon
@@ -47,7 +47,7 @@ __all__ = [
47
47
  ]
48
48
 
49
49
  # If a user config file exists, load the first listed nameserver by default,
50
- # so that locate_ns "just works."
50
+ # so that locate_ns "just works."
51
51
  if USER_CONFIG_FILE.exists():
52
52
  cfg = PyroLabConfiguration.from_file(USER_CONFIG_FILE)
53
53
  nscfg = next(iter(cfg.nameservers.values()))