strawberry-django-aggregates 0.2.1__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 (40) hide show
  1. strawberry_django_aggregates-0.2.1/LICENSE +29 -0
  2. strawberry_django_aggregates-0.2.1/PKG-INFO +128 -0
  3. strawberry_django_aggregates-0.2.1/README.md +98 -0
  4. strawberry_django_aggregates-0.2.1/pyproject.toml +74 -0
  5. strawberry_django_aggregates-0.2.1/setup.cfg +4 -0
  6. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/__init__.py +146 -0
  7. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/builder.py +1865 -0
  8. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/compiler.py +2295 -0
  9. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/errors.py +73 -0
  10. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/fill.py +325 -0
  11. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/granularity.py +96 -0
  12. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/operators.py +174 -0
  13. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/ordering.py +267 -0
  14. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/pagination.py +138 -0
  15. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/relations.py +536 -0
  16. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates/types.py +1263 -0
  17. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates.egg-info/PKG-INFO +128 -0
  18. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates.egg-info/SOURCES.txt +38 -0
  19. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates.egg-info/dependency_links.txt +1 -0
  20. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates.egg-info/requires.txt +5 -0
  21. strawberry_django_aggregates-0.2.1/strawberry_django_aggregates.egg-info/top_level.txt +1 -0
  22. strawberry_django_aggregates-0.2.1/tests/test_aggregate_correctness.py +575 -0
  23. strawberry_django_aggregates-0.2.1/tests/test_bool_aliases.py +282 -0
  24. strawberry_django_aggregates-0.2.1/tests/test_bucket_range.py +310 -0
  25. strawberry_django_aggregates-0.2.1/tests/test_builder_integration.py +291 -0
  26. strawberry_django_aggregates-0.2.1/tests/test_comodel_ordering.py +300 -0
  27. strawberry_django_aggregates-0.2.1/tests/test_cursor_pagination.py +611 -0
  28. strawberry_django_aggregates-0.2.1/tests/test_determinism.py +67 -0
  29. strawberry_django_aggregates-0.2.1/tests/test_federation.py +153 -0
  30. strawberry_django_aggregates-0.2.1/tests/test_fill_temporal.py +752 -0
  31. strawberry_django_aggregates-0.2.1/tests/test_groupby_timezones.py +127 -0
  32. strawberry_django_aggregates-0.2.1/tests/test_having_aliases.py +89 -0
  33. strawberry_django_aggregates-0.2.1/tests/test_jsonb_groupby.py +378 -0
  34. strawberry_django_aggregates-0.2.1/tests/test_no_relation_traversal.py +216 -0
  35. strawberry_django_aggregates-0.2.1/tests/test_order_on_aggregates.py +99 -0
  36. strawberry_django_aggregates-0.2.1/tests/test_percentile.py +184 -0
  37. strawberry_django_aggregates-0.2.1/tests/test_postgres_only_ops.py +68 -0
  38. strawberry_django_aggregates-0.2.1/tests/test_relation_aggregate.py +412 -0
  39. strawberry_django_aggregates-0.2.1/tests/test_streaming.py +518 -0
  40. strawberry_django_aggregates-0.2.1/tests/test_week_start.py +525 -0
