Source code for httk.core.datastream.textstream_request

import io
import urllib.parse
import urllib.request
from typing import Any, cast

from .compression import open_compressed, validate_compression
from .textstream_backend import TextstreamBackend
from .textstream_common import TextstreamCommon


[docs] class TextstreamRequest(TextstreamCommon, TextstreamBackend): """ Backend for streaming text fetched via a urllib.request.Request. """ _request: urllib.request.Request _timeout: float | None _encoding: str | None _compression: str _f: io.TextIOBase | None _underlying: io.IOBase | None _closed: bool # mypy does not allow to type annotate __new__ as `Self | None` for some reason def __new__(cls, request: urllib.request.Request, **hints: Any) -> Any: if not isinstance(request, urllib.request.Request): return None if hints and hints.get("kind", "request") != "request": return None return super().__new__(cls) def __init__(self, request: urllib.request.Request, **hints: Any) -> None: self._request = request self._timeout = hints.get("timeout") self._encoding = hints.get("encoding") self._compression = hints.get("compression", "auto") validate_compression(self._compression) self._f = None self._underlying = None self._closed = False def _ensure_f(self) -> io.TextIOBase: if self._closed: raise ValueError("I/O operation on closed stream") if self._f is None: if self._timeout is None: resp = urllib.request.urlopen(self._request) else: resp = urllib.request.urlopen(self._request, timeout=self._timeout) encoding = self._encoding or resp.headers.get_content_charset() or "utf-8" raw = cast(io.IOBase, resp) name = urllib.parse.urlsplit(self._request.full_url).path decompressed = open_compressed(raw, compression=self._compression, name=name) self._underlying = raw if decompressed is not raw else None self._f = io.TextIOWrapper(cast(io.BufferedReader, decompressed), encoding=encoding) return self._f @property
[docs] def name(self) -> str | None: return None
@property
[docs] def url(self) -> str: return self._request.full_url
@property
[docs] def request(self) -> urllib.request.Request: return self._request
@property
[docs] def closed(self) -> bool: return self._closed