Files
baijiahao_data_crawl/venv/Lib/site-packages/mitmproxy/contentviews/_registry.py
“shengyudong” 322ac74336 2025-12-25 upload
2025-12-25 11:16:59 +08:00

74 lines
2.4 KiB
Python

from __future__ import annotations
import logging
import typing
from collections.abc import Mapping
from ..utils import signals
from ._api import Contentview
from ._api import Metadata
logger = logging.getLogger(__name__)
def _on_change(view: Contentview) -> None: ...
class ContentviewRegistry(Mapping[str, Contentview]):
def __init__(self):
self._by_name: dict[str, Contentview] = {}
self.on_change = signals.SyncSignal(_on_change)
def register(self, instance: Contentview | type[Contentview]) -> None:
if isinstance(instance, type):
instance = instance()
name = instance.name.lower()
if name in self._by_name:
logger.info(f"Replacing existing {name} contentview.")
self._by_name[name] = instance
self.on_change.send(instance)
def available_views(self) -> list[str]:
return ["auto", *sorted(self._by_name.keys())]
def get_view(
self, data: bytes, metadata: Metadata, view_name: str = "auto"
) -> Contentview:
"""
Get the best contentview for the given data and metadata.
If `view_name` is "auto" or the provided view not found,
the best matching contentview based on `render_priority` will be returned.
"""
if view_name != "auto":
try:
return self[view_name.lower()]
except KeyError:
logger.warning(
f"Unknown contentview {view_name!r}, selecting best match instead."
)
max_prio: tuple[float, Contentview] | None = None
for name, view in self._by_name.items():
try:
priority = view.render_priority(data, metadata)
assert isinstance(priority, (int, float)), (
f"render_priority for {view.name} did not return a number."
)
except Exception:
logger.exception(f"Error in {view.name}.render_priority")
else:
if max_prio is None or max_prio[0] < priority:
max_prio = (priority, view)
assert max_prio, "At least one view needs to have a working `render_priority`."
return max_prio[1]
def __iter__(self) -> typing.Iterator[str]:
return iter(self._by_name)
def __getitem__(self, item: str) -> Contentview:
return self._by_name[item.lower()]
def __len__(self):
return len(self._by_name)