dirigent-common 0.23.4__tar.gz → 0.24.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (23) hide show
  1. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/PKG-INFO +1 -1
  2. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/pyproject.toml +1 -1
  3. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/pyproject.toml.orig +1 -1
  4. dirigent_common-0.24.0/src/dirigent_common/requests.py +33 -0
  5. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/LICENSE +0 -0
  6. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/README.md +0 -0
  7. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/__init__.py +0 -0
  8. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/clients.py +0 -0
  9. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/docstrings.py +0 -0
  10. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/durations.py +0 -0
  11. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/formats.py +0 -0
  12. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/formatters.py +0 -0
  13. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/messages.py +0 -0
  14. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/names.py +0 -0
  15. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/programs.py +0 -0
  16. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/py.typed +0 -0
  17. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/schemas.py +0 -0
  18. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/sizes.py +0 -0
  19. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/templating.py +0 -0
  20. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/types.py +0 -0
  21. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/uris.py +0 -0
  22. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/values.py +0 -0
  23. {dirigent_common-0.23.4 → dirigent_common-0.24.0}/src/dirigent_common/versions.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: dirigent-common
3
- Version: 0.23.4
3
+ Version: 0.24.0
4
4
  Summary: Value types and shared schemas every dirigent package may depend on.
5
5
  License-Expression: LicenseRef-Proprietary
6
6
  License-File: LICENSE
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-common"
3
- version = "0.23.4"
3
+ version = "0.24.0"
4
4
  description = "Value types and shared schemas every dirigent package may depend on."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "dirigent-common"
3
- version = "0.23.4"
3
+ version = "0.24.0"
4
4
  description = "Value types and shared schemas every dirigent package may depend on."
5
5
  readme = "README.md"
6
6
  requires-python = ">=3.13"
@@ -0,0 +1,33 @@
1
+ """Reading the parts of an HTTP request that every surface reads the same way."""
2
+
3
+ from collections.abc import Iterable
4
+ from urllib.parse import parse_qsl
5
+
6
+ from pydantic import JsonValue
7
+
8
+
9
+ def gather_values(pairs: Iterable[tuple[str, str]]) -> dict[str, JsonValue]:
10
+ """Fold name-value pairs into a map: one value a string, a repeated name a list in order."""
11
+ gathered: dict[str, list[str]] = {}
12
+ for name, value in pairs:
13
+ gathered.setdefault(name, []).append(value)
14
+ return {name: values[0] if len(values) == 1 else list(values) for name, values in gathered.items()}
15
+
16
+
17
+ def form_values(text: str) -> dict[str, JsonValue]:
18
+ """Read an ``application/x-www-form-urlencoded`` body the way a query string is read."""
19
+ return gather_values(parse_qsl(text, keep_blank_values=True))
20
+
21
+
22
+ def media_type(content_type: str | None) -> tuple[str | None, dict[str, str]]:
23
+ """Split a content-type header into its lowercased media type and its parameters."""
24
+ if not content_type:
25
+ return None, {}
26
+ head, *rest = content_type.split(";")
27
+ params: dict[str, str] = {}
28
+ for part in rest:
29
+ name, _, value = part.partition("=")
30
+ if name.strip():
31
+ params[name.strip().lower()] = value.strip().strip('"')
32
+ media = head.strip().lower()
33
+ return (media or None), params