mirror of
https://github.com/kuhyx/utils.git
synced 2026-11-12 08:31:01 +01:00
pylint --fail-under=10 everywhere, and clear what…
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file length / file-length (push) Waiting to run
leetcode-coach pre-commit / pre-commit (push) Waiting to run
leetcode-coach tests / test (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
palette drift / palette (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
shared gate tests / gate unit tests (push) Waiting to run
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
file length / file-length (push) Waiting to run
leetcode-coach pre-commit / pre-commit (push) Waiting to run
leetcode-coach tests / test (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
palette drift / palette (push) Waiting to run
repo-contract / repo contract (push) Waiting to run
shared gate tests / gate unit tests (push) Waiting to run
Todo: fda71ed1
This commit is contained in:
parent
f71b0532fd
commit
46ab26fa15
@ -112,8 +112,10 @@ repos:
|
|||||||
- id: pylint
|
- id: pylint
|
||||||
args:
|
args:
|
||||||
- --rcfile=leetcode_coach/pyproject.toml
|
- --rcfile=leetcode_coach/pyproject.toml
|
||||||
- --fail-under=8.0
|
- --fail-under=10
|
||||||
- --jobs=4
|
# --jobs=1: pylint's parallel mode pickles its state with dill,
|
||||||
|
# which crashes on Python 3.15 (no code.co_lnotab).
|
||||||
|
- --jobs=1
|
||||||
- leetcode_coach/leetcode_coach
|
- leetcode_coach/leetcode_coach
|
||||||
# Whole package, never the staged subset: a score over an arbitrary
|
# Whole package, never the staged subset: a score over an arbitrary
|
||||||
# handful of files is an arbitrary number. Kept in step with
|
# handful of files is an arbitrary number. Kept in step with
|
||||||
|
|||||||
@ -15,6 +15,7 @@ write is logged and retried in order; the relay never exits over it.
|
|||||||
|
|
||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import dataclasses
|
||||||
import functools
|
import functools
|
||||||
import json
|
import json
|
||||||
import logging
|
import logging
|
||||||
@ -54,6 +55,14 @@ def _pairs(event: sse.Event) -> list[tuple[list[str], object]]:
|
|||||||
return [(base, event.data)]
|
return [(base, event.data)]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclasses.dataclass
|
||||||
|
class _ChatMirror:
|
||||||
|
"""Which session's chat RTDB holds, and the line keys already sent."""
|
||||||
|
|
||||||
|
sid: str | None = None
|
||||||
|
sent: set[str] = dataclasses.field(default_factory=set)
|
||||||
|
|
||||||
|
|
||||||
class PhoneLink:
|
class PhoneLink:
|
||||||
"""Mirrors the relay into RTDB and feeds RTDB requests to the lane."""
|
"""Mirrors the relay into RTDB and feeds RTDB requests to the lane."""
|
||||||
|
|
||||||
@ -78,15 +87,14 @@ class PhoneLink:
|
|||||||
self._rescan_every = rescan_s
|
self._rescan_every = rescan_s
|
||||||
self.outbox = Outbox()
|
self.outbox = Outbox()
|
||||||
self._mirror_lock = threading.Lock()
|
self._mirror_lock = threading.Lock()
|
||||||
self._chat_sid: str | None = None
|
self._chat = _ChatMirror()
|
||||||
self._sent: set[str] = set()
|
|
||||||
|
|
||||||
def attach(self) -> None:
|
def attach(self) -> None:
|
||||||
"""Listen to the lane and the backend; then mirror everything once."""
|
"""Listen to the lane and the backend; then mirror everything once."""
|
||||||
self.lane.on_result.append(self.on_result)
|
self.lane.on_result.append(self.on_result)
|
||||||
self.lane.on_busy.append(lambda _busy: self.beat())
|
self.lane.on_busy.append(lambda _busy: self.beat())
|
||||||
self.coach.listeners.append(self.on_state)
|
self.coach.listeners.append(self.on_state)
|
||||||
self._chat_sid = None
|
self._chat.sid = None
|
||||||
self.on_state(self.coach.state(), self.coach.session)
|
self.on_state(self.coach.state(), self.coach.session)
|
||||||
|
|
||||||
def beat(self) -> None:
|
def beat(self) -> None:
|
||||||
@ -111,18 +119,18 @@ class PhoneLink:
|
|||||||
text = json.dumps(state, ensure_ascii=False)
|
text = json.dumps(state, ensure_ascii=False)
|
||||||
with self._mirror_lock:
|
with self._mirror_lock:
|
||||||
sid = None if session is None else session.sid
|
sid = None if session is None else session.sid
|
||||||
if sid != self._chat_sid:
|
if sid != self._chat.sid:
|
||||||
self.outbox.put(
|
self.outbox.put(
|
||||||
"chat reset", functools.partial(self.rtdb.delete, "chat")
|
"chat reset", functools.partial(self.rtdb.delete, "chat")
|
||||||
)
|
)
|
||||||
self._chat_sid, self._sent = sid, set()
|
self._chat = _ChatMirror(sid)
|
||||||
lines = {} if session is None else dict(session.chat)
|
lines = {} if session is None else dict(session.chat)
|
||||||
new: dict[str, object] = {
|
new: dict[str, object] = {
|
||||||
k: v for k, v in lines.items() if k not in self._sent
|
k: v for k, v in lines.items() if k not in self._chat.sent
|
||||||
}
|
}
|
||||||
if new:
|
if new:
|
||||||
self.outbox.put("chat", functools.partial(self.rtdb.patch, "chat", new))
|
self.outbox.put("chat", functools.partial(self.rtdb.patch, "chat", new))
|
||||||
self._sent |= set(new)
|
self._chat.sent |= set(new)
|
||||||
put = functools.partial(self.rtdb.put, "state", text)
|
put = functools.partial(self.rtdb.put, "state", text)
|
||||||
self.outbox.put("state", put, latest="state")
|
self.outbox.put("state", put, latest="state")
|
||||||
self.beat()
|
self.beat()
|
||||||
|
|||||||
@ -8,10 +8,18 @@ mechanically (no model, nothing to fail open), and the verdict rides the same
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import Final
|
from typing import Final, NamedTuple
|
||||||
|
|
||||||
from leetcode_coach import req_check
|
from leetcode_coach import req_check
|
||||||
|
|
||||||
|
|
||||||
|
class Facet(NamedTuple):
|
||||||
|
"""One part of an output shape: how to spot it, and what to ask for."""
|
||||||
|
|
||||||
|
pattern: re.Pattern[str]
|
||||||
|
hint: str
|
||||||
|
|
||||||
|
|
||||||
VIA: Final = "shape"
|
VIA: Final = "shape"
|
||||||
SHAPE_RE: Final = re.compile(r"^\s*shape\s*:", re.IGNORECASE)
|
SHAPE_RE: Final = re.compile(r"^\s*shape\s*:", re.IGNORECASE)
|
||||||
SQL_LANGS: Final = frozenset(
|
SQL_LANGS: Final = frozenset(
|
||||||
@ -20,15 +28,15 @@ SQL_LANGS: Final = frozenset(
|
|||||||
LANGUAGES_RE: Final = re.compile(r"^Languages available:(.*)$", re.MULTILINE)
|
LANGUAGES_RE: Final = re.compile(r"^Languages available:(.*)$", re.MULTILINE)
|
||||||
TAGS_RE: Final = re.compile(r"^Tags:(.*)$", re.MULTILINE)
|
TAGS_RE: Final = re.compile(r"^Tags:(.*)$", re.MULTILINE)
|
||||||
FACETS: Final = {
|
FACETS: Final = {
|
||||||
"columns": (
|
"columns": Facet(
|
||||||
re.compile(r"\b(?:columns?|fields?|headers?|named)\b", re.IGNORECASE),
|
re.compile(r"\b(?:columns?|fields?|headers?|named)\b", re.IGNORECASE),
|
||||||
"which columns come back, named how",
|
"which columns come back, named how",
|
||||||
),
|
),
|
||||||
"rows": (
|
"rows": Facet(
|
||||||
re.compile(r"\b(?:rows?|records?|per)\b", re.IGNORECASE),
|
re.compile(r"\b(?:rows?|records?|per)\b", re.IGNORECASE),
|
||||||
"what one row stands for (one row per ...)",
|
"what one row stands for (one row per ...)",
|
||||||
),
|
),
|
||||||
"grouping": (
|
"grouping": Facet(
|
||||||
re.compile(
|
re.compile(
|
||||||
r"\b(?:group\w*|aggregat\w*|distinct|unique|per|sum|count|ungrouped)\b",
|
r"\b(?:group\w*|aggregat\w*|distinct|unique|per|sum|count|ungrouped)\b",
|
||||||
re.IGNORECASE,
|
re.IGNORECASE,
|
||||||
@ -49,7 +57,9 @@ def is_sql(statement: str) -> bool:
|
|||||||
|
|
||||||
|
|
||||||
def missing_facets(text: str) -> tuple[str, ...]:
|
def missing_facets(text: str) -> tuple[str, ...]:
|
||||||
return tuple(name for name, (found, _) in FACETS.items() if not found.search(text))
|
return tuple(
|
||||||
|
name for name, facet in FACETS.items() if not facet.pattern.search(text)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
def check(text: str) -> req_check.Check:
|
def check(text: str) -> req_check.Check:
|
||||||
@ -58,4 +68,4 @@ def check(text: str) -> req_check.Check:
|
|||||||
|
|
||||||
|
|
||||||
def hints(missing: tuple[str, ...] | list[str]) -> list[str]:
|
def hints(missing: tuple[str, ...] | list[str]) -> list[str]:
|
||||||
return [f"{name}: {FACETS[name][1]}" for name in missing if name in FACETS]
|
return [f"{name}: {FACETS[name].hint}" for name in missing if name in FACETS]
|
||||||
|
|||||||
@ -5,7 +5,7 @@
|
|||||||
# none of them at import time.
|
# none of them at import time.
|
||||||
bandit[toml]==1.9.4
|
bandit[toml]==1.9.4
|
||||||
codespell==2.4.3
|
codespell==2.4.3
|
||||||
coverage==7.17.0
|
coverage==7.17.2
|
||||||
crdt-sync @ git+https://github.com/kuhyx/utils@crdt-sync-v0.9.2#subdirectory=crdt-sync
|
crdt-sync @ git+https://github.com/kuhyx/utils@crdt-sync-v0.9.2#subdirectory=crdt-sync
|
||||||
genanki==0.13.1
|
genanki==0.13.1
|
||||||
mypy==2.4.1
|
mypy==2.4.1
|
||||||
@ -16,5 +16,5 @@ pytest-cov==7.1.0
|
|||||||
pytest-randomly==5.0.0
|
pytest-randomly==5.0.0
|
||||||
pytest-xdist==3.8.0
|
pytest-xdist==3.8.0
|
||||||
requests==2.34.2
|
requests==2.34.2
|
||||||
ruff==0.17.3
|
ruff==0.17.4
|
||||||
types-requests==2.33.0.20261030
|
types-requests==2.33.0.20261030
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user