Skip to content

Commit 5f7524f

Browse files
authored
Release 1.0 (#7)
1 parent d68764a commit 5f7524f

43 files changed

Lines changed: 478 additions & 689 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎README.md‎

Lines changed: 59 additions & 55 deletions
Large diffs are not rendered by default.

‎bookshop/app_graphql.py‎

Lines changed: 19 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,7 @@
66
from bookshop.graphql.runtime import _operation_type
77
from bookshop.graphql.runtime import _reflection
88
from bookshop.graphql import runtime as _runtime
9-
from bookshop.graphql.schema import enum as _enum
10-
from bookshop.graphql.schema import input as _input
11-
from bookshop.graphql import _scalar
9+
from bookshop.graphql import schema as _schema
1210

1311
class _BookCard_author(_compat.TypedDict, closed=True):
1412
name: _builtins.str
@@ -17,23 +15,23 @@ class BookCard(_compat.TypedDict):
1715
"""What a book shows in a list."""
1816
id: _builtins.str
1917
title: _builtins.str
20-
price: _scalar.Money
18+
price: _schema.Money
2119
author: _BookCard_author | None
2220
"""Null for an anthology, which has no single author."""
2321

2422
class GetBookVariables(_compat.TypedDict, closed=True):
25-
lookup: _input.BookLookup
23+
lookup: _schema.BookLookup
2624
"""An identifier or an ISBN."""
2725
withReviews: _typing.NotRequired[_builtins.bool]
2826

2927
class _GetBookData_book_reviews(_compat.TypedDict, closed=True):
3028
rating: _builtins.int
3129
"""From 1 to 5."""
3230
text: _builtins.str | None
33-
postedAt: _scalar.DateTime
31+
postedAt: _schema.DateTime
3432

3533
class _GetBookData_book(BookCard, closed=True):
36-
isbn: _scalar.ISBN
34+
isbn: _schema.ISBN
3735
pageCount: _builtins.int
3836
reviews: _typing.NotRequired[_builtins.list[_GetBookData_book_reviews]]
3937

@@ -71,19 +69,19 @@ class SearchVariables(_compat.TypedDict, closed=True):
7169

7270
class _SearchData_search_Book(_SearchData_search_Book_Base, closed=True):
7371
title: _builtins.str
74-
price: _scalar.Money
72+
price: _schema.Money
7573

7674
_SearchData_search_Magazine_Base = _compat.TypedDict('_SearchData_search_Magazine_Base', {'__typename': _compat.ReadOnly[_typing.Literal['Magazine']]})
7775

7876
class _SearchData_search_Magazine(_SearchData_search_Magazine_Base, closed=True):
7977
title: _builtins.str
80-
price: _scalar.Money
78+
price: _schema.Money
8179

8280
_SearchData_search_Audiobook_Base = _compat.TypedDict('_SearchData_search_Audiobook_Base', {'__typename': _compat.ReadOnly[_typing.Literal['Audiobook']]})
8381

8482
class _SearchData_search_Audiobook(_SearchData_search_Audiobook_Base, closed=True):
8583
title: _builtins.str
86-
price: _scalar.Money
84+
price: _schema.Money
8785

8886
_SearchData_search_Author_Base = _compat.TypedDict('_SearchData_search_Author_Base', {'__typename': _compat.ReadOnly[_typing.Literal['Author']]})
8987

@@ -110,11 +108,11 @@ class SearchData(_compat.TypedDict, closed=True):
110108
}""", variables_type=SearchVariables, data_type=SearchData)
111109

112110
class ListBooksVariables(_compat.TypedDict, closed=True):
113-
filter: _typing.NotRequired[_input.BookFilter | None]
111+
filter: _typing.NotRequired[_schema.BookFilter | None]
114112
first: _typing.NotRequired[_builtins.int | None]
115113

116114
class _ListBooksData_books(BookCard, closed=True):
117-
genre: _enum.Genre
115+
genre: _schema.Genre
118116

119117
class ListBooksData(_compat.TypedDict, closed=True):
120118
books: _builtins.list[_ListBooksData_books]
@@ -144,7 +142,7 @@ class GetPublicationVariables(_compat.TypedDict, closed=True):
144142
class _GetPublicationData_publication_Book(_GetPublicationData_publication_Book_Base, closed=True):
145143
title: _builtins.str
146144
pages: _builtins.int
147-
isbn: _scalar.ISBN
145+
isbn: _schema.ISBN
148146

149147
_GetPublicationData_publication_Magazine_Base = _compat.TypedDict('_GetPublicationData_publication_Magazine_Base', {'__typename': _compat.ReadOnly[_typing.Literal['Magazine']]})
150148

@@ -186,7 +184,7 @@ class GetSavedSearchVariables(_compat.TypedDict, closed=True):
186184
name: _builtins.str
187185

188186
class _GetSavedSearchData_savedSearch(_compat.TypedDict, closed=True):
189-
value: _input.BookFilter | None
187+
value: _schema.BookFilter | None
190188

191189
class GetSavedSearchData(_compat.TypedDict, closed=True):
192190
savedSearch: _GetSavedSearchData_savedSearch | None
@@ -199,13 +197,13 @@ class GetSavedSearchData(_compat.TypedDict, closed=True):
199197
}""", variables_type=GetSavedSearchVariables, data_type=GetSavedSearchData)
200198

