Build and Push Docker Container / build-and-push (push) Successful in 2m25s
- Require Python 3.15 for the server and Python 3.14 for the CLI. - Match the server requirement to quart_common's Python 3.15 features. - Replace future annotations with native deferred evaluation. - Defer CLI command dependencies and QR imports on Python 3.15. - Enable argparse suggestions for mistyped CLI commands. - Remove the obsolete tomllib import fallback. - Update my_helpers and quart_common submodule references. - Lock test dependencies and exclude them from Docker installations. - Add regression coverage for lazy imports and deferred annotations. - Document runtime requirements and standalone CLI validation. - Validate 276 tests on Python 3.15 and 18 CLI tests on Python 3.14. BREAKING CHANGE: The server now requires Python 3.15+ and the standalone CLI requires Python 3.14+.
41 lines
1.4 KiB
Python
41 lines
1.4 KiB
Python
from collections.abc import Awaitable, Callable
|
|
|
|
from .render import build_segments
|
|
|
|
# Text types that get the rendered viewer; anything else is served untouched.
|
|
VIEWABLE_CONTENT_TYPES = {'text/plain', 'text/markdown'}
|
|
|
|
_TRUTHY = {'1', 'true', 'yes'}
|
|
|
|
def _base_content_type(content_type: str) -> str:
|
|
return (content_type or '').split(';')[0].strip().lower()
|
|
|
|
def wants_text_view(content_type: str, accept_header: str, raw_param: str | None, force_download: bool) -> bool:
|
|
"""Only real browser navigations get HTML; curl, wget and the CLI keep the raw bytes."""
|
|
if force_download or (raw_param or '').lower() in _TRUTHY:
|
|
return False
|
|
if _base_content_type(content_type) not in VIEWABLE_CONTENT_TYPES:
|
|
return False
|
|
# Accept: */* (curl, wget, CLI clients) must not trigger the viewer.
|
|
return 'text/html' in (accept_header or '').lower()
|
|
|
|
def decode_text(raw: bytes) -> str:
|
|
"""Decode the full document; invalid bytes become replacement characters."""
|
|
return raw.decode('utf-8', errors='replace')
|
|
|
|
async def build_view_context(
|
|
raw: bytes,
|
|
file_name: str,
|
|
host: str,
|
|
root_path: str,
|
|
raw_url: str,
|
|
lookup: Callable[[str], Awaitable[dict | None]] | None,
|
|
) -> dict:
|
|
text = decode_text(raw)
|
|
segments = await build_segments(text, host=host, root_path=root_path, lookup=lookup)
|
|
return {
|
|
'file_name': file_name,
|
|
'segments': segments,
|
|
'raw_url': raw_url,
|
|
}
|