Skip to content

[RUFF] Enable DTZ rule (datetime timezone)#1041

Open
agentydragon wants to merge 2 commits intodevelfrom
claude/ruff-enable-dtz
Open

[RUFF] Enable DTZ rule (datetime timezone)#1041
agentydragon wants to merge 2 commits intodevelfrom
claude/ruff-enable-dtz

Conversation

@agentydragon
Copy link
Copy Markdown
Owner

Summary

  • Enable DTZ (flake8-datetimez) in ruff.toml
  • Fix all 135 violations: add explicit timezone to all datetime construction
  • datetime.now()datetime.now(tz=UTC), fromtimestamp(t)fromtimestamp(t, tz=UTC), strptime(...).replace(tzinfo=UTC)
  • Uses from datetime import UTC (Python 3.11+ module-level constant)

https://claude.ai/code/session_013WcexLQ8JPJG1j79uvMfCF

Copilot AI review requested due to automatic review settings March 27, 2026 17:44
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR enables Ruff’s DTZ (flake8-datetimez) ruleset repository-wide and updates code to use explicit UTC when constructing datetimes, eliminating naive datetime usage.

Changes:

  • Enable DTZ in ruff.toml.
  • Replace naive datetime construction patterns (now(), utcnow(), fromtimestamp(), strptime()) with explicit UTC equivalents across the repo.
  • Opportunistically modernize some logging calls (avoid f-strings in logger calls; add UTC timestamps to logs).

Reviewed changes

Copilot reviewed 57 out of 57 changed files in this pull request and generated 9 comments.