201199
class PlaceOrderVariables(_compat.TypedDict, closed=True):
202-
input: _input.PlaceOrderInput
200+
input: _schema.PlaceOrderInput
203201

204202
class _PlaceOrderData_placeOrder(_compat.TypedDict, closed=True):
205203
id: _builtins.str
206-
status: _enum.OrderStatus
207-
total: _scalar.Money
208-
placedAt: _scalar.DateTime
204+
status: _schema.OrderStatus
205+
total: _schema.Money
206+
placedAt: _schema.DateTime
209207

210208
class PlaceOrderData(_compat.TypedDict, closed=True):
211209
placeOrder: _PlaceOrderData_placeOrder
@@ -221,11 +219,11 @@ class PlaceOrderData(_compat.TypedDict, closed=True):
221219
}""", variables_type=PlaceOrderVariables, injections={'idempotencyKey': _builtins.frozenset({('input',)})}, data_type=PlaceOrderData)
222220

223221
class CancelOrderVariables(_compat.TypedDict, closed=True):
224-
input: _input.CancelOrderInput
222+
input: _schema.CancelOrderInput
225223

226224
class _CancelOrderData_cancelOrder(_compat.TypedDict, closed=True):
227225
id: _builtins.str
228-
status: _enum.OrderStatus
226+
status: _schema.OrderStatus
229227

230228
class CancelOrderData(_compat.TypedDict, closed=True):
231229
cancelOrder: _CancelOrderData_cancelOrder | None
@@ -246,7 +244,7 @@ class OnOrderStatusChangedVariables(_compat.TypedDict, closed=True):
246244

247245
class _OnOrderStatusChangedData_orderStatusChanged(_compat.TypedDict, closed=True):
248246
id: _builtins.str
249-
status: _enum.OrderStatus
247+
status: _schema.OrderStatus
250248

251249
class OnOrderStatusChangedData(_compat.TypedDict, closed=True):
252250
orderStatusChanged: _OnOrderStatusChangedData_orderStatusChanged

‎bookshop/get_order_graphql.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,14 @@
55
from bookshop.graphql.runtime import _compat
66
from bookshop.graphql.runtime import _operation_type
77
from bookshop.graphql import runtime as _runtime
8-
from bookshop.graphql.schema import enum as _enum
8+
from bookshop.graphql import schema as _schema
99

1010
class GetOrderVariables(_compat.TypedDict, closed=True):
1111
id: _builtins.str
1212

1313
class _GetOrderData_order(_compat.TypedDict, closed=True):
1414
id: _builtins.str
15-
status: _enum.OrderStatus
15+
status: _schema.OrderStatus
1616

1717
class GetOrderData(_compat.TypedDict, closed=True):
1818
order: _GetOrderData_order | None

‎bookshop/graphql.config.yml‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
# An SDL file here, but globs, introspection results, and server URLs work too.
22
schema: schema.graphqls
33
documents: "*.graphql"
4-
# This library's config, under its extension name.
4+
# graphql-codegen's config, under its extension name.
55
extensions:
66
pythonCodegen:
77
# Where imports start, relative to this file's directory.

‎bookshop/graphql/_scalar.py‎

Lines changed: 0 additions & 19 deletions
This file was deleted.

‎bookshop/graphql/injection.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33
import collections.abc as _abc
44
from .runtime import _compat
55
from .runtime import injection as _injection
6-
from . import _scalar
6+
from . import schema as _schema
77

88
class InjectorFunctions(_compat.TypedDict, closed=True):
99
"""The functions supplying each injected value, by name.
1010
1111
Where the value may be null, one returning `OMITTED` leaves it out, and one returning `None` sends `null`."""
12-
idempotencyKey: _abc.Callable[[], _scalar.UUID]
12+
idempotencyKey: _abc.Callable[[], _schema.UUID]
1313

1414
def injectors(functions: InjectorFunctions, /) -> _injection._Injectors:
1515
"""Return what `Request.prepare()` calls to supply the injected values, each serialized as its type says."""

‎bookshop/graphql/runtime/_reflection.py‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -229,7 +229,7 @@ def convert(value: object, /) -> object:
229229
try:
230230
result[key] = convert_value(result[key])
231231
except UnexpectedNullError as error:
232-
error.path.insert(0, key)
232+
error._path.insert(0, key)
233233
raise
234234

235235
return result
@@ -323,7 +323,7 @@ def convert(value: object, /) -> object:
323323
try:
324324
result.append(convert_item(item))
325325
except UnexpectedNullError as error:
326-
error.path.insert(0, index)
326+
error._path.insert(0, index)
327327
raise
328328

329329
return result

‎bookshop/graphql/runtime/error.py‎

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,20 @@ class UnexpectedNullError(Error):
2727
"""
2828

