Skip to content

Commit 598b78d

Browse files
quantbaiclaude
andauthored
feat: docs restructure, show_versions, pyright CI, remove 1e-10 zero guards (#6)
* feat(ci): add pyright static type checking - Fix 4 pyright errors in factor.py (hash annotation, eq/ne override, dead code) - Add pyright to CI pipeline and dev dependencies - Remove _resolve_other (dead code after _binary refactor) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> * docs: add pyright to all checklists and update changelog for 0.4.0 - PR template: add pyright check item - README Development section: add pyright command - CONTRIBUTING: add pyright to verify, dev cycle, and pre-PR checklist - CHANGELOG [Unreleased]: full list of additions and changes since 0.3.0 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1 parent 1e43a84 commit 598b78d

8 files changed

Lines changed: 26 additions & 15 deletions

File tree

.github/pull_request_template.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
- [ ] Added or updated tests
1919
- [ ] All tests pass (`pytest tests/ -v`)
2020
- [ ] Lint passes (`ruff check elvers/`)
21+
- [ ] Type check passes (`pyright elvers/`)
2122

2223
## New Operator Checklist
2324
<!-- Delete this section if not adding a new operator -->

.github/workflows/ci.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,4 +19,5 @@ jobs:
1919
python-version: ${{ matrix.python-version }}
2020
- run: pip install -e ".[dev]"
2121
- run: ruff check elvers/
22+
- run: pyright elvers/
2223
- run: pytest tests/ -v

CHANGELOG.md

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,19 @@ Numerical changes are marked with [NUMERICAL].
77

88
## [Unreleased]
99

10+
### Added
11+
- `show_versions()` for environment diagnostics in bug reports
12+
- Pyright static type checking in CI pipeline
13+
- Community templates: issue templates (bug, feature, new operator), CODE_OF_CONDUCT, SECURITY
14+
- CONTRIBUTING.md with workflow, numerical invariants, and design rationale
15+
- Timestamp type validation in loader (must be pl.Date or pl.Datetime)
16+
- `_check_intervals()` warns about irregular timestamp spacing
17+
1018
### Changed
11-
- [NUMERICAL] Removed arbitrary `1e-10` zero guards across all operators. Pure divisions (divide, inverse) now flow through Factor constructor (Inf → null). Statistical and regression operators use exact zero checks for degenerate cases (constant series). No more silent data loss from legitimate small values.
19+
- [NUMERICAL] Removed arbitrary `1e-10` zero guards across all operators. Pure divisions (divide, inverse) now flow through Factor constructor (Inf → null). Statistical and regression operators use exact zero checks for degenerate cases (constant series).
20+
- Replaced interval-based panel skeleton with union-based skeleton (no frequency inference)
21+
- Restructured documentation: CLAUDE.md (AI memo), CONTRIBUTING.md (human guide), no duplication
22+
- Removed `interval` parameter from `load()`
1223

1324
## [0.3.0] - 2026-03-24
1425

CLAUDE.md

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,3 @@ Data loading pipeline (each function has one responsibility):
5858
- `_validation.py`: not wired into all operator entry points
5959
- `_dev.py`: Python callbacks, not production-grade
6060
- No property-based testing or performance benchmarks
61-
- No static type checking (mypy/pyright) in CI; type hints are written but not enforced

CONTRIBUTING.md

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ Verify:
2222
```bash
2323
pytest tests/ -v
2424
ruff check elvers/
25+
pyright elvers/
2526
```
2627

2728
---
@@ -45,7 +46,7 @@ All changes enter through pull requests to `dev`.
4546
git checkout dev && git pull upstream dev # 1. sync
4647
git checkout -b feature/ts-entropy # 2. branch
4748
# ... implement ...
48-
ruff check elvers/ && pytest tests/ -v # 3. verify
49+
ruff check elvers/ && pyright elvers/ && pytest tests/ -v # 3. verify
4950
git add <specific files> # 4. stage (never git add -A)
5051
git commit -m "feat(ops): add ts_entropy" # 5. commit
5152
git push -u origin feature/ts-entropy # 6. push
@@ -89,6 +90,7 @@ Add entry to [OPERATORS.md](OPERATORS.md).
8990
### 6. Pre-PR Checklist
9091

9192
- [ ] `ruff check elvers/` passes
93+
- [ ] `pyright elvers/` passes
9294
- [ ] `pytest tests/ -v` passes (full suite)
9395
- [ ] Operator in `__init__.py` exports and `__all__`
9496
- [ ] Docstring: description, parameters, return type, null behavior, warmup
@@ -126,6 +128,7 @@ Full conventions: [OPERATORS.md](OPERATORS.md).
126128
## Style
127129

128130
- Ruff for formatting and linting (line-length = 120)
131+
- Pyright for static type checking (zero errors required in CI)
129132
- English for all code, comments, commits, and documentation
130133
- No emoji
131134

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ Full specifications: **[OPERATORS.md](OPERATORS.md)**
8080
pip install -e ".[dev]"
8181
pytest tests/ -v
8282
ruff check elvers/
83+
pyright elvers/
8384
```
8485

8586
See [CONTRIBUTING.md](CONTRIBUTING.md) for the contributor guide.

elvers/core/factor.py

Lines changed: 6 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ class Factor:
1818
"""
1919

2020
__slots__ = ("_df", "_name")
21-
__hash__ = None
21+
__hash__: None # type: ignore[assignment] # Unhashable by design: __eq__ returns Factor
2222

2323
def __init__(self, df: pl.DataFrame, name: str):
2424
required = {"timestamp", "symbol", "factor"}
@@ -54,21 +54,15 @@ def __repr__(self) -> str:
5454
preview_df = self._df.sort(["timestamp", "symbol"])
5555
return f"Factor({self._name}, rows={len(self._df)})\n{preview_df.__repr__()}"
5656

57-
def _resolve_other(self, other: Factor | int | float):
57+
def _binary(self, other: Factor | int | float, op, op_sym: str) -> Factor:
5858
if isinstance(other, Factor):
5959
left = self._df.rename({"factor": "_l"})
6060
right = other._df.select(["timestamp", "symbol", pl.col("factor").alias("_r")])
6161
merged = left.join(right, on=["timestamp", "symbol"], how="inner")
62-
return merged, "_l", "_r", other._name
63-
return self._df, "factor", None, str(other)
64-
65-
def _binary(self, other, op, op_sym) -> Factor:
66-
if isinstance(other, Factor):
67-
merged, lc, rc, oname = self._resolve_other(other)
6862
result = merged.with_columns(
69-
op(pl.col(lc), pl.col(rc)).alias("factor")
63+
op(pl.col("_l"), pl.col("_r")).alias("factor")
7064
).select(["timestamp", "symbol", "factor"])
71-
return Factor(result, f"({self._name}{op_sym}{oname})")
65+
return Factor(result, f"({self._name}{op_sym}{other._name})")
7266
result = self._df.with_columns(
7367
op(pl.col("factor"), pl.lit(other)).alias("factor")
7468
)
@@ -142,8 +136,8 @@ def __lt__(self, other):
142136
def __le__(self, other):
143137
return self._binary(other, lambda a, b: a <= b, "<=")
144138

145-
def __eq__(self, other):
139+
def __eq__(self, other) -> Factor: # type: ignore[override] # Element-wise, not scalar bool
146140
return self._binary(other, lambda a, b: a == b, "==")
147141

148-
def __ne__(self, other):
142+
def __ne__(self, other) -> Factor: # type: ignore[override] # Element-wise, not scalar bool
149143
return self._binary(other, lambda a, b: a != b, "!=")

pyproject.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ version = {attr = "elvers.__version__"}
4444
dev = [
4545
"pytest>=7.0",
4646
"ruff>=0.4.0",
47+
"pyright>=1.1",
4748
"pre-commit>=3.0",
4849
]
4950

0 commit comments

Comments
 (0)