Show a summary per file
File Description
x/skype_history/skype_history.py Make fromtimestamp UTC-aware.
x/gatelet/server/models.py Use UTC-aware datetime.now() for validity checks.
x/gatelet/server/endpoints/test_challenge.py Update tests to use UTC-aware timestamps.
x/gatelet/server/endpoints/challenge.py Use UTC-aware timestamps for nonce/session creation.
x/gatelet/server/endpoints/admin.py Use UTC-aware timestamps for admin sessions and key actions.
x/gatelet/server/conftest.py Use UTC-aware timestamps in fixtures/stubs.
x/gatelet/server/auth/test_key_path_auth.py Use UTC-aware timestamps in tests.
x/gatelet/server/auth/test_key_auth.py Use UTC-aware timestamps in tests.
x/gatelet/server/auth/test_handlers.py Use UTC-aware timestamps in tests.
x/gatelet/server/auth/handlers.py Use UTC-aware now() in session/admin auth logic.
x/gatelet/server/app.py Use UTC-aware now() for admin session redirect check.
x/ember_evals/scenarios/regression.py Make date parsing/comparison UTC-based.
x/ember_evals/runner.py Make run metadata timestamps UTC-based.
x/cotrl/llm_rl_experiment.py Use UTC-aware timestamps for experiment logging and duration.
x/claude_linter_v2/test_multiline_predicates.py Use UTC-aware timestamps in predicate tests.
x/claude_linter_v2/test_mcp_tools.py Use UTC-aware timestamps in tool logging tests.
x/claude_linter_v2/session/violations.py Use UTC-aware timestamps in violation records.
x/claude_linter_v2/session/state.py Use UTC-aware timestamps for session state updates.
x/claude_linter_v2/session/manager.py Use UTC-aware timestamps; improve logger formatting.
x/claude_linter_v2/hooks/handler.py Use UTC-aware timestamps; adjust logger formatting and log-level parsing.
x/claude_linter_v2/cli.py Use UTC-aware expiry parsing; improve logger formatting.
x/claude_linter/precommit_runner.py Use UTC-aware timestamps in debug logs.
x/claude_linter/cli.py Use UTC-aware timestamps for cleanup cutoff and hook logs.
x/agent_server/presets.py Use UTC-aware fromtimestamp; improve logger formatting.
wt/testing/conftest.py Use UTC-aware timestamps in test fixtures.
wt/shared/protocol.py Use UTC-aware timestamps in protocol collectors.
wt/server/wt_server.py Use UTC-aware timestamps for request timing; tweak shutdown task attribute.
wt/server/types.py Use UTC-aware _now() helper.
wt/server/handlers/status_handler.py Use UTC-aware last_updated_at.
wt/integration/test_integration_cli_output_format.py Use UTC-aware timestamps in integration tests.
wt/e2e/test_github_pr_display_variants.py Use UTC-aware merged timestamp in tests.
trilium/search_hack.py Use UTC-aware timestamps in embeddings metadata.
tana/export/convert.py Make strptime results UTC-aware.
sysrw/run_eval.py Use UTC-aware timestamps for output directories.
skills/proxmox_vm/vm_interact.py Use UTC-aware timestamps for screenshot naming.
ruff.toml Enable DTZ rules.
props/core/gepa/gepa_adapter.py Use UTC-aware timestamps; improve logger formatting.
props/cli/cmd_db.py Use UTC-aware timestamps for backups and listing.
llm/ultra_long_cot/ultra_long_cot_o4.py Use UTC-aware timestamps for session timing/log naming.
llm/mcp/habitify/utils/date_utils.py Use UTC-aware defaults and UTC-aware strptime parsing.
llm/mcp/habitify/test_habitify_client.py Use UTC-based “today” in tests.
llm/mcp/habitify/cli.py Use UTC-aware display dates; improve exception logging.
llm/html/llm_html/test_token.py Use UTC-aware timestamps for token generation tests.
llm/hook_logging.py Use UTC-aware fromtimestamp when emitting JSON logs.
gmail_archiver/planners/usps.py Make parsed dates UTC-aware.
gmail_archiver/planners/test_square.py Update expected datetimes to be UTC-aware.
gmail_archiver/planners/test_anthropic.py Update expected datetimes to be UTC-aware.
gmail_archiver/planners/square.py Make parsed transaction datetime UTC-aware.
gmail_archiver/planners/anthem_reimbursement.py Make parsed care date UTC-aware.
gmail_archiver/planners/aliexpress.py Normalize file formatting; make delivered date UTC-aware.
finance/reconcile/splitwise_lib.py Make parsed API datetime UTC-aware.
finance/reconcile/cli.py Use UTC-aware timestamps for notes; make parsed dates UTC-aware.
devinfra/claude/hook_daemon/session_start/handler.py Use UTC-aware session start timestamps.
debug/spice_lag/record.py Use UTC-aware timestamps for recording labels.
debug/spice_lag/analyze.py Make parsed clock times UTC-aware.
cluster/k8s/inventree/token-provisioner/provision.py Use UTC-based “today” for expiry calculations.
agent_cli/cli.py Use UTC-aware timestamps for transcript naming.

Comment on lines 113 to +114
"""Check if nonce is valid (not used and not expired)."""
return self.used_at is None and datetime.now() < self.expires_at
return self.used_at is None and datetime.now(tz=UTC) < self.expires_at
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same naive/aware mismatch risk here: self.expires_at comes from a DateTime (no timezone) column, but datetime.now(tz=UTC) is offset-aware. This will throw when evaluating is_valid unless the model/db schema uses timezone-aware datetimes or both sides are normalized.

Copilot uses AI. Check for mistakes.
Comment on lines +39 to 40
if not admin_session or admin_session.expires_at <= datetime.now(tz=UTC):
raise HTTPException(status_code=status.HTTP_401_UNAUTHORIZED)
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

admin_session.expires_at is stored in a SQLAlchemy DateTime column without timezone support, so it's likely offset-naive. Comparing it to datetime.now(tz=UTC) will raise TypeError (naive vs aware). Consider migrating the Gatelet datetime columns to DateTime(timezone=True) (and emitting UTC everywhere) or normalizing both sides to naive UTC before comparing.

Copilot uses AI. Check for mistakes.
Comment on lines +132 to +137
try:
level_value = logging._nameToLevel.get(log_level.upper(), logging.INFO)
level_value = logging.getLevelName(log_level.upper())
file_handler.setLevel(level_value)
except (AttributeError, KeyError):
file_handler.setLevel(logging.INFO)
logger.warning(f"Invalid log level '{log_level}', using INFO")
logger.warning("Invalid log level '%s', using INFO", log_level)
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