2929
def __init__(self, path: list[str | int], /) -> None:
30-
self.path: Final = path
30+
"""Private."""
31+
# Each level the error unwinds through prepends its key or index.
32+
self._path: Final = path
3133
super().__init__()
3234

35+
@property
36+
def path(self) -> Sequence[str | int]:
37+
return self._path
38+
3339
@override
3440
def __str__(self) -> str:
3541
formatted = "".join(
3642
f"[{segment}]" if isinstance(segment, int) else f".{segment}"
37-
for segment in self.path
43+
for segment in self._path
3844
).removeprefix(".")
3945
return f"Expected `{formatted}` to not be null."
4046

@@ -51,7 +57,7 @@ class GraphqlError(TypedDict):
5157
message: Required[str]
5258
locations: NotRequired[Sequence[Location]]
5359
path: NotRequired[Sequence[str | int]]
54-
extensions: NotRequired[object]
60+
extensions: NotRequired[Mapping[str, object]]
5561

5662

5763
class ResponseError(Error):
@@ -64,6 +70,7 @@ def __init__(
6470
*,
6571
extensions: Mapping[str, object] | None,
6672
) -> None:
73+
"""Private."""
6774
assert errors, "Cannot raise without at least one error."
6875
self.errors: Final = tuple(errors)
6976
self.extensions: Final = extensions
@@ -117,6 +124,7 @@ def __init__(
117124
extensions: Mapping[str, object] | None,
118125
partial_data_parser: Callable[[object], object] | None,
119126
) -> None:
127+
"""Private."""
120128
super().__init__(errors, extensions=extensions)
121129
self.data = data
122130
self._partial_data_parser: Final = partial_data_parser

