Source code for org.converters

import morepath

from collections import defaultdict


from typing import TYPE_CHECKING
if TYPE_CHECKING:
    from collections.abc import Mapping, Sequence
    from typing import Protocol

[docs] class HasKeywords(Protocol): @property
[docs] def keywords(self) -> Mapping[str, Sequence[str]]: ...
[docs] def keywords_encode( keywords: 'HasKeywords | Mapping[str, Sequence[str]]' ) -> str: """ Takes a dictionary of keywords and encodes them into a somewhat readable url query format. For example:: { 'color': ['blue', 'red'], 'weight': ['normal'] } Results in:: '+color:blue+color:red+weight:normal' Instead of a dictionary we can also use any kind of object which has a 'keywords' property returning the expected dictionary. Note that that object won't be recreated during decode however. """ if not keywords: return '' if hasattr(keywords, 'keywords'): keywords = keywords.keywords def escape(s: str) -> str: return s.replace('+', '++') return '+'.join( '{}:{}'.format(escape(key), escape(value)) for key in keywords for value in keywords[key] )
[docs] def keywords_decode(text: str) -> dict[str, list[str]] | None: """ Decodes keywords creaged by :func:`keywords_encode`. """ if not text: return None result = defaultdict(list) for item in text.replace('++', '\0').split('+'): key, value = item.split(':', 1) result[key.replace('\0', '+')].append(value.replace('\0', '+')) return result
[docs] keywords_converter = morepath.Converter( decode=keywords_decode, encode=keywords_encode # type:ignore[arg-type] )