PyroLab 0.3.2__py3-none-any.whl → 0.5.0rc2__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 (48) hide show
  1. pyrolab/__init__.py +42 -93
  2. pyrolab/api.py +21 -9
  3. pyrolab/cli.py +606 -205
  4. pyrolab/configure.py +327 -104
  5. pyrolab/drivers/VISAResourceExtensions.py +65 -34
  6. pyrolab/drivers/__init__.py +50 -25
  7. pyrolab/drivers/arduino/arduino.py +71 -19
  8. pyrolab/drivers/cameras/amcam.py +61 -0
  9. pyrolab/drivers/cameras/sciTSI.py +41 -34
  10. pyrolab/drivers/cameras/thorcam.py +122 -73
  11. pyrolab/drivers/cameras/uc480.py +68 -63
  12. pyrolab/drivers/fpgas/__init__.py +16 -0
  13. pyrolab/drivers/fpgas/analogdiscovery.py +309 -0
  14. pyrolab/drivers/function_generators/__init__.py +16 -0
  15. pyrolab/drivers/function_generators/smcv100b.py +389 -0
  16. pyrolab/drivers/lasers/ppcl55x.py +302 -262
  17. pyrolab/drivers/lasers/sachertec.py +25 -20
  18. pyrolab/drivers/lasers/tsl550.py +232 -176
  19. pyrolab/drivers/motion/KMTS25E.py +92 -0
  20. pyrolab/drivers/motion/kinesis/__init__.py +9 -5
  21. pyrolab/drivers/motion/kinesis/bpc303.py +86 -43
  22. pyrolab/drivers/motion/kinesis/kdc101.py +123 -95
  23. pyrolab/drivers/motion/max31x.py +31 -24
  24. pyrolab/drivers/motion/prm1z8.py +2 -1
  25. pyrolab/drivers/motion/z8xx.py +13 -10
  26. pyrolab/drivers/sample.py +16 -11
  27. pyrolab/drivers/scopes/rohdeschwarz.py +137 -114
  28. pyrolab/drivers/smu/keysight.py +94 -83
  29. pyrolab/locations.py +129 -0
  30. pyrolab/logs.py +359 -0
  31. pyrolab/manager.py +888 -278
  32. pyrolab/nameserver.py +58 -25
  33. pyrolab/pyrolabd.py +268 -72
  34. pyrolab/server.py +110 -62
  35. pyrolab/service.py +13 -8
  36. pyrolab/updates.py +108 -0
  37. pyrolab/utils.py +145 -12
  38. pyrolab-0.5.0rc2.dist-info/METADATA +301 -0
  39. pyrolab-0.5.0rc2.dist-info/RECORD +51 -0
  40. {pyrolab-0.3.2.dist-info → pyrolab-0.5.0rc2.dist-info}/WHEEL +1 -1
  41. pyrolab-0.5.0rc2.dist-info/entry_points.txt +2 -0
  42. {pyrolab-0.3.2.dist-info → pyrolab-0.5.0rc2.dist-info/licenses}/NOTICE.txt +1 -1
  43. pyrolab-0.3.2.dist-info/AUTHORS.txt +0 -20
  44. pyrolab-0.3.2.dist-info/METADATA +0 -973
  45. pyrolab-0.3.2.dist-info/RECORD +0 -43
  46. pyrolab-0.3.2.dist-info/entry_points.txt +0 -2
  47. {pyrolab-0.3.2.dist-info → pyrolab-0.5.0rc2.dist-info/licenses}/LICENSE +0 -0
  48. {pyrolab-0.3.2.dist-info → pyrolab-0.5.0rc2.dist-info}/top_level.txt +0 -0
pyrolab/__init__.py CHANGED
@@ -23,119 +23,68 @@ PyroLab
23
23
  A framework for using remote lab instruments as local resources built on Pyro5.
