Source code for betty.extension.wikipedia

"""Integrate Betty with `Wikipedia <https://wikipedia.org>`_."""

from __future__ import annotations

import logging
from pathlib import Path
from typing import Callable, Iterable, Any

from jinja2 import pass_context
from jinja2.runtime import Context

from betty import wikipedia
from betty.app.extension import UserFacingExtension
from betty.asyncio import gather
from betty.jinja2 import Jinja2Provider, context_localizer
from betty.load import PostLoader
from betty.locale import negotiate_locale, Str
from betty.model.ancestry import Link
from betty.wikipedia import Summary, _parse_url, NotAPageError, RetrievalError


[docs] class Wikipedia(UserFacingExtension, Jinja2Provider, PostLoader):
[docs] @classmethod def name(cls) -> str: return "betty.extension.Wikipedia"
def __init__(self, *args: Any, **kwargs: Any): super().__init__(*args, **kwargs) self.__retriever: wikipedia._Retriever | None = None self.__populator: wikipedia._Populator | None = None
[docs] async def post_load(self) -> None: populator = wikipedia._Populator(self.app, self._retriever) await populator.populate()
@property def _retriever(self) -> wikipedia._Retriever: if self.__retriever is None: self.__retriever = wikipedia._Retriever( self.app.http_client, self._app.cache, self._app.binary_file_cache.with_scope(self.name()), ) return self.__retriever @_retriever.deleter def _retriever(self) -> None: self.__retriever = None @property def filters(self) -> dict[str, Callable[..., Any]]: return { "wikipedia": self._filter_wikipedia_links, } @pass_context async def _filter_wikipedia_links( self, context: Context, links: Iterable[Link] ) -> Iterable[Summary]: return filter( None, await gather( *( self._filter_wikipedia_link( context_localizer(context).locale, link, ) for link in links ) ), ) async def _filter_wikipedia_link(self, locale: str, link: Link) -> Summary | None: try: page_language, page_name = _parse_url(link.url) except NotAPageError: return None if negotiate_locale(locale, [page_language]) is None: return None try: return await self._retriever.get_summary(page_language, page_name) except RetrievalError as error: logger = logging.getLogger(__name__) logger.warning(str(error)) return None
[docs] @classmethod def assets_directory_path(cls) -> Path | None: return Path(__file__).parent / "assets"
[docs] @classmethod def label(cls) -> Str: return Str._("Wikipedia")
[docs] @classmethod def description(cls) -> Str: return Str._( """ Display <a href="https://www.wikipedia.org/">Wikipedia</a> summaries for resources with external links. In your custom <a href="https://jinja2docs.readthedocs.io/en/stable/">Jinja2</a> templates, use the following: <pre><code> {{% with resource=resource_with_links %}} {{% include 'wikipedia.html.j2' %}} {{% endwith %}} </code></pre>""" )