logging.getLevelName(log_level.upper()) returns a string (e.g. 'INFO' or 'Level INFO'), not the numeric level expected here, and setLevel(...) can raise ValueError for unknown strings (not caught by the current exception list). Use logging._nameToLevel.get(...), logging.getLevelNamesMapping().get(...), or pass log_level.upper() directly to setLevel and catch ValueError.

Copilot uses AI. Check for mistakes.
Comment on lines 96 to +97
"""Check if session is currently valid."""
return self.expires_at > datetime.now()
return self.expires_at > datetime.now(tz=UTC)
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

self.expires_at is stored in a SQLAlchemy DateTime column without timezone=True, so it's expected to be offset-naive. Comparing it to datetime.now(tz=UTC) will raise a naive/aware TypeError at runtime unless the DB layer is switched to timezone-aware datetimes (or values are normalized before comparison).

Copilot uses AI. Check for mistakes.
labels=request.labels,
secrets=request.secrets,
started_at=datetime.datetime.utcnow().isoformat() + "Z",
started_at=datetime.datetime.now(tz=datetime.UTC).isoformat() + "Z",
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

datetime.datetime.now(tz=datetime.UTC).isoformat() already includes a UTC offset (e.g. +00:00). Appending 'Z' will produce an invalid timestamp like 2026-03-27T12:34:56+00:00Z. Prefer emitting RFC3339 UTC either via ...isoformat().replace('+00:00', 'Z') or formatting with strftime(...'%Y-%m-%dT%H:%M:%SZ').

Copilot uses AI. Check for mistakes.

metadata.status = "ready"
metadata.ready_at = datetime.datetime.utcnow().isoformat() + "Z"
metadata.ready_at = datetime.datetime.now(tz=datetime.UTC).isoformat() + "Z"
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same timestamp formatting issue as started_at: isoformat() on an aware UTC datetime includes +00:00, so ... + 'Z' yields an invalid +00:00Z suffix. Please normalize to a single UTC designator (Z or +00:00) consistently.

Copilot uses AI. Check for mistakes.
except Exception as exc:
metadata.status = "failed"
metadata.failed_at = datetime.datetime.utcnow().isoformat() + "Z"
metadata.failed_at = datetime.datetime.now(tz=datetime.UTC).isoformat() + "Z"
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same timestamp formatting issue as above: datetime.datetime.now(tz=datetime.UTC).isoformat() + 'Z' will render ...+00:00Z. Emit either RFC3339 Z or keep the +00:00 offset, but not both.

Copilot uses AI. Check for mistakes.
Comment on lines 72 to +73
expiration_time = self.created_at + validity_period
return self.revoked_at is None and datetime.now() < expiration_time
return self.revoked_at is None and datetime.now(tz=UTC) < expiration_time
Copy link

Copilot AI Mar 27, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This compares a timezone-aware datetime.now(tz=UTC) with self.created_at (and thus expiration_time) that come from SQLAlchemy DateTime columns defined without timezone=True (and with server_default=func.now() in the migration). Those values will be offset-naive, and Python will raise TypeError: can't compare offset-naive and offset-aware datetimes. Either migrate these columns to timezone-aware datetimes (preferred) or ensure both sides of the comparison are consistently naive/UTC.

Copilot uses AI. Check for mistakes.
@agentydragon agentydragon force-pushed the claude/ruff-enable-dtz branch 17 times, most recently from d63b621 to d743266 Compare March 27, 2026 23:50
Adds `DTZ` (flake8-datetimez) to ruff.toml. Flags naive datetime
construction without timezone. Fixes: datetime.now() → datetime.now(tz=UTC),
fromtimestamp(t) → fromtimestamp(t, tz=UTC), strptime → .replace(tzinfo=UTC),
date.today() → datetime.now(tz=UTC).date(). Uses `from datetime import UTC`
(Python 3.11+).

https://claude.ai/code/session_013WcexLQ8JPJG1j79uvMfCF
@agentydragon agentydragon force-pushed the claude/ruff-enable-dtz branch from d743266 to 38a7129 Compare March 28, 2026 00:04
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants