| 17 | |
| 18 | |
| 19 | class Querystring: |
| 20 | array_format: ArrayFormat |
| 21 | nested_format: NestedFormat |
| 22 | |
| 23 | def __init__( |
| 24 | self, |
| 25 | *, |
| 26 | array_format: ArrayFormat = "repeat", |
| 27 | nested_format: NestedFormat = "brackets", |
| 28 | ) -> None: |
| 29 | self.array_format = array_format |
| 30 | self.nested_format = nested_format |
| 31 | |
| 32 | def parse(self, query: str) -> Mapping[str, object]: |
| 33 | # Note: custom format syntax is not supported yet |
| 34 | return parse_qs(query) |
| 35 | |
| 36 | def stringify( |
| 37 | self, |
| 38 | params: Params, |
| 39 | *, |
| 40 | array_format: ArrayFormat | NotGiven = not_given, |
| 41 | nested_format: NestedFormat | NotGiven = not_given, |
| 42 | ) -> str: |
| 43 | return urlencode( |
| 44 | self.stringify_items( |
| 45 | params, |
| 46 | array_format=array_format, |
| 47 | nested_format=nested_format, |
| 48 | ) |
| 49 | ) |
| 50 | |
| 51 | def stringify_items( |
| 52 | self, |
| 53 | params: Params, |
| 54 | *, |
| 55 | array_format: ArrayFormat | NotGiven = not_given, |
| 56 | nested_format: NestedFormat | NotGiven = not_given, |
| 57 | ) -> list[tuple[str, str]]: |
| 58 | opts = Options( |
| 59 | qs=self, |
| 60 | array_format=array_format, |
| 61 | nested_format=nested_format, |
| 62 | ) |
| 63 | return flatten([self._stringify_item(key, value, opts) for key, value in params.items()]) |
| 64 | |
| 65 | def _stringify_item( |
| 66 | self, |
| 67 | key: str, |
| 68 | value: Data, |
| 69 | opts: Options, |
| 70 | ) -> list[tuple[str, str]]: |
| 71 | if isinstance(value, Mapping): |
| 72 | items: list[tuple[str, str]] = [] |
| 73 | nested_format = opts.nested_format |
| 74 | for subkey, subvalue in value.items(): |
| 75 | items.extend( |
| 76 | self._stringify_item( |
no outgoing calls