"""Teach feedparser the Podcasting 2.0 tags we read. feedparser 6 doesn't know the podcast namespace. Unknown tags still come through, but only under whatever prefix the feed happened to declare, and an unknown tag with attributes is stored as a single dict, so a second overwrites the first. Registering the namespace fixes the prefix ("podcast_…" for every feed); the handler below keeps every transcript in a list, entry["podcast_transcripts"]. podcast:chapters is left to feedparser's default handling, which gives entry["podcast_chapters"] = {"url": …, "type": …} (one per item, as the spec says). """ from feedparser.mixin import _FeedParserMixin as FeedParserMixin from feedparser.util import FeedParserDict PODCAST_NAMESPACES = ( 'https://podcastindex.org/namespace/1.0', # The URL the namespace was announced under; some early feeds still use it. 'https://github.com/podcastindex-org/podcast-namespace/blob/main/docs/1.0.md', ) def _start_podcast_transcript(self, attrs_d): context = self._get_context() context.setdefault('podcast_transcripts', []).append(FeedParserDict(attrs_d)) def _end_podcast_transcript(self): pass def install(): """Idempotent; called when podcasts.views is imported.""" for uri in PODCAST_NAMESPACES: FeedParserMixin.namespaces.setdefault(uri, 'podcast') # Filled lazily from `namespaces` by the first parser; once it has # been, later additions have to go in here directly. if FeedParserMixin._matchnamespaces: FeedParserMixin._matchnamespaces.setdefault(uri.lower(), 'podcast') FeedParserMixin._start_podcast_transcript = _start_podcast_transcript FeedParserMixin._end_podcast_transcript = _end_podcast_transcript