ekfsm 1.1.0a15.post1__py3-none-any.whl → 1.2.0a7__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.

Potentially problematic release.


This version of ekfsm might be problematic. Click here for more details.

ekfsm/devices/eeprom.py CHANGED
@@ -1067,6 +1067,23 @@ class EKF_CCU_EEPROM(EKF_EEPROM):
1067
1067
  def write_customer_area(self, data: bytes) -> None:
1068
1068
  """
1069
1069
  Write data to CCU EEPROM customer area.
1070
+
1071
+ Parameters
1072
+ ----------
1073
+ data
1074
+ The data to write to the customer area of the CCU EEPROM.
1075
+
1076
+ Raises
1077
+ ------
1078
+ ValueError
1079
+ If the data exceeds the customer area length.
1080
+
1081
+ Example
1082
+ -------
1083
+ >>> eeprom = EKF_CCU_EEPROM()
1084
+ >>> eeprom.write_customer_area(b"Hello, World!")
1085
+ >>> eeprom.customer_area()
1086
+ b'Hello, World!'
1070
1087
  """
1071
1088
  if len(data) > self._customer_area_length:
1072
1089
  raise ValueError("Data exceeds customer area length")
@@ -54,7 +54,10 @@ class EKFCcuUc(Device):
54
54
  def temperature(self) -> float:
55
55
  """
56
56
  Get the temperature from the CCU thermal/humidity sensor.
57
- The temperature is read once per second.
57
+
58
+ Note
59
+ ----
60
+ The CCU reads the temperature once per second.
58
61
 
59
62
  Returns
60
63
  -------
@@ -304,6 +307,13 @@ class EKFCcuUc(Device):
304
307
  progress_callback
305
308
  A callback function that is called with the current progress in bytes.
306
309
 
310
+ Example
311
+ -------
312
+ >>> from ekfsm.devices import EkfCcuUc
313
+ >>> ccu = EkfCcuUc("ccu")
314
+ >>> firmware = open("fw-ccu-1.0.0.bin", "rb").read()
315
+ >>> # Load firmware with progress callback
316
+ >>> ccu.load_firmware(firmware, progress_callback=lambda x: print(f"Progress: {x} bytes"))
307
317
  """
308
318
  with Locker(self.name + "-load_firmware").lock():
309
319
  offset = 0
@@ -423,6 +433,8 @@ class EKFCcuUc(Device):
423
433
  This would load a parameterset with just one parameter, the default fan speed. All other parameters will
424
434
  be set to their default values.
425
435
 
436
+ Important
437
+ ---------
426
438
  In order to apply the parameterset, the CCU must be restarted.
427
439
 
428
440
  Parameters
@@ -430,6 +442,14 @@ class EKFCcuUc(Device):
430
442
  _cfg
431
443
  The parameterset in JSON format.
432
444
 
445
+ Example
446
+ -------
447
+ >>> from ekfsm.devices import EkfCcuUc
448
+ >>> ccu = EkfCcuUc("ccu")
449
+ >>> # Load parameterset
450
+ >>> ccu.load_parameterset('{"version": "1.0.0", "parameters": {"fan-defrpm": "6000"}}')
451
+ >>> # Restart CCU to apply parameterset
452
+ >>> ccu.restart()
433
453
  """
434
454
  with Locker(self.name + "-parameterset").lock():
435
455
  cfg = _cfg.encode("utf-8")
ekfsm/devices/pmbus.py CHANGED
@@ -93,9 +93,8 @@ class PsuStatus(IntFlag):
93
93
  >>> PsuStatus.OK in status
94
94
  True
95
95
  >>> # Instead, check if status is OK
96
- >>> status = PsuStatus(0x00)
97
- >>> status
98
- <PsuStatus.OK: 0>
96
+ >>> status == PsuStatus(0x00)
97
+ False
99
98
  >>> PsuStatus.OUTPUT_OVERCURRENT in status
100
99
  False
101
100
  """
ekfsm/lock.py CHANGED
@@ -1,23 +1,24 @@
1
+ """
2
+ Some devices or device functions don't allow concurrent access.
3
+ The locking mechanism is used to ensure that only one process/thread can
4
+ access the device (function) at a time.
5
+
6
+ Locking granularity is defined by the device.
7
+ It may be at the device level or function level.
8
+
9
+ Application can choose to use the locking mechanism or not.
10
+ By default, the locking mechanism is enabled and uses the default
11
+ lockfile root directory ``/var/lock/ekfsm``.
12
+
13
+ Use :func:`locking_configure` to enable or disable the locking mechanism or to change
14
+ the lockfile root directory.
15
+ """
16
+
1
17
  import fcntl
