From 2787b4dfefacfc68e1daaf472530d06abe7e0cd4 Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 3 Apr 2026 16:18:41 +0000 Subject: [PATCH 1/2] Make Python files pass ty typechecker - Add pyproject.toml configuring ty to target Python 3.11 and ignore unresolved-import errors for third-party packages not in this env - config/qutebrowser/config.py: use cast(Any, None) in TYPE_CHECKING block so c and config are typed Any (bare annotations aren't definitions) - dot/jupyter/jupyter_notebook_config.py: suppress get_config undefined reference with type: ignore (injected by Jupyter at runtime) - py-scripts/wah.py: annotate data as Dict[str, Any] and replace walrus operator pattern that ty couldn't narrow through - venueQ/venueQ.py: add _Vim stub class so vim has correct attribute types in TYPE_CHECKING context; rename deprecated warn() to warning() - py-scripts/aur-auto-vote-with-chaotic.py: remove now-unused type: ignore https://claude.ai/code/session_01Pa53zwdcjHTSJcRZUxD6ib --- config/qutebrowser/config.py | 7 ++++--- dot/jupyter/jupyter_notebook_config.py | 2 +- py-scripts/aur-auto-vote-with-chaotic.py | 2 +- py-scripts/wah.py | 11 ++++++----- pyproject.toml | 5 +++++ venueQ/venueQ.py | 16 +++++++++++++--- 6 files changed, 30 insertions(+), 13 deletions(-) create mode 100644 pyproject.toml diff --git a/config/qutebrowser/config.py b/config/qutebrowser/config.py index 02ce754c..6827d55e 100644 --- a/config/qutebrowser/config.py +++ b/config/qutebrowser/config.py @@ -1,12 +1,13 @@ ## qutebrowser config.py -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING, Any, cast from qutebrowser.api import interceptor if TYPE_CHECKING: - c: Any = object - config: Any = object + # c and config are injected as globals by qutebrowser at runtime + c = cast(Any, None) + config = cast(Any, None) config.load_autoconfig() diff --git a/dot/jupyter/jupyter_notebook_config.py b/dot/jupyter/jupyter_notebook_config.py index 4b7fe4b8..7c0f7950 100644 --- a/dot/jupyter/jupyter_notebook_config.py +++ b/dot/jupyter/jupyter_notebook_config.py @@ -1,6 +1,6 @@ # Configuration file for notebook. -c = get_config() # noqa +c = get_config() # type: ignore # noqa # ------------------------------------------------------------------------------ # Application(SingletonConfigurable) configuration diff --git a/py-scripts/aur-auto-vote-with-chaotic.py b/py-scripts/aur-auto-vote-with-chaotic.py index db0d880a..b4e8b7b0 100644 --- a/py-scripts/aur-auto-vote-with-chaotic.py +++ b/py-scripts/aur-auto-vote-with-chaotic.py @@ -103,7 +103,7 @@ def login(session, username, password): return bool( navbar.find( "form", - action=lambda h: h and h.rstrip("/").endswith("/logout"), # type: ignore + action=lambda h: h and h.rstrip("/").endswith("/logout"), ) ) diff --git a/py-scripts/wah.py b/py-scripts/wah.py index 3ece0de4..723551e0 100644 --- a/py-scripts/wah.py +++ b/py-scripts/wah.py @@ -9,7 +9,7 @@ import argparse import datetime from pathlib import Path -from typing import Dict, List +from typing import Any, Dict, List import yaml from colorama import Back, Fore, Style, init @@ -134,6 +134,7 @@ def save(path, data): # read wah data needs_save = False + data: Dict[str, Any] if save_path.exists(): data = yaml.load(save_path.read_text(), Loader=yaml.SafeLoader) else: @@ -160,10 +161,10 @@ def save(path, data): if needs_save is True: save(save_path, data) - min_hours: float = _ if (_ := data["min_hours"]) is not None else 0.75 - max_hours: float = _ if (_ := data["max_hours"]) is not None else 4.0 - min_lpm: float = _ if (_ := data["min_lpm"]) is not None else 0.1 - max_lpm: float = _ if (_ := data["max_lpm"]) is not None else 1 + min_hours: float = data["min_hours"] if data["min_hours"] is not None else 0.75 + max_hours: float = data["max_hours"] if data["max_hours"] is not None else 4.0 + min_lpm: float = data["min_lpm"] if data["min_lpm"] is not None else 0.1 + max_lpm: float = data["max_lpm"] if data["max_lpm"] is not None else 1 decision: Dict[str, bool] = data.get("decision", {}) # hexsha -> true or false time = datetime.timedelta(hours=0) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 00000000..070a8a2c --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,5 @@ +[tool.ty.environment] +python-version = "3.11" + +[tool.ty.rules] +unresolved-import = "ignore" diff --git a/venueQ/venueQ.py b/venueQ/venueQ.py index 3bd83e13..5cae8bb9 100644 --- a/venueQ/venueQ.py +++ b/venueQ/venueQ.py @@ -21,7 +21,17 @@ def repr_str(dumper: yaml.SafeDumper, data: str) -> yaml.ScalarNode: yaml.add_representer(str, repr_str, Dumper=yaml.SafeDumper) if TYPE_CHECKING: - vim: Any = None + + class _Vim: + """Stub for the vim C extension module.""" + + class error(Exception): ... + + buffers: Any + + def command(self, s: str) -> None: ... + + vim = _Vim() VIM_ENABLED = True else: try: @@ -276,7 +286,7 @@ def queue_wipe(self, p: Path): self.wipe_queue.append(b.number) break else: - logger.warn( + logger.warning( f"Tried to wipe {p} but found no buffer for it among " + ", ".join(b.name for b in vim.buffers) ) @@ -288,7 +298,7 @@ def wipe(self): try: vim.command(f"bdelete! {bn}") except vim.error: - logging.warn( + logging.warning( f"Could not delete buffer {bn}, maybe it was deleted already." ) self.wipe_queue = [] From 2c581c35b755e50ced4d194ab09562b9aace18ef Mon Sep 17 00:00:00 2001 From: Claude Date: Fri, 3 Apr 2026 19:26:37 +0000 Subject: [PATCH 2/2] Use ty.toml instead of pyproject.toml; fix datetime.UTC - Replace pyproject.toml with ty.toml (more appropriate for a dotfiles repo that isn't a Python project) - Drop python-version setting; only configure unresolved-import = "ignore" - venueQ/otis.py: replace datetime.UTC (Python 3.11+) with timezone.utc which works in all Python 3 versions https://claude.ai/code/session_01Pa53zwdcjHTSJcRZUxD6ib --- pyproject.toml | 5 ----- ty.toml | 2 ++ venueQ/otis.py | 10 +++++----- 3 files changed, 7 insertions(+), 10 deletions(-) delete mode 100644 pyproject.toml create mode 100644 ty.toml diff --git a/pyproject.toml b/pyproject.toml deleted file mode 100644 index 070a8a2c..00000000 --- a/pyproject.toml +++ /dev/null @@ -1,5 +0,0 @@ -[tool.ty.environment] -python-version = "3.11" - -[tool.ty.rules] -unresolved-import = "ignore" diff --git a/ty.toml b/ty.toml new file mode 100644 index 00000000..2ce7b9d9 --- /dev/null +++ b/ty.toml @@ -0,0 +1,2 @@ +[rules] +unresolved-import = "ignore" diff --git a/venueQ/otis.py b/venueQ/otis.py index bd0a9805..65a74048 100644 --- a/venueQ/otis.py +++ b/venueQ/otis.py @@ -8,7 +8,7 @@ import subprocess import time import webbrowser -from datetime import UTC, datetime +from datetime import datetime, timezone from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText from importlib.util import find_spec @@ -511,9 +511,9 @@ def on_buffer_close(self, data: Data): if data["accept_all"]: if query_otis_server(payload={"action": "accept_inquiries"}): body = "This is an automated message to notify you that your recent unit petition\n" - body += f"was processed on {datetime.now(UTC).strftime('%-d %B %Y, %H:%M')} UTC." + body += f"was processed on {datetime.now(timezone.utc).strftime('%-d %B %Y, %H:%M')} UTC." body += "\n\n" - body += f"Have a nice {datetime.now(UTC).strftime('%A')}." + body += f"Have a nice {datetime.now(timezone.utc).strftime('%A')}." recipients = [ inquiry["student__user__email"] for inquiry in data["inquiries"] @@ -545,7 +545,7 @@ def on_buffer_close(self, data: Data): "You are receiving this message because you checked the box " "asking to be notified once your decision form was processed.\n\n" "We're happy to confirm that your decision form\n" - f"was processed on {datetime.now(UTC).strftime('%-d %B %Y, %H:%M')} UTC " + f"was processed on {datetime.now(timezone.utc).strftime('%-d %B %Y, %H:%M')} UTC " "and your account is now fully activated!" "You should be able to log in and pick your units now,\n" "and use the /register slash command in the Discord." @@ -790,7 +790,7 @@ def callback(): "You are receiving this message because you checked the box " "asking to be notified by email when your application was reviewed.\n\n" "We're letting you know that your OTIS application was reviewed at " - f"{datetime.now(UTC).strftime('%-d %B %Y, %H:%M')} UTC. " + f"{datetime.now(timezone.utc).strftime('%-d %B %Y, %H:%M')} UTC. " "You can see the decision (and comments if any) on the " f"website {linkify('https://apply.evanchen.cc')} " "by logging in to the account you used when you submitted."