flpit 0.2.0__tar.gz → 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.
- flpit-0.2.0/README.md → flpit-0.2.1/PKG-INFO +85 -0
- flpit-0.2.0/PKG-INFO → flpit-0.2.1/README.md +61 -21
- {flpit-0.2.0 → flpit-0.2.1}/pyproject.toml +9 -4
- {flpit-0.2.0 → flpit-0.2.1}/src/flpit/core/linq.py +67 -9
- flpit-0.2.1/src/flpit/csv.py +333 -0
- flpit-0.2.1/src/flpit/json.py +694 -0
- flpit-0.2.1/src/flpit/task.py +1873 -0
- {flpit-0.2.0 → flpit-0.2.1}/.gitignore +0 -0
- {flpit-0.2.0 → flpit-0.2.1}/LICENSE +0 -0
- {flpit-0.2.0 → flpit-0.2.1}/src/flp/__init__.py +0 -0
- {flpit-0.2.0 → flpit-0.2.1}/src/flpit/__init__.py +0 -0
- {flpit-0.2.0 → flpit-0.2.1}/src/flpit/core/__init__.py +0 -0
- {flpit-0.2.0 → flpit-0.2.1}/src/flpit/flp.py +0 -0
- {flpit-0.2.0 → flpit-0.2.1}/src/flpit/py.typed +0 -0
|
@@ -1,3 +1,27 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: flpit
|
|
3
|
+
Version: 0.2.1
|
|
4
|
+
Summary: Fluent LINQ for Python — flip your iterables
|
|
5
|
+
Project-URL: Homepage, https://github.com/riemar/flpit
|
|
6
|
+
Project-URL: Repository, https://github.com/riemar/flpit
|
|
7
|
+
Project-URL: Issues, https://github.com/riemar/flpit/issues
|
|
8
|
+
License: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: fluent,generators,iterable,lazy-evaluation,linq,pipeline,pyrefly,type-safe
|
|
11
|
+
Classifier: Development Status :: 3 - Alpha
|
|
12
|
+
Classifier: Intended Audience :: Developers
|
|
13
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
14
|
+
Classifier: Programming Language :: Python :: 3
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
19
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
20
|
+
Classifier: Typing :: Typed
|
|
21
|
+
Requires-Python: >=3.12
|
|
22
|
+
Requires-Dist: msgspec>=0.22.0
|
|
23
|
+
Description-Content-Type: text/markdown
|
|
24
|
+
|
|
1
25
|
# FlpIt
|
|
2
26
|
|
|
3
27
|
> **Fluent LINQ for Python — LINQ semantics, Python-native execution**
|
|
@@ -130,6 +154,52 @@ print(list(backend_engineers))
|
|
|
130
154
|
# ['Alice']
|
|
131
155
|
```
|
|
132
156
|
|
|
157
|
+
## JSON Serialization
|
|
158
|
+
|
|
159
|
+
FlpIt provides typed JSON serialization and deserialization through `flpit.json.JsonConvert`,
|
|
160
|
+
backed by [`msgspec`](https://github.com/jcrist/msgspec).
|
|
161
|
+
|
|
162
|
+
It supports dataclasses, nested models, generic containers, configurable property naming, and explicit field metadata.
|
|
163
|
+
|
|
164
|
+
```python
|
|
165
|
+
from dataclasses import dataclass
|
|
166
|
+
from typing import Annotated
|
|
167
|
+
|
|
168
|
+
from flpit import FlpList
|
|
169
|
+
from flpit.json import JProp, JIgnore, JsonConvert
|
|
170
|
+
|
|
171
|
+
@dataclass
|
|
172
|
+
class Person:
|
|
173
|
+
first_name: str
|
|
174
|
+
internal_id: Annotated[str, JProp("id")]
|
|
175
|
+
password: Annotated[str, JIgnore] = ""
|
|
176
|
+
|
|
177
|
+
|
|
178
|
+
person = Person("Ada", "usr-42", "secret")
|
|
179
|
+
raw = JsonConvert.serialize(person, Person)
|
|
180
|
+
# {"firstName":"Ada","id":"usr-42"}
|
|
181
|
+
|
|
182
|
+
people_json = """
|
|
183
|
+
[
|
|
184
|
+
{"firstName": "Ada", "id": "usr-42"},
|
|
185
|
+
{"firstName": "Grace", "id": "usr-43"}
|
|
186
|
+
]
|
|
187
|
+
"""
|
|
188
|
+
|
|
189
|
+
people: FlpList[Person] = FlpList.from_json(people_json, Person)
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### Mapping and conversion
|
|
193
|
+
|
|
194
|
+
- **Naming policies:** Configure automatic property naming with `JsonSerializerOptions`. The default is camel case.
|
|
195
|
+
- **Explicit metadata:** `JProp` assigns a specific JSON property name, `JIgnore` excludes a field, and `JInclude` explicitly includes otherwise excluded underscore-prefixed fields.
|
|
196
|
+
- **Serialization options:** Control default-value omission and whether unknown JSON fields are accepted or rejected.
|
|
197
|
+
- **Typed collections:** Pass the complete target type, such as `list[Person]`, so nested and generic values can be decoded against the intended schema.
|
|
198
|
+
|
|
199
|
+
For large outputs, `JsonConvert.serialize_to()` writes a JSON array to a file-like stream without first materializing the entire serialized document.
|
|
200
|
+
|
|
201
|
+
By default, deserialization returns instances of the requested model type. Setting `native=True` opts into the generated `msgspec.Struct` representation instead, trading the original model type for the native representation and its performance characteristics.
|
|
202
|
+
|
|
133
203
|
## 🔬 LINQ Semantics, Python Runtime
|
|
134
204
|
|
|
135
205
|
`flpit` deliberately separates the two:
|
|
@@ -325,6 +395,21 @@ to_list ← terminal materialization
|
|
|
325
395
|
|
|
326
396
|
Operations such as `order_by()` necessarily materialize their input internally to establish ordering.
|
|
327
397
|
|
|
398
|
+
## ⚙️ Task Runtime
|
|
399
|
+
|
|
400
|
+
FlpIt includes a lightweight, `asyncio`-free task runtime for scheduling and coordinating concurrent work, with synchronous callables executed through a bounded worker pool.
|
|
401
|
+
|
|
402
|
+
Key features:
|
|
403
|
+
|
|
404
|
+
- **Task scheduling:** `Task.run()` schedules coroutines, awaitables, and synchronous callables.
|
|
405
|
+
- **Task coordination:** `Task.when_all()` waits for all tasks while preserving input order; `Task.when_any()` returns the first completed task; `Task.collect()` yields tasks as they complete.
|
|
406
|
+
- **Cancellation:** `CancellationToken` and `CancellationTokenSource` support cooperative cancellation, cancellation callbacks, timeouts, and linked cancellation tokens.
|
|
407
|
+
- **Resource management:** Configure worker capacity and pending background-work limits, handle queue saturation explicitly, and shut down the process-wide runtime with an observable shutdown report.
|
|
408
|
+
|
|
409
|
+
The runtime starts lazily and manages its own lifecycle. It is deliberately not an `asyncio` compatibility layer; cancellation of running synchronous functions is cooperative.
|
|
410
|
+
|
|
411
|
+
See the [Task Runtime examples](https://github.com/riemar/flpit/tree/main/examples/task) for usage examples.
|
|
412
|
+
|
|
328
413
|
## ⚙️ Installation
|
|
329
414
|
|
|
330
415
|
```bash
|
|
@@ -1,24 +1,3 @@
|
|
|
1
|
-
Metadata-Version: 2.5
|
|
2
|
-
Name: flpit
|
|
3
|
-
Version: 0.2.0
|
|
4
|
-
Summary: Fluent LINQ for Python — flip your iterables
|
|
5
|
-
Project-URL: Homepage, https://github.com/riemar/flpit
|
|
6
|
-
License: MIT
|
|
7
|
-
License-File: LICENSE
|
|
8
|
-
Keywords: fluent,generators,iterable,lazy-evaluation,linq,pipeline,pyrefly,type-safe
|
|
9
|
-
Classifier: Development Status :: 3 - Alpha
|
|
10
|
-
Classifier: Intended Audience :: Developers
|
|
11
|
-
Classifier: License :: OSI Approved :: MIT License
|
|
12
|
-
Classifier: Programming Language :: Python :: 3
|
|
13
|
-
Classifier: Programming Language :: Python :: 3.11
|
|
14
|
-
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
-
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.14
|
|
17
|
-
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
18
|
-
Classifier: Typing :: Typed
|
|
19
|
-
Requires-Python: >=3.11
|
|
20
|
-
Description-Content-Type: text/markdown
|
|
21
|
-
|
|
22
1
|
# FlpIt
|
|
23
2
|
|
|
24
3
|
> **Fluent LINQ for Python — LINQ semantics, Python-native execution**
|
|
@@ -151,6 +130,52 @@ print(list(backend_engineers))
|
|
|
151
130
|
# ['Alice']
|
|
152
131
|
```
|
|
153
132
|
|
|
133
|
+
## JSON Serialization
|
|
134
|
+
|
|
135
|
+
FlpIt provides typed JSON serialization and deserialization through `flpit.json.JsonConvert`,
|
|
136
|
+
backed by [`msgspec`](https://github.com/jcrist/msgspec).
|
|
137
|
+
|
|
138
|
+
It supports dataclasses, nested models, generic containers, configurable property naming, and explicit field metadata.
|
|
139
|
+
|
|
140
|
+
```python
|
|
141
|
+
from dataclasses import dataclass
|
|
142
|
+
from typing import Annotated
|
|
143
|
+
|
|
144
|
+
from flpit import FlpList
|
|
145
|
+
from flpit.json import JProp, JIgnore, JsonConvert
|
|
146
|
+
|
|
147
|
+
@dataclass
|
|
148
|
+
class Person:
|
|
149
|
+
first_name: str
|
|
150
|
+
internal_id: Annotated[str, JProp("id")]
|
|
151
|
+
password: Annotated[str, JIgnore] = ""
|
|
152
|
+
|
|
153
|
+
|
|
154
|
+
person = Person("Ada", "usr-42", "secret")
|
|
155
|
+
raw = JsonConvert.serialize(person, Person)
|
|
156
|
+
# {"firstName":"Ada","id":"usr-42"}
|
|
157
|
+
|
|
158
|
+
people_json = """
|
|
159
|
+
[
|
|
160
|
+
{"firstName": "Ada", "id": "usr-42"},
|
|
161
|
+
{"firstName": "Grace", "id": "usr-43"}
|
|
162
|
+
]
|
|
163
|
+
"""
|
|
164
|
+
|
|
165
|
+
people: FlpList[Person] = FlpList.from_json(people_json, Person)
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### Mapping and conversion
|
|
169
|
+
|
|
170
|
+
- **Naming policies:** Configure automatic property naming with `JsonSerializerOptions`. The default is camel case.
|
|
171
|
+
- **Explicit metadata:** `JProp` assigns a specific JSON property name, `JIgnore` excludes a field, and `JInclude` explicitly includes otherwise excluded underscore-prefixed fields.
|
|
172
|
+
- **Serialization options:** Control default-value omission and whether unknown JSON fields are accepted or rejected.
|
|
173
|
+
- **Typed collections:** Pass the complete target type, such as `list[Person]`, so nested and generic values can be decoded against the intended schema.
|
|
174
|
+
|
|
175
|
+
For large outputs, `JsonConvert.serialize_to()` writes a JSON array to a file-like stream without first materializing the entire serialized document.
|
|
176
|
+
|
|
177
|
+
By default, deserialization returns instances of the requested model type. Setting `native=True` opts into the generated `msgspec.Struct` representation instead, trading the original model type for the native representation and its performance characteristics.
|
|
178
|
+
|
|
154
179
|
## 🔬 LINQ Semantics, Python Runtime
|
|
155
180
|
|
|
156
181
|
`flpit` deliberately separates the two:
|
|
@@ -346,6 +371,21 @@ to_list ← terminal materialization
|
|
|
346
371
|
|
|
347
372
|
Operations such as `order_by()` necessarily materialize their input internally to establish ordering.
|
|
348
373
|
|
|
374
|
+
## ⚙️ Task Runtime
|
|
375
|
+
|
|
376
|
+
FlpIt includes a lightweight, `asyncio`-free task runtime for scheduling and coordinating concurrent work, with synchronous callables executed through a bounded worker pool.
|
|
377
|
+
|
|
378
|
+
Key features:
|
|
379
|
+
|
|
380
|
+
- **Task scheduling:** `Task.run()` schedules coroutines, awaitables, and synchronous callables.
|
|
381
|
+
- **Task coordination:** `Task.when_all()` waits for all tasks while preserving input order; `Task.when_any()` returns the first completed task; `Task.collect()` yields tasks as they complete.
|
|
382
|
+
- **Cancellation:** `CancellationToken` and `CancellationTokenSource` support cooperative cancellation, cancellation callbacks, timeouts, and linked cancellation tokens.
|
|
383
|
+
- **Resource management:** Configure worker capacity and pending background-work limits, handle queue saturation explicitly, and shut down the process-wide runtime with an observable shutdown report.
|
|
384
|
+
|
|
385
|
+
The runtime starts lazily and manages its own lifecycle. It is deliberately not an `asyncio` compatibility layer; cancellation of running synchronous functions is cooperative.
|
|
386
|
+
|
|
387
|
+
See the [Task Runtime examples](https://github.com/riemar/flpit/tree/main/examples/task) for usage examples.
|
|
388
|
+
|
|
349
389
|
## ⚙️ Installation
|
|
350
390
|
|
|
351
391
|
```bash
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "flpit"
|
|
3
|
-
version = "0.2.
|
|
3
|
+
version = "0.2.1"
|
|
4
4
|
description = "Fluent LINQ for Python — flip your iterables"
|
|
5
5
|
readme = "README.md"
|
|
6
|
-
requires-python = ">=3.
|
|
6
|
+
requires-python = ">=3.12"
|
|
7
7
|
license = { text = "MIT" }
|
|
8
8
|
keywords = ["linq", "fluent", "iterable", "pipeline", "lazy-evaluation", "pyrefly", "type-safe", "generators"]
|
|
9
9
|
classifiers = [
|
|
@@ -11,17 +11,21 @@ classifiers = [
|
|
|
11
11
|
"Intended Audience :: Developers",
|
|
12
12
|
"License :: OSI Approved :: MIT License",
|
|
13
13
|
"Programming Language :: Python :: 3",
|
|
14
|
-
"Programming Language :: Python :: 3.11",
|
|
15
14
|
"Programming Language :: Python :: 3.12",
|
|
16
15
|
"Programming Language :: Python :: 3.13",
|
|
17
16
|
"Programming Language :: Python :: 3.14",
|
|
17
|
+
"Programming Language :: Python :: 3.15",
|
|
18
18
|
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
19
19
|
"Typing :: Typed"
|
|
20
20
|
]
|
|
21
|
-
dependencies = [
|
|
21
|
+
dependencies = [
|
|
22
|
+
"msgspec>=0.22.0",
|
|
23
|
+
]
|
|
22
24
|
|
|
23
25
|
[project.urls]
|
|
24
26
|
Homepage = "https://github.com/riemar/flpit"
|
|
27
|
+
Repository = "https://github.com/riemar/flpit"
|
|
28
|
+
Issues = "https://github.com/riemar/flpit/issues"
|
|
25
29
|
|
|
26
30
|
[dependency-groups]
|
|
27
31
|
dev = [
|
|
@@ -31,6 +35,7 @@ dev = [
|
|
|
31
35
|
"pyright>=1.1.414",
|
|
32
36
|
"pytest-benchmark>=5.3.0",
|
|
33
37
|
"mypy>=2.4.0",
|
|
38
|
+
"httpx>=0.28.1",
|
|
34
39
|
]
|
|
35
40
|
|
|
36
41
|
|
|
@@ -1,7 +1,10 @@
|
|
|
1
1
|
from __future__ import annotations
|
|
2
|
-
|
|
2
|
+
|
|
3
|
+
from io import BytesIO, StringIO
|
|
4
|
+
|
|
3
5
|
import decimal
|
|
4
6
|
from decimal import Decimal, Overflow, Inexact
|
|
7
|
+
from contextlib import AbstractContextManager
|
|
5
8
|
|
|
6
9
|
import builtins
|
|
7
10
|
from collections import UserList
|
|
@@ -15,15 +18,21 @@ from typing import (
|
|
|
15
18
|
Iterable,
|
|
16
19
|
Iterator,
|
|
17
20
|
Collection,
|
|
21
|
+
SupportsIndex,
|
|
18
22
|
List,
|
|
19
23
|
Set,
|
|
20
24
|
Type,
|
|
21
25
|
TypeVar,
|
|
26
|
+
ClassVar,
|
|
22
27
|
Union,
|
|
23
28
|
override,
|
|
24
29
|
overload,
|
|
25
|
-
cast as typing_cast,
|
|
30
|
+
cast as typing_cast, BinaryIO,
|
|
26
31
|
)
|
|
32
|
+
|
|
33
|
+
import flpit.json
|
|
34
|
+
from flpit.json import JsonConvert, JsonSerializerOptions
|
|
35
|
+
|
|
27
36
|
TItem = TypeVar("TItem")
|
|
28
37
|
TResult = TypeVar("TResult")
|
|
29
38
|
TKey = TypeVar("TKey")
|
|
@@ -118,8 +127,7 @@ def _guard_empty(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
|
118
127
|
return wrapper
|
|
119
128
|
|
|
120
129
|
|
|
121
|
-
|
|
122
|
-
def dotnet_context() -> decimal._ContextManager: # awesome that type was not intended
|
|
130
|
+
def dotnet_context() -> AbstractContextManager[decimal.Context]:
|
|
123
131
|
# 1. Create and configure pure Context object
|
|
124
132
|
ctx = decimal.getcontext().copy()
|
|
125
133
|
ctx.prec = max(ctx.prec, 29)
|
|
@@ -246,8 +254,8 @@ class FlpIt(Iterable[TItem], Generic[TItem]):
|
|
|
246
254
|
for item in self:
|
|
247
255
|
if predicate(item):
|
|
248
256
|
yield item
|
|
249
|
-
|
|
250
|
-
return
|
|
257
|
+
# return typing_cast(FlpIt[TItem], FlpIt[TItem](_FactoryIterable(_generator)))
|
|
258
|
+
return FlpIt[TItem](_FactoryIterable(_generator))
|
|
251
259
|
|
|
252
260
|
def select(self, selector: Callable[[TItem], TResult]) -> FlpIt[TResult]:
|
|
253
261
|
"""Projects each element into a new form."""
|
|
@@ -617,10 +625,36 @@ class FlpIt(Iterable[TItem], Generic[TItem]):
|
|
|
617
625
|
|
|
618
626
|
raise MultipleMatchesError() if has_predicate else MultipleElementsError()
|
|
619
627
|
|
|
620
|
-
|
|
621
628
|
def to_list(self) -> FlpList[TItem]:
|
|
622
629
|
"""Explicitly materializes the query into a FlpList."""
|
|
623
|
-
return FlpList(self)
|
|
630
|
+
return FlpList[TItem](self)
|
|
631
|
+
|
|
632
|
+
# =====================================================================
|
|
633
|
+
# 5. json serialization
|
|
634
|
+
# =====================================================================
|
|
635
|
+
|
|
636
|
+
@classmethod
|
|
637
|
+
def from_json[T](cls, data: str | bytes, item_type: type[T], jso: JsonSerializerOptions|None=None) -> FlpIt[T]:
|
|
638
|
+
return FlpIt[T](JsonConvert.deserialize(data, list[item_type], jso))
|
|
639
|
+
|
|
640
|
+
def to_json_bytes[T](self, item_type: type[T], jso: JsonSerializerOptions|None=None) -> bytes:
|
|
641
|
+
writer = BytesIO()
|
|
642
|
+
JsonConvert.serialize_to(self, item_type, writer, jso)
|
|
643
|
+
return writer.getvalue()
|
|
644
|
+
|
|
645
|
+
def to_json[T](self, item_type: type[T], jso: JsonSerializerOptions|None=None) -> str:
|
|
646
|
+
writer = StringIO()
|
|
647
|
+
JsonConvert.serialize_to(self, item_type, writer, jso)
|
|
648
|
+
return writer.getvalue()
|
|
649
|
+
|
|
650
|
+
def write_json[T](
|
|
651
|
+
self,
|
|
652
|
+
item_type: type[T],
|
|
653
|
+
output: BinaryIO,
|
|
654
|
+
jso: JsonSerializerOptions | None = None,
|
|
655
|
+
) -> None:
|
|
656
|
+
JsonConvert.serialize_to(self, item_type, output, jso)
|
|
657
|
+
|
|
624
658
|
|
|
625
659
|
from functools import partial
|
|
626
660
|
|
|
@@ -731,6 +765,8 @@ class FlpList(Collection[TItem], Generic[TItem]):
|
|
|
731
765
|
| Fluent List
|
|
732
766
|
A materialized list extending UserList that yields lazy FlpIt instances for query operations.
|
|
733
767
|
"""
|
|
768
|
+
__type_args__: ClassVar[tuple[Any, ...]]
|
|
769
|
+
|
|
734
770
|
def __init__(self, source: Iterable[TItem] | _Sentinel=_SENTINEL):
|
|
735
771
|
if source is None:
|
|
736
772
|
raise SourceNoneError()
|
|
@@ -1001,7 +1037,7 @@ class FlpList(Collection[TItem], Generic[TItem]):
|
|
|
1001
1037
|
return self # type: ignore[return-value]
|
|
1002
1038
|
|
|
1003
1039
|
def where(self, predicate: Callable[[TItem], bool]) -> FlpIt[TItem]:
|
|
1004
|
-
return FlpIt(self.__list.data).where(predicate)
|
|
1040
|
+
return FlpIt[TItem](self.__list.data).where(predicate)
|
|
1005
1041
|
|
|
1006
1042
|
def select(self, selector: Callable[[TItem], TResult]) -> FlpIt[TResult]:
|
|
1007
1043
|
return FlpIt(self.__list.data).select(selector)
|
|
@@ -1179,3 +1215,25 @@ class FlpList(Collection[TItem], Generic[TItem]):
|
|
|
1179
1215
|
def to_list(self) -> FlpList[TItem]:
|
|
1180
1216
|
"""Explicitly returns a shallow copy instance to isolate mutations."""
|
|
1181
1217
|
return FlpList(self.__list.data.copy())
|
|
1218
|
+
|
|
1219
|
+
# =====================================================================
|
|
1220
|
+
# 5. json serialization
|
|
1221
|
+
# =====================================================================
|
|
1222
|
+
|
|
1223
|
+
@classmethod
|
|
1224
|
+
def from_json[T](cls, data: str | bytes, item_type: type[T], jso: JsonSerializerOptions|None=None) -> FlpList[T]:
|
|
1225
|
+
return FlpList[T](JsonConvert.deserialize(data, list[item_type], jso))
|
|
1226
|
+
|
|
1227
|
+
def to_json_bytes[T](self, item_type: type[T], jso: JsonSerializerOptions|None=None) -> bytes:
|
|
1228
|
+
return JsonConvert.serialize_bytes(self.__list.data, list[item_type], jso)
|
|
1229
|
+
|
|
1230
|
+
def to_json[T](self, item_type: type[T], jso: JsonSerializerOptions|None=None) -> str:
|
|
1231
|
+
return JsonConvert.serialize(self.__list.data, list[item_type], jso)
|
|
1232
|
+
|
|
1233
|
+
def write_json[T](
|
|
1234
|
+
self,
|
|
1235
|
+
item_type: type[T],
|
|
1236
|
+
output: BinaryIO,
|
|
1237
|
+
jso: JsonSerializerOptions | None = None,
|
|
1238
|
+
) -> None:
|
|
1239
|
+
JsonConvert.serialize_to(self, item_type, output, jso)
|