‎bookshop/graphql/runtime/operation.py‎

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -44,10 +44,7 @@ def __init__(
4444
injections: Mapping[str, frozenset[tuple[str, ...]]] = _NO_INJECTIONS,
4545
data_type: type[Data],
4646
) -> None:
47-
"""*injections* maps each injector's name to the paths of the objects receiving its value, `()` being the variables themselves.
48-
49-
What crosses the wire is read off *variables_type* and *data_type* at runtime.
50-
"""
47+
"""Private."""
5148
self._operation_type: Final = operation_type
5249
self._name: Final = name
5350
self._document: Final = document
Lines changed: 30 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -4,38 +4,53 @@
44
import builtins as _builtins
55
import collections.abc as _abc
66
import typing as _typing
7-
from ..runtime import _compat
8-
from ..schema import enum as _enum
9-
from .. import _scalar
7+
from .runtime import _compat
8+
from .runtime import _reflection
9+
from datetime import datetime as _datetime
10+
from ..scalar import decode_datetime as _decode_datetime
11+
from ..scalar import encode_datetime as _encode_datetime
12+
from ..scalar import ISBN as _ISBN
13+
from decimal import Decimal as _Decimal
14+
from uuid import UUID as _UUID
1015

11-
type _BookFilter_Ref = BookFilter
16+
type DateTime = _typing.Annotated[_datetime, _reflection.Codec(decode=_decode_datetime, encode=_encode_datetime)]
17+
18+
type Money = _typing.Annotated[_Decimal, _reflection.Codec(decode=_Decimal, encode=_builtins.str)]
19+
20+
type ISBN = _ISBN
21+
22+
type UUID = _typing.Annotated[_UUID, _reflection.Codec(decode=_UUID, encode=_builtins.str)]
23+
24+
type Genre = _typing.Literal['FICTION', 'NONFICTION', 'POETRY', 'CHILDREN']
25+
26+
type OrderStatus = _typing.Literal['PENDING', 'SHIPPED', 'DELIVERED', 'CANCELED']
27+
28+
type BookLookup = _BookLookup_id | _BookLookup_isbn
29+
"""A book, found by exactly one of its identifiers."""
1230

1331
class _BookLookup_id(_compat.TypedDict, closed=True):
1432
id: _builtins.str
1533

1634
class _BookLookup_isbn(_compat.TypedDict, closed=True):
17-
isbn: _scalar.ISBN
35+
isbn: ISBN
1836

19-
type BookLookup = _BookLookup_id | _BookLookup_isbn
20-
"""A book, found by exactly one of its identifiers."""
37+
type BookFilter = _BookFilter_genre | _BookFilter_author | _BookFilter_priceBelow | _BookFilter_and | _BookFilter_or | _BookFilter_not
38+
"""A recursive filter on books."""
2139

2240
class _BookFilter_genre(_compat.TypedDict, closed=True):
23-
genre: _enum.Genre
41+
genre: Genre
2442

2543
class _BookFilter_author(_compat.TypedDict, closed=True):
2644
author: _builtins.str
2745

2846
class _BookFilter_priceBelow(_compat.TypedDict, closed=True):
29-
priceBelow: _scalar.Money
47+
priceBelow: Money
3048

31-
_BookFilter_and = _compat.TypedDict('_BookFilter_and', {'and': _abc.Sequence[_BookFilter_Ref]}, closed=True)
49+
_BookFilter_and = _compat.TypedDict('_BookFilter_and', {'and': _abc.Sequence[BookFilter]}, closed=True)
3250

33-
_BookFilter_or = _compat.TypedDict('_BookFilter_or', {'or': _abc.Sequence[_BookFilter_Ref]}, closed=True)
51+
_BookFilter_or = _compat.TypedDict('_BookFilter_or', {'or': _abc.Sequence[BookFilter]}, closed=True)
3452

35-
_BookFilter_not = _compat.TypedDict('_BookFilter_not', {'not': _BookFilter_Ref}, closed=True)
36-
37-
type BookFilter = _BookFilter_genre | _BookFilter_author | _BookFilter_priceBelow | _BookFilter_and | _BookFilter_or | _BookFilter_not
38-
"""A recursive filter on books."""
53+
_BookFilter_not = _compat.TypedDict('_BookFilter_not', {'not': BookFilter}, closed=True)
3954

4055
class PlaceOrderInput(_compat.TypedDict, closed=True):
4156
lines: _abc.Sequence[OrderLineInput]

0 commit comments

Comments
 (0)