primitives 0.1.0__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.
primitives/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ from .ton import TON
2
+ from .sr import SR
3
+
4
+ __all__ = ["TON", "SR"]
primitives/py.typed ADDED
File without changes
primitives/sr.py ADDED
@@ -0,0 +1,12 @@
1
+ from dataclasses import dataclass
2
+
3
+ @dataclass(slots=True)
4
+ class SR:
5
+ state: bool = False
6
+
7
+ def update(self, set_: bool, reset: bool) -> bool:
8
+ if reset:
9
+ self.state = False
10
+ elif set_:
11
+ self.state = True
12
+ return self.state
primitives/ton.py ADDED
@@ -0,0 +1,53 @@
1
+ # primitives/ton.py
2
+ from __future__ import annotations
3
+
4
+ from dataclasses import dataclass
5
+ from time import monotonic
6
+ from typing import Optional
7
+
8
+
9
+ @dataclass(slots=True)
10
+ class TON:
11
+ """IEC-style TON (timer on-delay).
12
+
13
+ Usage:
14
+ t = TON(2.0) # 2 seconds preset
15
+ t.update(True) # call each scan with enable signal
16
+ if t.q: ... # output goes True after preset elapses
17
+ """
18
+ preset: float # seconds
19
+ _start: Optional[float] = None # monotonic start time
20
+ q: bool = False # done/output
21
+
22
+ def reset(self) -> None:
23
+ self._start = None
24
+ self.q = False
25
+
26
+ def update(self, enable: bool, now: Optional[float] = None) -> bool:
27
+ """Update the timer; return output (q).
28
+
29
+ Args:
30
+ enable: input signal; when False, timer resets.
31
+ now: optional monotonic time for testing; defaults to time.monotonic().
32
+ """
33
+ if not enable:
34
+ self.reset()
35
+ return self.q
36
+
37
+ t = monotonic() if now is None else now
38
+ if self._start is None:
39
+ self._start = t
40
+ self.q = False
41
+ return self.q
42
+
43
+ if (t - self._start) >= self.preset:
44
+ self.q = True
45
+ return self.q
46
+
47
+ @property
48
+ def elapsed(self) -> float:
49
+ """Seconds since enable; 0 if not running."""
50
+ if self._start is None:
51
+ return 0.0
52
+ t = monotonic()
53
+ return max(0.0, t - self._start)
@@ -0,0 +1,73 @@
1
+ Metadata-Version: 2.4
2
+ Name: primitives
3
+ Version: 0.1.0
4
+ Summary: Shared PLC-style primitives in Python
5
+ Author-email: Neil Doell <neil@vococo.ca>
6
+ License-Expression: MIT
7
+ Requires-Python: >=3.9
8
+ Description-Content-Type: text/markdown
9
+
10
+ timers-latches
11
+
12
+ Lightweight, production-ready implementations of PLC-style primitives in Python:
13
+
14
+ TON — On-delay timer
15
+
16
+ SR — Set/Reset latch (reset dominant)
17
+
18
+ These primitives are useful for industrial automation logic, simulations, or anywhere you want PLC-like control behavior in Python.
19
+
20
+ Installation
21
+ pip install timers-latches
22
+
23
+
24
+ Or, for development:
25
+
26
+ git clone https://github.com/yourorg/timers-latches.git
27
+ cd timers-latches
28
+ pip install -e .
29
+
30
+ Usage
31
+ from timers_latches import TON, SR
32
+
33
+ # --- TON example ---
34
+ ton = TON(preset_s=2.0) # 2-second delay
35
+ for step in range(5):
36
+ q = ton.update(enable=True, dt_s=0.5)
37
+ print(f"t={step*0.5:.1f}s, Q={q}")
38
+ # Q will turn True after 2.0 seconds of accumulated enable time
39
+
40
+ # --- SR example ---
41
+ latch = SR(initial=False)
42
+ print(latch.update(set_=True, reset=False)) # True
43
+ print(latch.update(set_=False, reset=True)) # False (reset dominates)
44
+
45
+ API
46
+ TON(preset_s: float)
47
+
48
+ preset_s: delay time in seconds (must be ≥ 0).
49
+
50
+ .update(enable: bool, dt_s: float) -> bool: call once per scan; returns the done bit (Q).
51
+
52
+ .Q: current output (done bit).
53
+
54
+ SR(initial: bool = False)
55
+
56
+ initial: starting state.
57
+
58
+ .update(set_: bool, reset: bool) -> bool: updates and returns current state. Reset dominates set.
59
+
60
+ .state: current latched state.
61
+
62
+ Versioning
63
+
64
+ Follows Semantic Versioning
65
+ .
66
+
67
+ API is stable from 1.0.0 onward.
68
+
69
+ License
70
+
71
+ MIT © Your Name / Your Organization
72
+
73
+ ⚡️ This package is intentionally minimal and focused: no dependencies, only core primitives. You can drop it into simulations, control logic, or larger automation frameworks.
@@ -0,0 +1,7 @@
1
+ primitives/__init__.py,sha256=YlyjvaUWcohJSbzLrgWX9gz5rgqj7lRZ_KkL8B4ucBI,65
2
+ primitives/sr.py,sha256=HmmJJ8bzRWvpDoJ-ddd2mzSyGgETHx7VGFpCywsfGLU,271
3
+ primitives/ton.py,sha256=4irB3UGucnfcvs492A20UXc1SBeA6VhmPiqlh_lErMU,1531
4
+ primitives/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
5
+ primitives-0.1.0.dist-info/METADATA,sha256=du2tehI1S0SodKm0kv4NIrz4L2EJOatRF4IAr5xDLCU,1816
6
+ primitives-0.1.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ primitives-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,4 @@
1
+ Wheel-Version: 1.0
2
+ Generator: hatchling 1.27.0
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any