@@ -0,0 +1,29 @@
1
+ BSD 3-Clause License
2
+
3
+ Copyright (c) 2026, the strawberry-django-aggregates maintainers.
4
+ All rights reserved.
5
+
6
+ Redistribution and use in source and binary forms, with or without
7
+ modification, are permitted provided that the following conditions are met:
8
+
9
+ 1. Redistributions of source code must retain the above copyright notice, this
10
+ list of conditions and the following disclaimer.
11
+
12
+ 2. Redistributions in binary form must reproduce the above copyright notice,
13
+ this list of conditions and the following disclaimer in the documentation
14
+ and/or other materials provided with the distribution.
15
+
16
+ 3. Neither the name of the copyright holder nor the names of its
17
+ contributors may be used to endorse or promote products derived from
18
+ this software without specific prior written permission.
19
+
20
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21
+ AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
23
+ DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
24
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
27
+ CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
28
+ OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29
+ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
@@ -0,0 +1,128 @@
1
+ Metadata-Version: 2.4
2
+ Name: strawberry-django-aggregates
3
+ Version: 0.2.1
4
+ Summary: Hasura-shape aggregations over Django querysets in Strawberry GraphQL — count, sum, avg, min, max, stddev, variance, array_agg + Odoo-grade group-by with timezone-correct date bucketing.
5
+ Author: strawberry-django-aggregates maintainers
6
+ License: BSD-3-Clause
7
+ Project-URL: Homepage, https://github.com/Apexive/strawberry-django-aggregates
8
+ Project-URL: Documentation, https://github.com/Apexive/strawberry-django-aggregates/blob/main/docs/SPEC.md
9
+ Project-URL: Issues, https://github.com/Apexive/strawberry-django-aggregates/issues
10
+ Keywords: django,strawberry,graphql,aggregate,groupby,hasura,postgraphile,odoo,analytics
11
+ Classifier: Development Status :: 4 - Beta
12
+ Classifier: Framework :: Django
13
+ Classifier: Framework :: Django :: 6.0
14
+ Classifier: Intended Audience :: Developers
15
+ Classifier: License :: OSI Approved :: BSD License
16
+ Classifier: Operating System :: OS Independent
17
+ Classifier: Programming Language :: Python :: 3
18
+ Classifier: Programming Language :: Python :: 3.14
19
+ Classifier: Topic :: Database
20
+ Classifier: Topic :: Internet :: WWW/HTTP
21
+ Classifier: Typing :: Typed
22
+ Requires-Python: >=3.14
23
+ Description-Content-Type: text/markdown
24
+ License-File: LICENSE
25
+ Requires-Dist: django>=6.0
26
+ Requires-Dist: strawberry-graphql>=0.315.0
27
+ Requires-Dist: strawberry-graphql-django>=0.82.0
28
+ Provides-Extra: postgres
29
+ Dynamic: license-file
30
+
31
+ # strawberry-django-aggregates
32
+
33
+ Hasura-shape aggregations over Django querysets in Strawberry GraphQL.
34
+
35
+ `count` · `count_distinct` · `sum` · `avg` · `min` · `max` · `stddev` · `variance` · `bool_and` · `bool_or` · `array_agg` · `string_agg` — composed with multi-level `group_by`, `having` filters, and ordering on aggregate aliases. Inspired by [Hasura](https://hasura.io/docs/latest/api-reference/graphql-api/query/#aggregateobject)'s `<table>_aggregate`, [PostGraphile](https://github.com/graphile/pg-aggregates)'s `pg-aggregates`, and [Odoo 18](https://github.com/odoo/odoo/blob/18.0/odoo/models.py)'s `_read_group`. Built for [`strawberry-django`](https://strawberry-django.readthedocs.io) over PostgreSQL and SQLite.
36
+
37
+ ```python
38
+ from decimal import Decimal
39
+ from datetime import datetime
40
+ from strawberry import auto
41
+ import strawberry, strawberry_django
42
+ from strawberry_django_aggregates import AggregateBuilder
43
+
44
+ from .models import Order
45
+
46
+ @strawberry_django.type(Order)
47
+ class OrderType:
48
+ id: auto
49
+ customer: "CustomerType"
50
+ total: Decimal
51
+ status: str
52
+ created_at: datetime
53
+
54
+ # One call wires count/sum/avg/min/max + group_by + having into the schema:
55
+ order_aggs = AggregateBuilder(
56
+ model=Order,
57
+ aggregate_fields=["total"],
58
+ group_by_fields=["customer", "status", "created_at"],
59
+ ).build()
60
+
61
+ @strawberry.type
62
+ class Query:
63
+ orders_aggregate = order_aggs.aggregate_field
64
+ orders_group_by = order_aggs.group_by_field
65
+ ```
66
+
67
+ Generates a fully-typed GraphQL surface:
68
+
69
+ ```graphql
70
+ type Query {
71
+ ordersAggregate(filter: OrderFilter): OrderAggregate!
72
+ ordersGroupBy(
73
+ filter: OrderFilter
74
+ groupBy: [OrderGroupBySpec!]!
75
+ having: OrderHaving
76
+ orderBy: [OrderGroupOrder!]
77
+ pagination: OffsetPagination
78
+ ): OrderGroupedResult!
79
+ }
80
+
81
+ type OrderAggregate {
82
+ count: Int!
83
+ countDistinct(field: OrderCountableField!): Int!
84
+ sum: OrderSumFields
85
+ avg: OrderAvgFields
86
+ min: OrderMinFields
87
+ max: OrderMaxFields
88
+ stddev: OrderStddevFields # Postgres only
89
+ variance: OrderVarianceFields # Postgres only
90
+ }
91
+
92
+ type OrderGrouped {
93
+ key: OrderGroupKey! # composite — every requested groupBy field present
94
+ count: Int!
95
+ sum: OrderSumFields
96
+ # ... no recursive subgroups field — flat results
97
+ }
98
+ ```
99
+
100
+ ## Features
101
+
102
+ - **Hasura-canonical schema shape.** `<Model>Aggregate { count, countDistinct, sum, avg, min, max, stddev, variance, boolAnd, boolOr, arrayAgg, stringAgg }`.
103
+ - **Odoo-grade group-by.** Multi-level via composite keys (flat result rows), dual date-granularity tracks (`date_trunc` returning `DateTime` AND `date_part::int` returning `Int`), timezone-correct bucketing.
104
+ - **HAVING with aggregate aliases.** `{ countGt: 5, sumTotalGt: 1000 }` — typed inputs generated per measure.
105
+ - **Ordering on aggregates.** `[{ field: "total:sum", direction: DESC }]` — fail-loud on unknown terms (Odoo's pre-17 silent-drop bug avoided).
106
+ - **Standalone backend primitive.** `compute_aggregation(qs, group_by, aggregates, having, order_by, ...)` is callable from any Python context — DRF view, Celery task, admin script, MCP tool — not just GraphQL resolvers.
107
+ - **Determinism.** Type generation produces byte-identical SDL for the same inputs.
108
+ - **No magic.** Every operator, every granularity, every type is whitelisted.
109
+
110
+ ## Non-goals
111
+
112
+ - **Cross-database aggregation.** PostgreSQL + SQLite only. SQLite degrades gracefully on `array_agg`/`string_agg`/`stddev`/`variance` — those operators raise `OperatorNotSupportedError` at resolver entry.
113
+ - **Auto-traversal of one-to-many / many-to-many for measures.** This is the silent row-multiplication footgun [Odoo refuses to ship](https://github.com/odoo/odoo/blob/18.0/odoo/models.py); we follow. `array_agg` is the explicit escape hatch.
114
+ - **Permission integration.** The library expects a pre-scoped queryset — the caller has already applied `accessible_by(user)` or equivalent. This keeps the library compatible with django-guardian, django-rules, [django-rebac](#) (when shipped), or hand-rolled permission systems.
115
+
116
+ ## Status
117
+
118
+ Beta (v0.2.1). The schema shape, operator vocabulary, and `compute_aggregation` signature are stable for early adopters, but minor-level iteration is still expected before a 1.0 stability commitment — see [`docs/SPEC.md`](./docs/SPEC.md) § 16. Runtime: Python 3.13, Django 6.0.
119
+
120
+ ## Documentation
121
+
122
+ - Full contract: [`docs/SPEC.md`](./docs/SPEC.md) — operator catalog, granularity tracks, HAVING semantics, ordering rules, timezone handling, and the Odoo-derived footgun audit.
123
+ - Naming and wire vocabulary: [`docs/TERMINOLOGY.md`](./docs/TERMINOLOGY.md)
124
+ - Contributor quality gate: [`CONTRIBUTING.md`](./CONTRIBUTING.md)
125
+
126
+ ## License
127
+
128
+ BSD-3-Clause.
@@ -0,0 +1,98 @@
1
+ # strawberry-django-aggregates
2
+
3
+ Hasura-shape aggregations over Django querysets in Strawberry GraphQL.
4
+
5
+ `count` · `count_distinct` · `sum` · `avg` · `min` · `max` · `stddev` · `variance` · `bool_and` · `bool_or` · `array_agg` · `string_agg` — composed with multi-level `group_by`, `having` filters, and ordering on aggregate aliases. Inspired by [Hasura](https://hasura.io/docs/latest/api-reference/graphql-api/query/#aggregateobject)'s `<table>_aggregate`, [PostGraphile](https://github.com/graphile/pg-aggregates)'s `pg-aggregates`, and [Odoo 18](https://github.com/odoo/odoo/blob/18.0/odoo/models.py)'s `_read_group`. Built for [`strawberry-django`](https://strawberry-django.readthedocs.io) over PostgreSQL and SQLite.
6
+
7
+ ```python
8
+ from decimal import Decimal
9
+ from datetime import datetime
10
+ from strawberry import auto
11
+ import strawberry, strawberry_django
12
+ from strawberry_django_aggregates import AggregateBuilder
13
+
14
+ from .models import Order
15
+
16
+ @strawberry_django.type(Order)
17
+ class OrderType:
18
+ id: auto
19
+ customer: "CustomerType"
20
+ total: Decimal
21
+ status: str
22
+ created_at: datetime
23
+
24
+ # One call wires count/sum/avg/min/max + group_by + having into the schema:
25
+ order_aggs = AggregateBuilder(
26
+ model=Order,
27
+ aggregate_fields=["total"],
28
+ group_by_fields=["customer", "status", "created_at"],
29
+ ).build()
30
+
31
+ @strawberry.type
32
+ class Query:
33
+ orders_aggregate = order_aggs.aggregate_field
34
+ orders_group_by = order_aggs.group_by_field
35
+ ```
36
+
37
+ Generates a fully-typed GraphQL surface:
38
+
39
+ ```graphql
40
+ type Query {
41
+ ordersAggregate(filter: OrderFilter): OrderAggregate!
42
+ ordersGroupBy(
43
+ filter: OrderFilter
44
+ groupBy: [OrderGroupBySpec!]!
45
+ having: OrderHaving
46
+ orderBy: [OrderGroupOrder!]
47
+ pagination: OffsetPagination
48
+ ): OrderGroupedResult!
49
+ }
50
+
51
+ type OrderAggregate {
52
+ count: Int!
53
+ countDistinct(field: OrderCountableField!): Int!
54
+ sum: OrderSumFields
55
+ avg: OrderAvgFields
56
+ min: OrderMinFields
57
+ max: OrderMaxFields
58
+ stddev: OrderStddevFields # Postgres only
59
+ variance: OrderVarianceFields # Postgres only
60
+ }
61
+
62
+ type OrderGrouped {
63
+ key: OrderGroupKey! # composite — every requested groupBy field present
64
+ count: Int!
65
+ sum: OrderSumFields
66
+ # ... no recursive subgroups field — flat results
67
+ }
68
+ ```
69
+
70
+ ## Features
71
+
72
+ - **Hasura-canonical schema shape.** `<Model>Aggregate { count, countDistinct, sum, avg, min, max, stddev, variance, boolAnd, boolOr, arrayAgg, stringAgg }`.
73
+ - **Odoo-grade group-by.** Multi-level via composite keys (flat result rows), dual date-granularity tracks (`date_trunc` returning `DateTime` AND `date_part::int` returning `Int`), timezone-correct bucketing.
74
+ - **HAVING with aggregate aliases.** `{ countGt: 5, sumTotalGt: 1000 }` — typed inputs generated per measure.
75
+ - **Ordering on aggregates.** `[{ field: "total:sum", direction: DESC }]` — fail-loud on unknown terms (Odoo's pre-17 silent-drop bug avoided).
76
+ - **Standalone backend primitive.** `compute_aggregation(qs, group_by, aggregates, having, order_by, ...)` is callable from any Python context — DRF view, Celery task, admin script, MCP tool — not just GraphQL resolvers.
77
+ - **Determinism.** Type generation produces byte-identical SDL for the same inputs.
78
+ - **No magic.** Every operator, every granularity, every type is whitelisted.
79
+
80
+ ## Non-goals
81
+
82
+ - **Cross-database aggregation.** PostgreSQL + SQLite only. SQLite degrades gracefully on `array_agg`/`string_agg`/`stddev`/`variance` — those operators raise `OperatorNotSupportedError` at resolver entry.
83
+ - **Auto-traversal of one-to-many / many-to-many for measures.** This is the silent row-multiplication footgun [Odoo refuses to ship](https://github.com/odoo/odoo/blob/18.0/odoo/models.py); we follow. `array_agg` is the explicit escape hatch.
84
+ - **Permission integration.** The library expects a pre-scoped queryset — the caller has already applied `accessible_by(user)` or equivalent. This keeps the library compatible with django-guardian, django-rules, [django-rebac](#) (when shipped), or hand-rolled permission systems.
85
+
86
+ ## Status
87
+
88
+ Beta (v0.2.1). The schema shape, operator vocabulary, and `compute_aggregation` signature are stable for early adopters, but minor-level iteration is still expected before a 1.0 stability commitment — see [`docs/SPEC.md`](./docs/SPEC.md) § 16. Runtime: Python 3.13, Django 6.0.
89
+
90
+ ## Documentation
91
+
92
+ - Full contract: [`docs/SPEC.md`](./docs/SPEC.md) — operator catalog, granularity tracks, HAVING semantics, ordering rules, timezone handling, and the Odoo-derived footgun audit.
93
+ - Naming and wire vocabulary: [`docs/TERMINOLOGY.md`](./docs/TERMINOLOGY.md)
94
+ - Contributor quality gate: [`CONTRIBUTING.md`](./CONTRIBUTING.md)
95
+
96
+ ## License
97
+
98
+ BSD-3-Clause.
@@ -0,0 +1,74 @@
1
+ [project]
2
+ name = "strawberry-django-aggregates"
3
+ version = "0.2.1"
4
+ description = "Hasura-shape aggregations over Django querysets in Strawberry GraphQL — count, sum, avg, min, max, stddev, variance, array_agg + Odoo-grade group-by with timezone-correct date bucketing."
5
+ readme = "README.md"
6
+ requires-python = ">=3.14"
7
+ license = { text = "BSD-3-Clause" }
8
+ authors = [{ name = "strawberry-django-aggregates maintainers" }]
9
+ keywords = [
10
+ "django", "strawberry", "graphql", "aggregate", "groupby",
11
+ "hasura", "postgraphile", "odoo", "analytics",
12
+ ]
13
+ classifiers = [
14
+ "Development Status :: 4 - Beta",
15
+ "Framework :: Django",
16
+ "Framework :: Django :: 6.0",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: BSD License",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.14",
22
+ "Topic :: Database",
23
+ "Topic :: Internet :: WWW/HTTP",
24
+ "Typing :: Typed",
25
+ ]
26
+
27
+ dependencies = [
28
+ "django>=6.0",
29
+ "strawberry-graphql>=0.315.0",
30
+ "strawberry-graphql-django>=0.82.0",
31
+ ]
32
+
33
+ [project.optional-dependencies]
34
+ # Postgres-only operators (array_agg, string_agg, stddev, variance).
35
+ # When this extra is NOT installed, those operators raise OperatorNotSupportedError
36
+ # at resolver entry on non-Postgres connections.
37
+ postgres = []
38
+
39
+ [project.urls]
40
+ Homepage = "https://github.com/Apexive/strawberry-django-aggregates"
41
+ Documentation = "https://github.com/Apexive/strawberry-django-aggregates/blob/main/docs/SPEC.md"
42
+ Issues = "https://github.com/Apexive/strawberry-django-aggregates/issues"
43
+
44
+ [dependency-groups]
45
+ dev = [
46
+ "pytest>=8",
47
+ "pytest-django>=4",
48
+ "ruff>=0.6",
49
+ "mypy>=1.10",
50
+ "django-stubs>=5",
51
+ ]
52
+
53
+ [build-system]
54
+ requires = ["setuptools>=68", "wheel"]
55
+ build-backend = "setuptools.build_meta"
56
+
57
+ [tool.setuptools.packages.find]
58
+ where = ["."]
59
+ include = ["strawberry_django_aggregates*"]
60
+ exclude = ["tests*", "docs*"]
61
+
62
+ [tool.ruff]
63
+ line-length = 79
64
+ target-version = "py314"
65
+
66
+ [tool.ruff.lint]
67
+ select = ["E", "F", "W", "I", "B", "UP"]
68
+
69
+ [tool.pytest.ini_options]
70
+ # Django is configured programmatically in tests/conftest.py.
71
+ python_files = ["test_*.py"]
72
+ testpaths = ["tests"]
73
+ addopts = "-ra --strict-markers"
74
+ pythonpath = ["."]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,146 @@
1
+ """strawberry-django-aggregates — Hasura aggregations for Django.
2
+
3
+ Public surface:
4
+
5
+ - :class:`AggregateBuilder` — convenience builder; emits all aggregate
6
+ types and the corresponding strawberry fields for a given model.
7
+ - :func:`make_aggregate_type` — generate the ``<Model>Aggregate`` type.
8
+ - :func:`make_grouped_type` — generate the ``<Model>Grouped`` /
9
+ ``<Model>GroupedResult`` types.
10
+ - :func:`make_having_input` — generate the ``<Model>Having`` input.
11
+ - :func:`make_group_by_spec` — generate the ``<Model>GroupBySpec`` input.
12
+ - :func:`compute_aggregation` — backend primitive; returns flat
13
+ composite-key result rows. Callable outside GraphQL.
14
+ - :class:`AggregateOp` — enum of aggregate operators.
15
+ - :class:`TimeGranularity`, :class:`NumberGranularity` — enums of date
16
+ bucketing tokens (``date_trunc`` and ``date_part::int`` respectively).
17
+ - :func:`parse_aggregate_order` — parser for ``"<field>:<op>"`` order
18
+ terms; raises on unknown.
19
+ - :data:`BigInt` — string-encoded 64-bit signed integer scalar. Output
20
+ type for ``SUM`` over integer Django fields (Postgres widens to
21
+ ``bigint``; the 32-bit GraphQL ``Int`` would silently overflow).
22
+ - :class:`BucketRange` + :func:`bucket_range` — half-open ``[from, to)``
23
+ interval emitted as a sibling on ``<Model>GroupKey`` for each
24
+ TIME-granularity bucket (SPEC § 7).
25
+ - :func:`generate_bucket_spine` + :func:`fill_bucket_results` —
26
+ empty-bucket filling helpers powering ``compute_aggregation(fill=True)``
27
+ (SPEC § 7.2). Pure stdlib; callable from any Python context.
28
+ - :func:`encode_group_cursor` + :func:`decode_group_cursor` — opaque
29
+ cursor encoding for Relay-style grouped pagination (SPEC § 4
30
+ cursor-pagination). Pure stdlib; the same encoding is used by the
31
+ builder's connection field.
32
+ - :func:`register_relation_aggregate` — attach a
33
+ ``<relation>Aggregate(filter: ...)`` field on an existing
34
+ strawberry-django parent type so callers can issue
35
+ ``customer.ordersAggregate { count, sum { total } }``. Per-row
36
+ resolver in v1.0; dataloader-based batching is a v1.x improvement
37
+ (SPEC § 4.2 / Stream 9).
38
+ - :func:`make_grouped_connection_type` — emit Relay-style
39
+ ``<Model>GroupedConnection`` / ``<Model>GroupedEdge`` types.
40
+ - Errors: :class:`AggregateError`, :class:`OperatorNotSupportedError`,
41
+ :class:`OrderFieldNotAllowed`, :class:`AggregationAcrossRelationError`.
42
+
43
+ See ``docs/SPEC.md`` for the full contract.
44
+ """
45
+
46
+ from __future__ import annotations
47
+
48
+ from strawberry_django_aggregates.builder import AggregateBuilder
49
+ from strawberry_django_aggregates.compiler import (
50
+ bucket_range,
51
+ compute_aggregation,
52
+ )
53
+ from strawberry_django_aggregates.errors import (
54
+ AggregateError,
55
+ AggregationAcrossRelationError,
56
+ GranularityNotApplicable,
57
+ GroupByFieldNotAllowed,
58
+ HavingFieldNotAllowed,
59
+ JSONPathNotAllowed,
60
+ OperatorNotSupportedError,
61
+ OrderFieldNotAllowed,
62
+ )
63
+ from strawberry_django_aggregates.fill import (
64
+ fill_bucket_results,
65
+ generate_bucket_spine,
66
+ )
67
+ from strawberry_django_aggregates.granularity import (
68
+ NumberGranularity,
69
+ TimeGranularity,
70
+ validate_week_start,
71
+ )
72
+ from strawberry_django_aggregates.operators import (
73
+ AggregateOp,
74
+ default_operators_for,
75
+ )
76
+ from strawberry_django_aggregates.ordering import (
77
+ comodel_ordering_terms,
78
+ parse_aggregate_order,
79
+ )
80
+ from strawberry_django_aggregates.pagination import (
81
+ decode_group_cursor,
82
+ encode_group_cursor,
83
+ )
84
+ from strawberry_django_aggregates.relations import (
85
+ register_relation_aggregate,
86
+ )
87
+ from strawberry_django_aggregates.types import (
88
+ BigInt,
89
+ BucketRange,
90
+ make_aggregate_type,
91
+ make_group_by_spec,
92
+ make_grouped_connection_type,
93
+ make_grouped_type,
94
+ make_having_input,
95
+ )
96
+
97
+ __version__ = "1.0.0"
98
+
99
+ __all__ = [
100
+ # Builder (high-level)
101
+ "AggregateBuilder",
102
+ # Type generators
103
+ "make_aggregate_type",
104
+ "make_grouped_type",
105
+ "make_grouped_connection_type",
106
+ "make_having_input",
107
+ "make_group_by_spec",
108
+ # Backend primitive
109
+ "compute_aggregation",
110
+ # Vocabularies
111
+ "AggregateOp",
112
+ "TimeGranularity",
113
+ "NumberGranularity",
114
+ "validate_week_start",
115
+ "default_operators_for",
116
+ # Custom scalars
117
+ "BigInt",
118
+ # Bucket range — half-open [from, to) interval for TIME-granularity
119
+ # group-by buckets (SPEC § 7 / Stream 5).
120
+ "BucketRange",
121
+ "bucket_range",
122
+ # Empty-bucket filling — dense bucket spine over date-bucketed
123
+ # results (SPEC § 7.2 / Stream 7).
124
+ "fill_bucket_results",
125
+ "generate_bucket_spine",
126
+ # Cursor pagination — opaque base64 / JSON encoding over the
127
+ # canonical-order group-by alias values (SPEC § 4 / Stream 11).
128
+ "encode_group_cursor",
129
+ "decode_group_cursor",
130
+ # Cross-relation aggregate field — attach
131
+ # ``<relation>Aggregate(filter: ...)`` to a strawberry-django
132
+ # parent type (SPEC § 4.2 / Stream 9).
133
+ "register_relation_aggregate",
134
+ # Ordering
135
+ "parse_aggregate_order",
136
+ "comodel_ordering_terms",
137
+ # Errors
138
+ "AggregateError",
139
+ "OperatorNotSupportedError",
140
+ "OrderFieldNotAllowed",
141
+ "AggregationAcrossRelationError",
142
+ "HavingFieldNotAllowed",
143
+ "GroupByFieldNotAllowed",
144
+ "GranularityNotApplicable",
145
+ "JSONPathNotAllowed",
146
+ ]