2
18
  import os
3
19
  from pathlib import Path
4
20
  from contextlib import contextmanager
5
21
 
6
- #
7
- # Some devices or device functions don't allow concurrent access.
8
- # The locking mechanism is used to ensure that only one process/thread can
9
- # access the device (function) at a time.
10
- #
11
- # Locking granularity is defined by the device.
12
- # It may be at the device level or function level.
13
- #
14
- # Application can choose to use the locking mechanism or not.
15
- # By default, the locking mechanism is enabled and uses the default
16
- # lockfile root directory /var/lock/ekfsm.
17
- #
18
- # Use locking_configure() to enable or disable the locking mechanism or to change
19
- # the lockfile root directory.
20
-
21
22
  USE_LOCK = True
22
23
  LOCKFILE_ROOT = "/var/lock/ekfsm"
23
24
  ALL_LOCKERS: list["Locker"] = [] # List of all locker instances
@@ -27,8 +28,12 @@ def locking_configure(enable: bool, lockfile_root: str = LOCKFILE_ROOT):
27
28
  """
28
29
  Configures the locking mechanism.
29
30
 
30
- :param enable: Whether to enable or disable locking.
31
- :param lockfile_root: The root directory for lockfiles. (default: /var/lock/ekfsm)
31
+ Parameters
32
+ ----------
33
+ enable
34
+ Whether to enable or disable locking.
35
+ lockfile_root
36
+ The root directory for lockfiles.
32
37
  """
33
38
  global USE_LOCK, LOCKFILE_ROOT
34
39
  USE_LOCK = enable
@@ -55,9 +60,12 @@ class Locker:
55
60
 
56
61
  Example
57
62
  -------
58
- with Locker("mysharedresourcename").lock():
59
- # Access the shared resource here
60
- pass
63
+ .. code-block:: python
64
+
65
+ with Locker("mysharedresourcename").lock():
66
+ # Access the shared resource here
67
+ pass
68
+
61
69
  """
62
70
 
63
71
  def __init__(self, module: str):
@@ -72,6 +80,17 @@ class Locker:
72
80
  ALL_LOCKERS.append(self)
73
81
 
74
82
  def cleanup(self):
83
+ """
84
+ Cleans up the lock file and closes the lock file descriptor.
85
+
86
+ Important
87
+ ---------
88
+ This method should be called when the lock is no longer needed.
89
+
90
+ Note
91
+ ----
92
+ It is automatically called when the context manager exits.
93
+ """
75
94
  if not USE_LOCK:
76
95
  return
77
96
  if self.lock_fd is not None:
@@ -84,6 +103,14 @@ class Locker:
84
103
 
85
104
  @contextmanager
86
105
  def lock(self):
106
+ """
107
+ Locks the resource for exclusive access.
108
+
109
+ Note
110
+ ----
111
+ This method is a context manager that locks the resource when entered
112
+ and releases the lock when exited.
113
+ """
87
114
  if not USE_LOCK:
88
115
  yield
89
116
  self.lock_fd = os.open(self.lockfile_path, os.O_RDWR)
ekfsm/system.py CHANGED
@@ -1,10 +1,12 @@
1
- from typing import Tuple, Any, Generator
1
+ from typing import Tuple, Any
2
2
  from pathlib import Path
3
3
  from munch import Munch, munchify
4
4
 
5
5
  from ekfsm.core.components import SysTree
6
6
  import yaml
7
7
 
8
+ from ekfsm.utils import all_board_cfg_files, find_board_config
9
+
8
10
  from .core.slots import Slot, SlotType
9
11
 
10
12
  from .config import load_config
@@ -14,39 +16,6 @@ from .exceptions import ConfigError
14
16
  from .log import ekfsm_logger
15
17
 
16
18
 
17
- _CFG_DIR = Path(__file__).parent / "boards"
18
-
19
-
20
- def find_board_config(module_type: str) -> Path | None:
21
- """
22
- Find a matching board config in `boards/oem/` given the module type specified in
23
- the system configuration file.
24
-
25
- Parameters
26
- ----------
27
- module_type
28
- Board type specified in the system configuration for a slot.
29
- It must consist of an OEM and the board type, separated by whitespace. Neither
30
- part may contain any other whitespace.
31
- """
32
- oem, board = module_type.split(maxsplit=1)
33
- if (
34
- path := _CFG_DIR / "oem" / oem.strip().lower() / f"{board.strip().lower()}.yaml"
35
- ).exists():
36
- return path
37
- return None
38
-
39
-
40
- def all_board_cfg_files() -> Generator[Path, None, None]:
41
- """
42
- Generator that recursively yields all *.yaml files in a directory
43
- """
44
- path = Path(_CFG_DIR)
45
- for item in path.rglob("*.yaml"):
46
- if item.is_file():
47
- yield item
48
-
49
-
50
19
  class System(SysTree):
51
20
  """
