steam-backlog-enforcer/steam_backlog_enforcer/_total_block_hosts.py
Krzysztof kuhy Rudnicki 356530a01c
Some checks are pending
dependency freshness / dependencies on newest stable (push) Waiting to run
md-naming / markdown naming convention (push) Waiting to run
pre-commit / pre-commit (push) Waiting to run
Tests / test (push) Waiting to run
Grade against 3.14 too, not just run on it
`requires-python` and the CI pin already said 3.14, but ruff, mypy and pylint
were still grading against 3.10 -- three tools judging an interpreter nothing
runs any more, and ruff withholding the pyupgrade fixes that only become safe
at the newer target. `pin_ci_python.py` rewrites exactly these three knobs.

What the stale target was hiding: `datetime.timezone.utc` where `datetime.UTC`
is now correct (UP017), `socket.timeout` where `TimeoutError` is (UP041),
deprecated `typing` imports (UP035), PEP 695 `type` aliases (UP040), and ruff's
stable formatter applying PEP 758 -- `except (A, B):` becomes `except A, B:`.
That last one makes the source 3.14-only at the syntax level, which is what
`requires-python = ">=3.14"` already promised; kuhy chose it deliberately over
holding ruff a release back (2026-08-29).

ruff, ruff-format, mypy --strict and pylint all clean at the new target. The
two modified web/ TypeScript files are another session's in-flight work and
are deliberately left unstaged.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01SfnJmxxsZ534AKk16rC2Gr
2026-08-29 11:44:25 +02:00

87 lines
2.6 KiB
Python

"""/etc/hosts null-routing for the total gaming block.
Deliberately distinct from :mod:`store_blocker`'s own BLOCKED_DOMAINS /
STEAM_ENFORCER hosts section, so ending a total block never disturbs the
user's normal ``config.block_store`` entries. The iptables half of the same
block lives in :mod:`steam_backlog_enforcer._total_block_iptables`.
"""
from __future__ import annotations
import logging
import subprocess
from steam_backlog_enforcer._total_block_domains import (
_ALL_TOTAL_BLOCK_DOMAINS,
NULL_ROUTE_IP,
)
from steam_backlog_enforcer.config import HOSTS_FILE
from steam_backlog_enforcer.store_blocker import (
_disable_hosts_protection,
_enable_hosts_protection,
_sudo_write_hosts,
)
logger = logging.getLogger(__name__)
_HOSTS_BLOCK_BEGIN = "# BEGIN steam-backlog-enforcer total-block\n"
_HOSTS_BLOCK_END = "# END steam-backlog-enforcer total-block\n"
def apply_total_block_hosts() -> bool:
"""Append the total-block domain block to /etc/hosts, if not present."""
try:
content = HOSTS_FILE.read_text(encoding="utf-8")
except OSError:
logger.exception("Failed to read /etc/hosts")
return False
if _HOSTS_BLOCK_BEGIN in content:
return True
block_lines = [_HOSTS_BLOCK_BEGIN]
block_lines += [
f"{NULL_ROUTE_IP} {domain}\n" for domain in _ALL_TOTAL_BLOCK_DOMAINS
]
block_lines.append(_HOSTS_BLOCK_END)
new_content = content if content.endswith("\n") else content + "\n"
new_content += "".join(block_lines)
try:
_disable_hosts_protection()
_sudo_write_hosts(new_content)
except OSError, subprocess.SubprocessError:
logger.exception("Failed to write total-block hosts entries")
return False
finally:
_enable_hosts_protection()
return True
def remove_total_block_hosts() -> bool:
"""Remove the total-block domain block from /etc/hosts, if present."""
try:
content = HOSTS_FILE.read_text(encoding="utf-8")
except OSError:
logger.exception("Failed to read /etc/hosts")
return False
if _HOSTS_BLOCK_BEGIN not in content:
return True
start = content.index(_HOSTS_BLOCK_BEGIN)
end_marker_at = content.index(_HOSTS_BLOCK_END, start)
end = end_marker_at + len(_HOSTS_BLOCK_END)
new_content = content[:start] + content[end:]
try:
_disable_hosts_protection()
_sudo_write_hosts(new_content)
except OSError, subprocess.SubprocessError:
logger.exception("Failed to remove total-block hosts entries")
return False
finally:
_enable_hosts_protection()
return True