@@ -77,7 +77,7 @@ pytest tests/test_commands.py::test_nec_command_get_raw_timings_standard
7777```
7878infrared_protocols/ # Library source (only this directory is linted/type-checked)
7979 __init__.py # Public API: defines __all__ and re-exports
80- commands.py # All domain logic: Command ABC, NECCommand, Timing
80+ commands.py # All domain logic: Command ABC, NECCommand
8181tests/
8282 test_commands.py # pytest suite (all tests in one file)
8383script/
@@ -111,7 +111,7 @@ pyproject.toml # Build config, ruff rules, pyright settings
111111| ---| ---| ---|
112112| Files / modules | ` snake_case ` | ` commands.py ` |
113113| Packages | ` snake_case ` | ` infrared_protocols ` |
114- | Classes | ` PascalCase ` | ` NECCommand ` , ` Timing ` |
114+ | Classes | ` PascalCase ` | ` NECCommand ` , ` Command ` |
115115| Functions / methods | ` snake_case ` | ` get_raw_timings ` |
116116| Variables / attributes | ` snake_case ` | ` high_us ` , ` repeat_count ` |
117117| Local numeric constants | ` snake_case ` (not ` UPPER_CASE ` ) | ` leader_high = 9000 ` |
@@ -125,11 +125,11 @@ pyproject.toml # Build config, ruff rules, pyright settings
125125- Type checker: ` basedpyright ` with ` typeCheckingMode = "standard" ` .
126126- ** All** function parameters and return types must be annotated.
127127- ` -> None ` must be explicit on ` __init__ ` and void methods.
128- - Use PEP 585 lowercase generics: ` list[Timing ] ` , not ` List[Timing ] ` .
128+ - Use PEP 585 lowercase generics: ` list[int ] ` , not ` List[int ] ` .
129129- Use PEP 604 union syntax: ` T | None ` , not ` Optional[T] ` .
130130- Use ` @override ` (from ` typing ` , Python 3.12+) on every overridden method.
131131- No ` Any ` ; avoid ` cast ` ; prefer real type narrowing.
132- - Inline variable annotations where needed: ` timings: list[Timing ] = [] ` .
132+ - Inline variable annotations where needed: ` timings: list[int ] = [] ` .
133133
134134### Classes
135135- Abstract base classes use ` abc.ABC ` and ` @abc.abstractmethod ` .
@@ -144,7 +144,7 @@ pyproject.toml # Build config, ruff rules, pyright settings
144144 parameter sections unless complexity demands it.
145145
146146``` python
147- def get_raw_timings (self ) -> list[Timing ]:
147+ def get_raw_timings (self ) -> list[int ]:
148148 """ Get raw timings for the NEC command.
149149
150150 NEC protocol timing (in microseconds):
@@ -159,33 +159,36 @@ def get_raw_timings(self) -> list[Timing]:
159159
160160### Adding a New Protocol
1611611 . Subclass ` Command ` (ABC) in ` infrared_protocols/commands.py ` .
162- 2 . Implement ` get_raw_timings(self) -> list[Timing ] ` .
162+ 2 . Implement ` get_raw_timings(self) -> list[int ] ` .
1631633 . Decorate the override with ` @override ` .
1641644 . Define timing constants as local ` snake_case ` variables inside the method.
1651655 . Re-export the new class from ` infrared_protocols/__init__.py ` and add it to
166166 ` __all__ ` .
167167
168168### Key Abstractions
169- - ** ` Timing(high_us, low_us) ` ** — frozen dataclass representing one pulse+space pair
170- (microseconds). Immutable, comparable by value.
169+ - ** Raw timings** — a flat ` list[int] ` of microsecond durations. Positive values are
170+ pulse (high) durations; negative values are space (low) durations. A transmission
171+ that ends on a pulse is represented by a trailing positive int with no paired
172+ space.
171173- ** ` Command ` (ABC)** — base class for all IR protocol encoders. Holds ` modulation `
172174 and ` repeat_count ` .
173175- ** ` NECCommand(Command) ` ** — encodes the NEC protocol; reference implementation.
174176
175177### Patterns to Follow
176- - Build timing lists by starting with a base list, appending in a loop, then using
177- ` extend() ` for repeat frames.
178- - Repeat-code frame gaps replace the last timing's ` low_us ` (see ` NECCommand ` ).
178+ - Build timing lists by starting with a base list, appending pulse/space ints in a
179+ loop, then using ` extend() ` for repeat frames.
180+ - Repeat-code frame gaps are appended as a negative int directly after the preceding
181+ end-pulse (see ` NECCommand ` ).
179182- Bit manipulation uses masks like ` data & 1 ` , ` data >>= 1 ` , ` (~x) & 0xFF ` .
180183
181184---
182185
183186## Testing
184187
185188- No mocking. Tests use pure value comparison against manually constructed
186- ` list[Timing ] ` fixtures.
189+ ` list[int ] ` fixtures of signed pulse/space durations .
187190- One assertion per logical case; reuse expected values with list unpacking
188- (` [*expected[:-1] , ...] ` ) rather than duplicating fixtures.
191+ (` [*expected, ...] ` ) rather than duplicating fixtures.
189192- Tests live in ` tests/test_commands.py ` ; keep them in one file unless the suite
190193 grows substantially.
191194- Pre-commit hooks (` prek ` ) do ** not** run on ` tests/ ` ; the type checker and linter
0 commit comments