52
21
  A System represents a CPCI system.
ekfsm/utils.py ADDED
@@ -0,0 +1,41 @@
1
+ from typing import Generator
2
+
3
+
4
+ from pathlib import Path
5
+
6
+ _CFG_DIR = Path(__file__).parent / "boards"
7
+
8
+
9
+ def find_board_config(module_type: str) -> Path | None:
10
+ """
11
+ Find a matching board config in `boards/oem/` given the module type specified in
12
+ the system configuration file.
13
+
14
+ Parameters
15
+ ----------
16
+ module_type
17
+ Board type specified in the system configuration for a slot.
18
+ It must consist of an OEM and the board type, separated by whitespace. Neither
19
+ part may contain any other whitespace.
20
+ """
21
+ oem, board = module_type.split(maxsplit=1)
22
+ if (
23
+ path := _CFG_DIR / "oem" / oem.strip().lower() / f"{board.strip().lower()}.yaml"
24
+ ).exists():
25
+ return path
26
+ return None
27
+
28
+
29
+ def all_board_cfg_files() -> Generator[Path, None, None]:
30
+ """
31
+ Generator that recursively yields all *.yaml files in the config directory.
32
+
33
+ Yields
34
+ ------
35
+ item: Path
36
+ Path to a config file.
37
+ """
38
+ path = Path(_CFG_DIR)
39
+ for item in path.rglob("*.yaml"):
40
+ if item.is_file():
41
+ yield item
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: ekfsm
3
- Version: 1.1.0a15.post1
3
+ Version: 1.2.0a7
4
4
  Summary: The EKF System Management Library (ekfsm) is a sensor monitoring suite for Compact PCI Serial devices.
5
5
  Author-email: Klaus Popp <klaus.popp@ci4rail.com>, Jan Jansen <jan@ekf.de>, Felix Päßler <fp@ekf.de>
6
6
  Requires-Python: >=3.10
@@ -2,11 +2,12 @@ ekfsm/__init__.py,sha256=R12o_igFRTqlHUD9jyrOIPq2nBpTUWuvIPgCytBlVzk,142
2
2
  ekfsm/cli.py,sha256=JmTO1TyxrTlGTkQo8ndSR7nj0grSGuQdh9ugXx1IeQE,3919
3
3
  ekfsm/config.py,sha256=FTk47f3qA05Zv6Cy_L_5XlGmmbC9z_kPdQJKpVoHkWs,924
4
4
  ekfsm/exceptions.py,sha256=25P677GxfBTdBWHRngPce0bmhcLg7MFeTtuAvguxd90,1310
5
- ekfsm/lock.py,sha256=qmWkW6OA-NLiDrtSsQn-K10tZJ19t-h4iFB5zyL97Vw,2682
5
+ ekfsm/lock.py,sha256=XWLu2yhgIs16oSyc_4jdVUobbxyYlYOjZi1EFgHsXVU,3236
6
6
  ekfsm/log.py,sha256=_GC8Y7a4fFV4_DNicbwQ-5rRzNQU6WSotXd2etXSrZk,866
7
7
  ekfsm/py.typed,sha256=1gNRtmxvYcVqDDEyAzBLnD8dAOweUfYxW2ZPdJzN1fg,102
8
8
  ekfsm/simctrl.py,sha256=NkmjvqOym9Wruh0f14Od6gHfEgPMAkxUzMQ-nvzcM3Q,6681
9
- ekfsm/system.py,sha256=azVFdVK7r-9RWotsD7c18YvyZfCqg-3z5t7SqUSDLh8,12922
9
+ ekfsm/system.py,sha256=kBukgVyPJYTh_ilauEEANG2KKqHWOrQBYLhVdG679HM,12028
10
+ ekfsm/utils.py,sha256=IKQrGr8UzUJpqj365uQqIWDRTAgpVC0OUmqIKzt_9T0,1081
10
11
  ekfsm/boards/oem/ekf/ccu.yaml,sha256=qgr7YZO0kEddD9K6tv6222NyozkRNuF7NFw6hyX0XgE,2094
11
12
  ekfsm/boards/oem/ekf/sc5-festival.yaml,sha256=_0kS5GegfyOt5CTJc9kY6HJbr9yZo4i18sVo6F4KE9c,772
12
13
  ekfsm/boards/oem/ekf/sc9-toccata.yaml,sha256=btLgQMSsW0tRipnUYUkVQSIsjzxfKq0NXaQ1fMMyBRI,771