24
24
  """
25
25
 
26
+ import logging
26
27
  import os
27
- import pathlib
28
28
  import platform
29
29
  import sys
30
30
 
31
31
  # Check if Python version is supported
32
32
  pyversion = sys.version_info
33
- if pyversion < (3, 7, 0):
33
+ if pyversion < (3, 11, 0):
34
34
  raise Exception(
35
- "PyroLab requires Python 3.7+ (version "
35
+ "PyroLab requires Python 3.11+ (version "
36
36
  + platform.python_version()
37
37
  + " detected)."
38
38
  )
39
39
 
40
40
 
41
41
  # Metadata
42
- __name__ = "PyroLab"
42
+ __title__ = "PyroLab"
43
43
  __author__ = "CamachoLab"
44
44
  __copyright__ = "Copyright 2020, The PyroLab Project"
45
- __version__ = "0.3.2"
45
+ # pyproject.toml is the single source of the version (see `uv version`).
46
+ import importlib.metadata as _metadata
47
+
48
+ try:
49
+ __version__ = _metadata.version("pyrolab")
50
+ except _metadata.PackageNotFoundError: # source tree that isn't installed
51
+ __version__ = "0.0.0+unknown"
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/"
53
59
 
54
60
 
55
- # Filter warnings
56
- import warnings
57
-
58
- warnings.filterwarnings("default", category=DeprecationWarning)
59
- if "PYROLAB_HUSH_DEPRECATION" in os.environ:
60
- warnings.filterwarnings("ignore", category=DeprecationWarning)
61
-
62
-
63
- # Configuration directories
64
- # Old api deprecated in 3.11, new api added in 3.9
65
- if pyversion < (3, 9, 0):
66
- base_path = pathlib.Path(__file__).resolve().parent
67
- else:
68
- from importlib.resources import files
69
- base_path = files("pyrolab")
70
- base_path = base_path / "data" / "local"
71
-
72
- # Data directories
73
- PYROLAB_DATA_DIR = pathlib.Path(base_path)
74
- PYROLAB_DATA_DIR.mkdir(parents=True, exist_ok=True)
75
-
76
- NAMESERVER_STORAGE = PYROLAB_DATA_DIR / "nameserver"
77
- NAMESERVER_STORAGE.mkdir(parents=True, exist_ok=True)
78
-
79
- PYROLAB_LOGDIR = PYROLAB_DATA_DIR / "logs"
80
- PYROLAB_LOGDIR.mkdir(parents=True, exist_ok=True)
81
-
82
- LOCKFILE = PYROLAB_DATA_DIR / "pyrolabd.lock"
83
- USER_CONFIG_FILE = PYROLAB_DATA_DIR / "user_configuration.yaml"
84
- RUNTIME_CONFIG = PYROLAB_DATA_DIR / "runtime_config.yaml"
85
-
86
-
87
- # Set up logging to file
88
- import logging
89
- import logging.handlers
90
-
91
-
92
- def get_loglevel() -> int:
93
- loglevel = os.getenv("PYROLAB_LOGLEVEL", "INFO")
94
- try:
95
- loglevel = getattr(logging, loglevel.upper())
96
- except AttributeError:
97
- loglevel = logging.INFO
98
- return loglevel
99
-
100
-
101
- if len(logging.root.handlers) == 0:
102
- logfile = PYROLAB_LOGDIR / f"pyrolab_{os.getpid()}.log"
103
- 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")
106
- h.setFormatter(f)
107
- root.addHandler(h)
108
- root.setLevel(get_loglevel())
109
- root.debug("PyroLab logging configured")
110
-
111
-
112
- # Include remote traceback in local tracebacks
113
- import Pyro5.errors
114
-
115
- sys.excepthook = Pyro5.errors.excepthook
116
-
117
-
118
- # Check for updates to PyroLab
119
- try:
120
- import json
121
- import requests
122
- from requests.adapters import HTTPAdapter
123
- from packaging.version import parse
124
-
125
- url = "https://pypi.org/pypi/pyrolab/json"
126
- with requests.Session() as s:
127
- s.mount('https://pypi.org', HTTPAdapter(max_retries=3))
128
- resp = s.get(url).text
129
-
130
- v = json.loads(resp)['info']['version']
131
- curver = parse(__version__)
132
- latest = parse(v)
133
-
134
- log = logging.getLogger(__name__)
135
-
136
- if curver < latest:
137
- message = f"A new version of PyroLab is available (latest is {latest}, but {curver} is installed)."
138
- warnings.warn(message, stacklevel=2)
139
- log.info(message)
140
- except:
141
- pass
61
+ # Where PyroLab keeps its files: per-user directories (see pyrolab.locations).
62
+ # Importing creates nothing; files and directories are created when written.
63
+ from pathlib import Path
64
+
65
+ from pyrolab.locations import LEGACY_DATA_DIR
66
+ from pyrolab.locations import locations as _find_locations
67
+
68
+ _locations = _find_locations()
69
+
70
+ PYROLAB_DATA_DIR = _locations.data_dir
71
+ NAMESERVER_STORAGE = _locations.data_dir / "nameserver"
72
+ PYROLAB_LOGDIR = _locations.log_dir
73
+ # The daemon's single log file; PYROLAB_LOGFILE overrides where it goes.
74
+ PYROLAB_LOGFILE = Path(
75
+ os.environ.get("PYROLAB_LOGFILE") or PYROLAB_LOGDIR / "pyrolab.log"
76
+ )
77
+ USER_CONFIG_FILE = _locations.config_dir / "user_configuration.yaml"
78
+ LOCKFILE = _locations.state_dir / "pyrolabd.lock"
79
+ RUNTIME_CONFIG = _locations.state_dir / "runtime_config.yaml"
80
+ # Why the background daemon exited before it could serve requests, for `up`.
81
+ STARTUP_ERROR_FILE = _locations.state_dir / "pyrolabd_startup_error.txt"
82
+ # Records that files from a pre-0.5 install were copied (see pyrolab.locations).
83
+ LEGACY_MIGRATION_MARKER = _locations.state_dir / "legacy_files_copied.txt"
84
+ UPDATE_CHECK_FILE = _locations.cache_dir / "update_check.json"
85
+
86
+
87
+ # As a library, PyroLab leaves logging to the application: its loggers do
88
+ # nothing until the application (or PyroLab's own CLI and daemon, see
89
+ # pyrolab.logs) configures logging.
90
+ logging.getLogger(__name__).addHandler(logging.NullHandler())
pyrolab/api.py CHANGED
@@ -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,8 +47,20 @@ __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
+ # This is a convenience only: importing the API must never fail because the
52
+ # local configuration is invalid, has no nameservers, or names a "public"
53
+ # host that can't be resolved -- otherwise neither client scripts nor the
54
+ # CLI commands that would fix the configuration could even start.
51
55
  if USER_CONFIG_FILE.exists():
52
- cfg = PyroLabConfiguration.from_file(USER_CONFIG_FILE)
53
- nscfg = next(iter(cfg.nameservers.values()))
54
- nscfg.update_pyro_config()
56
+ try:
57
+ cfg = PyroLabConfiguration.from_file(USER_CONFIG_FILE)
58
+ nscfg = next(iter(cfg.nameservers.values()), None)
59
+ if nscfg is not None:
60
+ nscfg.update_pyro_config()
61
+ except Exception as e:
62
+ import logging
63
+
64
+ logging.getLogger(__name__).warning(
65
+ "Not applying nameserver defaults from %s: %s", USER_CONFIG_FILE, e
66
+ )