drf-toon 0.1.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.
@@ -0,0 +1,106 @@
1
+ Metadata-Version: 2.3
2
+ Name: drf-toon
3
+ Version: 0.1.0
4
+ Summary: Native TOON parser and renderer for Django Rest Framework.
5
+ Author: Dash Winterson
6
+ Author-email: Dash Winterson <dashdanw@gmail.com>
7
+ Requires-Dist: django>=5.2,<6.0
8
+ Requires-Dist: djangorestframework>=3.15
9
+ Requires-Dist: djangorestframework-stubs>=3.15
10
+ Requires-Dist: toons>=0.7.0
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+
14
+ # drf-toon
15
+
16
+ Native [TOON](https://toonformat.dev/) (Token Oriented Object Notation) parser and renderer for [Django REST Framework](https://www.django-rest-framework.org/).
17
+
18
+ TOON is a token-efficient serialization format designed for LLM contexts. It can result in **30–60% fewer tokens** than JSON.
19
+
20
+ `drf-toon` is built on [`toons`](https://github.com/alesanfra/toons), a high-performance Rust implementation meant to mimic the native python `json` package.
21
+
22
+ ## Compatibility
23
+
24
+ `drf-toon` supports **Django 5.2 LTS** on **Python 3.10–3.13**, matching
25
+ Django's own [support matrix](https://docs.djangoproject.com/en/stable/faq/install/#what-python-version-can-i-use-with-django).
26
+ Every supported Python version is exercised in CI.
27
+
28
+ | Django | Python |
29
+ | ------- | ---------------------- |
30
+ | 5.2 LTS | 3.10, 3.11, 3.12, 3.13 |
31
+
32
+ Support for additional Django releases can be added later by extending the CI
33
+ matrix.
34
+
35
+ ## Installation
36
+
37
+ ```bash
38
+ pip install drf-toon
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ Add the parser and renderer to your DRF settings:
44
+
45
+ ```python
46
+ # settings.py
47
+ REST_FRAMEWORK = {
48
+ "DEFAULT_PARSER_CLASSES": [
49
+ "drf_toon.parsers.TOONParser",
50
+ "rest_framework.parsers.JSONParser",
51
+ ],
52
+ "DEFAULT_RENDERER_CLASSES": [
53
+ "drf_toon.renderers.TOONRenderer",
54
+ "rest_framework.renderers.JSONRenderer",
55
+ ],
56
+ }
57
+ ```
58
+
59
+ Or enable them per-view:
60
+
61
+ ```python
62
+ from rest_framework.views import APIView
63
+ from rest_framework.response import Response
64
+
65
+ from drf_toon.parsers import TOONParser
66
+ from drf_toon.renderers import TOONRenderer
67
+
68
+
69
+ class UserView(APIView):
70
+ parser_classes = [TOONParser]
71
+ renderer_classes = [TOONRenderer]
72
+
73
+ def get(self, request):
74
+ return Response({"name": "Alice", "age": 30})
75
+ ```
76
+
77
+ Both classes use the `application/toon` media type. Send requests with
78
+ `Content-Type: application/toon` to parse, and `Accept: application/toon`
79
+ (or `?format=toon`) to render.
80
+
81
+ ## Development
82
+
83
+ Install the dev dependencies and run the checks with uv:
84
+
85
+ ```bash
86
+ uv sync --dev
87
+
88
+ uv run ruff check . # lint
89
+ uv run ruff format . # format
90
+ uv run ruff format --check . # format check (CI)
91
+ uv run mypy # type check
92
+ uv run pytest # tests + coverage
93
+ ```
94
+
95
+ Optionally install the git hooks:
96
+
97
+ ```bash
98
+ uv run pre-commit install --install-hooks
99
+ ```
100
+
101
+ This wires up both a **pre-commit** hook (autofix + format) and a **pre-push**
102
+ hook that blocks the push if the code is not properly linted/formatted.
103
+
104
+ ## License
105
+
106
+ MIT
@@ -0,0 +1,93 @@
1
+ # drf-toon
2
+
3
+ Native [TOON](https://toonformat.dev/) (Token Oriented Object Notation) parser and renderer for [Django REST Framework](https://www.django-rest-framework.org/).
4
+
5
+ TOON is a token-efficient serialization format designed for LLM contexts. It can result in **30–60% fewer tokens** than JSON.
6
+
7
+ `drf-toon` is built on [`toons`](https://github.com/alesanfra/toons), a high-performance Rust implementation meant to mimic the native python `json` package.
8
+
9
+ ## Compatibility
10
+
11
+ `drf-toon` supports **Django 5.2 LTS** on **Python 3.10–3.13**, matching
12
+ Django's own [support matrix](https://docs.djangoproject.com/en/stable/faq/install/#what-python-version-can-i-use-with-django).
13
+ Every supported Python version is exercised in CI.
14
+
15
+ | Django | Python |
16
+ | ------- | ---------------------- |
17
+ | 5.2 LTS | 3.10, 3.11, 3.12, 3.13 |
18
+
19
+ Support for additional Django releases can be added later by extending the CI
20
+ matrix.
21
+
22
+ ## Installation
23
+
24
+ ```bash
25
+ pip install drf-toon
26
+ ```
27
+
28
+ ## Usage
29
+
30
+ Add the parser and renderer to your DRF settings:
31
+
32
+ ```python
33
+ # settings.py
34
+ REST_FRAMEWORK = {
35
+ "DEFAULT_PARSER_CLASSES": [
36
+ "drf_toon.parsers.TOONParser",
37
+ "rest_framework.parsers.JSONParser",
38
+ ],
39
+ "DEFAULT_RENDERER_CLASSES": [
40
+ "drf_toon.renderers.TOONRenderer",
41
+ "rest_framework.renderers.JSONRenderer",
42
+ ],
43
+ }
44
+ ```
45
+
46
+ Or enable them per-view:
47
+
48
+ ```python
49
+ from rest_framework.views import APIView
50
+ from rest_framework.response import Response
51
+
52
+ from drf_toon.parsers import TOONParser
53
+ from drf_toon.renderers import TOONRenderer
54
+
55
+
56
+ class UserView(APIView):
57
+ parser_classes = [TOONParser]
58
+ renderer_classes = [TOONRenderer]
59
+
60
+ def get(self, request):
61
+ return Response({"name": "Alice", "age": 30})
62
+ ```
63
+
64
+ Both classes use the `application/toon` media type. Send requests with
65
+ `Content-Type: application/toon` to parse, and `Accept: application/toon`
66
+ (or `?format=toon`) to render.
67
+
68
+ ## Development
69
+
70
+ Install the dev dependencies and run the checks with uv:
71
+
72
+ ```bash
73
+ uv sync --dev
74
+
75
+ uv run ruff check . # lint
76
+ uv run ruff format . # format
77
+ uv run ruff format --check . # format check (CI)
78
+ uv run mypy # type check
79
+ uv run pytest # tests + coverage
80
+ ```
81
+
82
+ Optionally install the git hooks:
83
+
84
+ ```bash
85
+ uv run pre-commit install --install-hooks
86
+ ```
87
+
88
+ This wires up both a **pre-commit** hook (autofix + format) and a **pre-push**
89
+ hook that blocks the push if the code is not properly linted/formatted.
90
+
91
+ ## License
92
+
93
+ MIT
@@ -0,0 +1,78 @@
1
+ [project]
2
+ name = "drf-toon"
3
+ version = "0.1.0"
4
+ description = "Native TOON parser and renderer for Django Rest Framework."
5
+ readme = "README.md"
6
+ requires-python = ">=3.10"
7
+ dependencies = [
8
+ "django>=5.2,<6.0",
9
+ "djangorestframework>=3.15",
10
+ "djangorestframework-stubs>=3.15",
11
+ "toons>=0.7.0",
12
+ ]
13
+
14
+ [[project.authors]]
15
+ name = "Dash Winterson"
16
+ email = "dashdanw@gmail.com"
17
+
18
+ [build-system]
19
+ requires = ["uv_build>=0.11.24,<0.12.0"]
20
+ build-backend = "uv_build"
21
+
22
+ [dependency-groups]
23
+ dev = [
24
+ "drf-spectacular>=0.27.0",
25
+ "mypy>=1.10.0",
26
+ "pre-commit>=3.7.0",
27
+ "pytest>=8.0.0",
28
+ "pytest-cov>=5.0.0",
29
+ "pytest-django>=4.8.0",
30
+ "ruff>=0.6.0",
31
+ ]
32
+
33
+ [tool.pytest.ini_options]
34
+ python_files = ["test_*.py"]
35
+ testpaths = ["tests"]
36
+ addopts = "--cov=drf_toon --cov-report=term-missing"
37
+
38
+ [tool.ruff]
39
+ line-length = 100
40
+ target-version = "py310"
41
+ src = [
42
+ "src",
43
+ "tests",
44
+ ]
45
+
46
+ [tool.ruff.lint]
47
+ select = [
48
+ "E",
49
+ "W",
50
+ "F",
51
+ "I",
52
+ "B",
53
+ "UP",
54
+ "C4",
55
+ ]
56
+ ignore = []
57
+
58
+ [tool.ruff.lint.isort]
59
+ known-first-party = ["drf_toon"]
60
+
61
+ [tool.ruff.format]
62
+ quote-style = "double"
63
+
64
+ [tool.mypy]
65
+ python_version = "3.10"
66
+ files = [
67
+ "src",
68
+ "tests",
69
+ ]
70
+ ignore_missing_imports = true
71
+ warn_unused_ignores = true
72
+ warn_redundant_casts = true
73
+
74
+ [tool.coverage.run]
75
+ source = ["drf_toon"]
76
+
77
+ [tool.coverage.report]
78
+ show_missing = true
@@ -0,0 +1,73 @@
1
+ [project]
2
+ name = "drf-toon"
3
+ version = "0.1.0"
4
+ description = "Native TOON parser and renderer for Django Rest Framework."
5
+ readme = "README.md"
6
+ authors = [
7
+ { name = "Dash Winterson", email = "dashdanw@gmail.com" }
8
+ ]
9
+ requires-python = ">=3.10"
10
+ dependencies = [
11
+ "django>=5.2,<6.0",
12
+ "djangorestframework>=3.15",
13
+ "djangorestframework-stubs>=3.15",
14
+ "toons>=0.7.0",
15
+ ]
16
+
17
+ [build-system]
18
+ requires = ["uv_build>=0.11.24,<0.12.0"]
19
+ build-backend = "uv_build"
20
+
21
+ [dependency-groups]
22
+ dev = [
23
+ "drf-spectacular>=0.27.0",
24
+ "mypy>=1.10.0",
25
+ "pre-commit>=3.7.0",
26
+ "pytest>=8.0.0",
27
+ "pytest-cov>=5.0.0",
28
+ "pytest-django>=4.8.0",
29
+ "ruff>=0.6.0",
30
+ ]
31
+
32
+
33
+ [tool.pytest.ini_options]
34
+ python_files = ["test_*.py"]
35
+ testpaths = ["tests"]
36
+ addopts = "--cov=drf_toon --cov-report=term-missing"
37
+
38
+ [tool.ruff]
39
+ line-length = 100
40
+ target-version = "py310"
41
+ src = ["src", "tests"]
42
+
43
+ [tool.ruff.lint]
44
+ select = [
45
+ "E", # pycodestyle errors
46
+ "W", # pycodestyle warnings
47
+ "F", # pyflakes
48
+ "I", # isort
49
+ "B", # flake8-bugbear
50
+ "UP", # pyupgrade
51
+ "C4", # flake8-comprehensions
52
+ ]
53
+ ignore = []
54
+
55
+ [tool.ruff.lint.isort]
56
+ known-first-party = ["drf_toon"]
57
+
58
+ [tool.ruff.format]
59
+ quote-style = "double"
60
+
61
+ [tool.mypy]
62
+ python_version = "3.10"
63
+ files = ["src", "tests"]
64
+ ignore_missing_imports = true
65
+ warn_unused_ignores = true
66
+ warn_redundant_casts = true
67
+
68
+ [tool.coverage.run]
69
+ source = ["drf_toon"]
70
+
71
+ [tool.coverage.report]
72
+ show_missing = true
73
+
File without changes
@@ -0,0 +1,6 @@
1
+ from django.apps import AppConfig
2
+
3
+
4
+ class TOONConfig(AppConfig):
5
+ default_auto_field = "django.db.models.BigAutoField"
6
+ name = "drf_toon"
@@ -0,0 +1,20 @@
1
+ import codecs
2
+
3
+ import toons
4
+ from django.conf import settings
5
+ from rest_framework.exceptions import ParseError
6
+ from rest_framework.parsers import BaseParser
7
+
8
+
9
+ class TOONParser(BaseParser):
10
+ media_type = "application/toon"
11
+
12
+ def parse(self, stream, media_type=None, parser_context=None):
13
+ parser_context = parser_context or {}
14
+ encoding = parser_context.get("encoding", settings.DEFAULT_CHARSET)
15
+ decoded_stream = codecs.getreader(encoding)(stream)
16
+
17
+ try:
18
+ return toons.load(decoded_stream)
19
+ except toons.ToonDecodeError as e:
20
+ raise ParseError(f"TOON parse error - {str(e)}") from e
@@ -0,0 +1,10 @@
1
+ import toons
2
+ from rest_framework.renderers import BaseRenderer
3
+
4
+
5
+ class TOONRenderer(BaseRenderer):
6
+ media_type = "application/toon"
7
+ format = "toon"
8
+
9
+ def render(self, data, accepted_media_type=None, renderer_context=None):
10
+ return toons.dumps(data).encode(self.charset)