@@ -26,8 +27,8 @@ ekfsm/core/sysfs.py,sha256=CVGxUEdhmJjRw8ZfnjL3hUwm6oWsp3ZKPG2qGUFYIiY,2283
26
27
  ekfsm/core/utils.py,sha256=EoPOuRmLlvHvGneDcKjP7Qbjfsc4XlMbLeaSFRObt_E,3145
27
28
  ekfsm/devices/__init__.py,sha256=UtFLCtAdpDJ3OaY7fedk13bx90NMsfxhyVAHV13t2U4,936
28
29
  ekfsm/devices/coretemp.py,sha256=oco909zpXw9BqkLWV3dJma1_Q23M2EUGsgdcs4QtFjU,1966
29
- ekfsm/devices/eeprom.py,sha256=wj2sy52s8YtsLyfb-_J3cbmI3m-EYdRgSqNZ9_GHVb8,31971
30
- ekfsm/devices/ekf_ccu_uc.py,sha256=mKOWt3T7uLUZdIzCnZwJPLEKYjN22TgOGZEo6yclnoA,15384
30
+ ekfsm/devices/eeprom.py,sha256=4UjydeDxZT7w2zXkhZu7GUuHYu8sAidT8xuVtkt4OJw,32389
31
+ ekfsm/devices/ekf_ccu_uc.py,sha256=bVdxaiXtrJC2-tSRv1rGUzm4wOxL20QfTL4NIKdRJE8,16092
31
32
  ekfsm/devices/ekf_sur_led.py,sha256=dY2EIqUx4-LV7ipCEIg8DfXWlGxpspRmEtEhVfHY6LI,1871
32
33
  ekfsm/devices/generic.py,sha256=9FDj8hhiCQAFmA5tt3lv1JPIZyAb3XCCriDIoR61kcE,10821
33
34
  ekfsm/devices/gpio.py,sha256=hlJ3yJ8jSGUIkPpjymani0EcxYJX2iEybGbnV8N0O5E,9552
@@ -35,11 +36,11 @@ ekfsm/devices/iio.py,sha256=gMOJGdg2PvFbAvlBpLfDTIc_-9i1Z3OLpuabTke6N3I,1480
35
36
  ekfsm/devices/iio_thermal_humidity.py,sha256=gALZ1B4f1ePGAEL7Q5VxbubgC3CgtC9RBM9F4YWuH4E,1478
36
37
  ekfsm/devices/imu.py,sha256=GwJrnC-WztpE5oGnkIp-laFkSp3_gbSp9YpJ8jBsUOs,423
37
38
  ekfsm/devices/mux.py,sha256=C2h5w8eXrL4RXXebCSnNY-VShTgeqmYDMvGSunapBqk,1830
38
- ekfsm/devices/pmbus.py,sha256=QIs93qv9sXSdWEPyY55k0KVSr-XMPYNJhTux3vYLzAE,7104
39
+ ekfsm/devices/pmbus.py,sha256=5nIvuUkY20YwXTIpd3lebdu2dU-he_IJ7wLz1EUTrzc,7078
39
40
  ekfsm/devices/smbios.py,sha256=gDDYtfCd7njzqxJBKJxIR2BMCK6-uZxUVxC9y0hnz4g,1009
40
41
  ekfsm/devices/smbus.py,sha256=zD9b6PehipMw-xoaOMC-oorDVxBoo30hc98gyFxFLs0,500
41
42
  ekfsm/devices/utils.py,sha256=4-0Kmvy4ou8R71afNj6RqdBTjLW4SMWPHqVrzB2RUZw,397
42
- ekfsm-1.1.0a15.post1.dist-info/METADATA,sha256=ylfAPwvJBbi31RurwwJQDMo6V3C-EYkeoTn_RjXs14E,6550
43
- ekfsm-1.1.0a15.post1.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
44
- ekfsm-1.1.0a15.post1.dist-info/entry_points.txt,sha256=WhUR4FzuxPoGrbTOKLsNJO7NAnk2qd4T30fqzN1yLw8,45
45
- ekfsm-1.1.0a15.post1.dist-info/RECORD,,
43
+ ekfsm-1.2.0a7.dist-info/METADATA,sha256=VUyieRTVS_l9ZWkP1ctAYgFAK5s9tv3V_mUOTBXkePM,6543
44
+ ekfsm-1.2.0a7.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
45
+ ekfsm-1.2.0a7.dist-info/entry_points.txt,sha256=WhUR4FzuxPoGrbTOKLsNJO7NAnk2qd4T30fqzN1yLw8,45
46
+ ekfsm-1.2.0a7.dist-info/RECORD,,