primitives 0.1.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.
@@ -0,0 +1,84 @@
1
+ # Python
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+ *.so
6
+ .Python
7
+ build/
8
+ develop-eggs/
9
+ dist/
10
+ downloads/
11
+ eggs/
12
+ .eggs/
13
+ lib/
14
+ lib64/
15
+ parts/
16
+ sdist/
17
+ var/
18
+ wheels/
19
+ share/python-wheels/
20
+ *.egg-info/
21
+ .installed.cfg
22
+ *.egg
23
+ MANIFEST
24
+
25
+ # Virtual environments
26
+ .env
27
+ .venv
28
+ env/
29
+ venv/
30
+ ENV/
31
+ env.bak/
32
+ venv.bak/
33
+
34
+ # uv
35
+ .uv/
36
+
37
+ # IDE
38
+ .vscode/
39
+ .idea/
40
+ *.swp
41
+ *.swo
42
+ *~
43
+
44
+ # OS
45
+ .DS_Store
46
+ Thumbs.db
47
+
48
+ # Docker
49
+ .dockerignore
50
+
51
+ # Logs
52
+ *.log
53
+
54
+ # Environment variables
55
+ .env.local
56
+ .env.development.local
57
+ .env.test.local
58
+ .env.production.local
59
+
60
+ # Coverage reports
61
+ htmlcov/
62
+ .coverage
63
+ .coverage.*
64
+ coverage.xml
65
+ *.cover
66
+ .hypothesis/
67
+ .pytest_cache/
68
+
69
+ # Jupyter Notebook
70
+ .ipynb_checkpoints
71
+
72
+ # pyenv
73
+ .python-version
74
+
75
+ # pipenv
76
+ Pipfile.lock
77
+
78
+ # poetry
79
+ poetry.lock
80
+
81
+ # mypy
82
+ .mypy_cache/
83
+ .dmypy.json
84
+ dmypy.json
@@ -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,64 @@
1
+ timers-latches
2
+
3
+ Lightweight, production-ready implementations of PLC-style primitives in Python:
4
+
5
+ TON — On-delay timer
6
+
7
+ SR — Set/Reset latch (reset dominant)
8
+
9
+ These primitives are useful for industrial automation logic, simulations, or anywhere you want PLC-like control behavior in Python.
10
+
11
+ Installation
12
+ pip install timers-latches
13
+
14
+
15
+ Or, for development:
16
+
17
+ git clone https://github.com/yourorg/timers-latches.git
18
+ cd timers-latches
19
+ pip install -e .
20
+
21
+ Usage
22
+ from timers_latches import TON, SR
23
+
24
+ # --- TON example ---
25
+ ton = TON(preset_s=2.0) # 2-second delay
26
+ for step in range(5):
27
+ q = ton.update(enable=True, dt_s=0.5)
28
+ print(f"t={step*0.5:.1f}s, Q={q}")
29
+ # Q will turn True after 2.0 seconds of accumulated enable time
30
+
31
+ # --- SR example ---
32
+ latch = SR(initial=False)
33
+ print(latch.update(set_=True, reset=False)) # True
34
+ print(latch.update(set_=False, reset=True)) # False (reset dominates)
35
+
36
+ API
37
+ TON(preset_s: float)
38
+
39
+ preset_s: delay time in seconds (must be ≥ 0).
40
+
41
+ .update(enable: bool, dt_s: float) -> bool: call once per scan; returns the done bit (Q).
42
+
43
+ .Q: current output (done bit).
44
+
45
+ SR(initial: bool = False)
46
+
47
+ initial: starting state.
48
+
49
+ .update(set_: bool, reset: bool) -> bool: updates and returns current state. Reset dominates set.
50
+
51
+ .state: current latched state.
52
+
53
+ Versioning
54
+
55
+ Follows Semantic Versioning
56
+ .
57
+
58
+ API is stable from 1.0.0 onward.
59
+
60
+ License
61
+
62
+ MIT © Your Name / Your Organization
63
+
64
+ ⚡️ 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,24 @@
1
+
2
+ [build-system]
3
+ requires = ["hatchling"]
4
+ build-backend = "hatchling.build"
5
+
6
+ [project]
7
+ name = "primitives"
8
+ version = "0.1.0"
9
+ description = "Shared PLC-style primitives in Python"
10
+ authors = [{name="Neil Doell", email="neil@vococo.ca"}]
11
+ readme = "README.md"
12
+ license = "MIT"
13
+ requires-python = ">=3.9"
14
+ dependencies = []
15
+
16
+ [tool.hatch.build.targets.wheel]
17
+ packages = ["src/primitives"]
18
+
19
+ [tool.hatch.build.targets.wheel.force-include]
20
+ "src/primitives/py.typed" = "primitives/py.typed"
21
+
22
+ [tool.ruff.lint.per-file-ignores]
23
+ "primitives/__init__.py" = ["F403", "F405"]
24
+
@@ -0,0 +1,4 @@
1
+ from .ton import TON
2
+ from .sr import SR
3
+
4
+ __all__ = ["TON", "SR"]
File without changes
@@ -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
@@ -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)
File without changes
File without changes
@@ -0,0 +1,8 @@
1
+ version = 1
2
+ revision = 3
3
+ requires-python = ">=3.10"
4
+
5
+ [[package]]
6
+ name = "primitives"
7
+ version = "0.1.0"
8
+ source = { editable = "." }