Repository navigation
several bug fixes #5
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
a316402
606a154
9ff8d00
6421d38
f82b089
8d040e1
ccf539c
2161b63
5cac731
03b728d
04ace59
ec94ed6
698a884
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -24,3 +24,6 @@ docs/ | |
| .claude/ | ||
| .agents/ | ||
| skills-lock.json | ||
|
|
||
| # logs | ||
| *.log | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,9 @@ | ||
| @echo off | ||
| ( | ||
| uv run mypy || exit /b 1 | ||
| uv run ruff format --check . || exit /b 1 | ||
| uv run ruff check . || exit /b 1 | ||
| uv run pylint tests tg_logging_handler || exit /b 1 | ||
| uv run flake8 tests tg_logging_handler || exit /b 1 | ||
| uv run pytest --cov=tg_logging_handler || exit /b 1 | ||
| ) > local.log 2>&1 | ||
|
Comment on lines
+1
to
+9
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win Store the batch file with CRLF line endings. Static analysis reports LF-only line endings. Convert this 🧰 Tools🪛 Blinter (1.1.7)[error] 1-1: Unix line endings detected. Explanation: Batch file uses Unix line endings (LF-only) which can cause GOTO/CALL label parsing failures and script malfunction due to Windows batch parser 512-byte boundary bugs. Recommendation: Convert file to Windows line endings (CRLF). Use tools like dos2unix, notepad++, or configure git with 'git config core.autocrlf true'. Context: File uses Unix line endings (LF-only) - 9 LF sequences found (E018) [warning] 8-8: Missing exit code. Explanation: Script doesn't set appropriate exit codes to indicate success or failure. Recommendation: Add EXIT /b 0 for success or EXIT /b 1 for errors at script end. Context: Script can reach end of file without explicit EXIT statement (W001) 🤖 Prompt for AI AgentsSource: Linters/SAST tools |
||
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -109,3 +109,68 @@ def test_constructor_validates_args() -> None: | |||||||||||||||||||||||||||||||||||||||||||||||||||||
| BatchAccumulator(0, 1.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| with pytest.raises(ValueError): | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| BatchAccumulator(1, -1.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| class _TimeoutQueue: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| """Scripted queue whose get() always times out (raises Empty).""" | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def __init__(self) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._items: list[object] = [] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def put_nowait(self, item: object) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| self._items.append(item) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def get(self, timeout: float | None = None) -> object: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| if not self._items: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| raise queue.Empty | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| return self._items.pop(0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def task_done(self) -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| pass | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_second_get_timeout_returns_partial_batch() -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # The mid-batch get() can time out with nothing new arriving; the partial | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # batch must be returned, not lost. Constant clock keeps remaining > 0 so | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # the get() is actually attempted (and times out immediately, scripted). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| acc, _ = _mk(batch_size=5, flush_interval=1.0, clock=ScriptedClock(0.0, 0.0)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| q = _TimeoutQueue() | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| q.put_nowait(_record("only")) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| batch, shutdown = acc.collect(q, Shutdown, timeout=0) # type: ignore[arg-type] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert [r.getMessage() for r in batch] == ["only"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert not shutdown | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_stop_flushes_partial_batch_promptly() -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # A shutdown requested while a partial batch is mid-collection must flush | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # it immediately, not wait out the flush interval (potentially minutes); | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # collect polls the stop predicate after a capped wait with nothing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # arriving. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| acc, q = _mk(batch_size=10, flush_interval=30.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _put(q, "only") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| batch, shutdown = acc.collect(q, Shutdown, timeout=0, stop=lambda: True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert [r.getMessage() for r in batch] == ["only"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert shutdown is False | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_stop_does_not_split_a_flowing_batch() -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Live-smoke regression: close() sets the shutdown event while the worker | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # is still draining a queue full of records. stop must only be consulted | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # once a wait actually elapsed with nothing arriving, or every flowing | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # record flushes as its own batch. stop=True here must not split the 5 | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # queued records (batch_size is exactly 5, so they must come back whole). | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| acc, q = _mk(batch_size=5, flush_interval=10.0) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _put(q, "a", "b", "c", "d", "e") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| batch, shutdown = acc.collect(q, Shutdown, timeout=0, stop=lambda: True) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert [r.getMessage() for r in batch] == ["a", "b", "c", "d", "e"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert not shutdown | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||||||||||||||||||||||||
| def test_stop_false_after_capped_wait_keeps_collecting() -> None: | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # Stop present but still False when a capped wait elapses: the loop must | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| # keep going (re-check the interval) instead of aborting an active batch. | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| acc, q = _mk(batch_size=10, flush_interval=5.0, clock=ScriptedClock(0.0, 0.0, 0.0, 5.0)) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| _put(q, "a", "b") | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| batch, shutdown = acc.collect(q, Shutdown, timeout=0, stop=lambda: False) | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert [r.getMessage() for r in batch] == ["a", "b"] | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
| assert not shutdown | ||||||||||||||||||||||||||||||||||||||||||||||||||||||
|
Comment on lines
+169
to
+176
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win
Both records are already queued, so the mid-batch Drive the empty capped wait explicitly: queue one record, then let the queue report ♻️ Suggested test change def test_stop_false_after_capped_wait_keeps_collecting() -> None:
# Stop present but still False when a capped wait elapses: the loop must
# keep going (re-check the interval) instead of aborting an active batch.
- acc, q = _mk(batch_size=10, flush_interval=5.0, clock=ScriptedClock(0.0, 0.0, 0.0, 5.0))
- _put(q, "a", "b")
- batch, shutdown = acc.collect(q, Shutdown, timeout=0, stop=lambda: False)
- assert [r.getMessage() for r in batch] == ["a", "b"]
+ # remaining stays 5.0 > _MAX_RECORD_WAIT on the first wait (capped -> stop
+ # polled -> False -> continue), then the interval elapses on the recheck.
+ acc, _ = _mk(batch_size=10, flush_interval=5.0, clock=ScriptedClock(0.0, 0.0, 5.0))
+ q = _TimeoutQueue()
+ q.put_nowait(_record("a"))
+ calls: list[bool] = []
+
+ def stop() -> bool:
+ calls.append(False)
+ return False
+
+ batch, shutdown = acc.collect(q, Shutdown, timeout=0, stop=stop) # type: ignore[arg-type]
+ assert [r.getMessage() for r in batch] == ["a"]
+ assert calls # the capped-wait branch was actually taken
assert not shutdown📝 Committable suggestion
Suggested change
🤖 Prompt for AI Agents |
||||||||||||||||||||||||||||||||||||||||||||||||||||||
Uh oh!
There was an error while loading. Please reload this page.