async-graph-data-flow 1.5.1__tar.gz → 1.6.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.
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/CHANGELOG.md +13 -0
- {async_graph_data_flow-1.5.1/src/async_graph_data_flow.egg-info → async_graph_data_flow-1.6.0}/PKG-INFO +9 -9
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/README.md +1 -1
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/pyproject.toml +7 -7
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow/executor.py +6 -2
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow/graph.py +34 -10
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0/src/async_graph_data_flow.egg-info}/PKG-INFO +9 -9
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow.egg-info/requires.txt +6 -6
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/tests/test_graph.py +3 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/LICENSE.txt +0 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/MANIFEST.in +0 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/setup.cfg +0 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow/__init__.py +0 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow/py.typed +0 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow.egg-info/SOURCES.txt +0 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow.egg-info/dependency_links.txt +0 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow.egg-info/not-zip-safe +0 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow.egg-info/top_level.txt +0 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/tests/test_executor.py +0 -0
- {async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/tests/test_version_number.py +0 -0
|
@@ -19,6 +19,19 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
|
|
|
19
19
|
|
|
20
20
|
### Security
|
|
21
21
|
|
|
22
|
+
## [1.6.0] - 2025-03-19
|
|
23
|
+
|
|
24
|
+
### Added
|
|
25
|
+
- Added support for custom edge behaviors, through the new `queue` argument at `add_node`
|
|
26
|
+
for a custom queue object. (#14)
|
|
27
|
+
|
|
28
|
+
### Deprecated
|
|
29
|
+
- Deprecated the `queue_size` argument at `add_node` -- use the new `queue` instead. (#14)
|
|
30
|
+
|
|
31
|
+
### Security
|
|
32
|
+
- Resolved CVE-2024-56326, CVE-2024-56201, and CVE-2025-27516
|
|
33
|
+
by updating jinja2 to v3.1.6 in requirements for Sphinx docs. (#14)
|
|
34
|
+
|
|
22
35
|
## [1.5.1] - 2024-11-07
|
|
23
36
|
|
|
24
37
|
### Added
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: async-graph-data-flow
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.0
|
|
4
4
|
Summary: Asynchronous functions that pass data along a directed acyclic graph
|
|
5
5
|
Author-email: Civis Analytics <opensource@civisanalytics.com>
|
|
6
6
|
License: BSD 3-Clause
|
|
@@ -24,14 +24,14 @@ Requires-Python: >=3.10
|
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE.txt
|
|
26
26
|
Provides-Extra: dev
|
|
27
|
-
Requires-Dist: black==
|
|
28
|
-
Requires-Dist: flake8==7.1.
|
|
29
|
-
Requires-Dist: pytest==8.3.
|
|
30
|
-
Requires-Dist: mypy==1.
|
|
27
|
+
Requires-Dist: black==25.1.0; extra == "dev"
|
|
28
|
+
Requires-Dist: flake8==7.1.2; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest==8.3.5; extra == "dev"
|
|
30
|
+
Requires-Dist: mypy==1.15.0; extra == "dev"
|
|
31
31
|
Requires-Dist: build==1.2.2; extra == "dev"
|
|
32
|
-
Requires-Dist: twine==
|
|
32
|
+
Requires-Dist: twine==6.1.0; extra == "dev"
|
|
33
33
|
Provides-Extra: docs
|
|
34
|
-
Requires-Dist: Sphinx==8.
|
|
34
|
+
Requires-Dist: Sphinx==8.2.3; extra == "docs"
|
|
35
35
|
Requires-Dist: furo==2024.8.6; extra == "docs"
|
|
36
36
|
Requires-Dist: numpydoc==1.8.0; extra == "docs"
|
|
37
37
|
Requires-Dist: sphinx-copybutton==0.5.2; extra == "docs"
|
|
@@ -77,7 +77,7 @@ black --check src tests examples
|
|
|
77
77
|
|
|
78
78
|
## Building Documentation
|
|
79
79
|
|
|
80
|
-
We use the Sphinx framework. The documentation source files are in `docs
|
|
80
|
+
We use the Sphinx framework. The documentation source files are in `docs/`.
|
|
81
81
|
These files can be updated as necessary.
|
|
82
82
|
|
|
83
83
|
The public documentation is accessible at https://async-graph-data-flow.readthedocs.io.
|
|
@@ -38,7 +38,7 @@ black --check src tests examples
|
|
|
38
38
|
|
|
39
39
|
## Building Documentation
|
|
40
40
|
|
|
41
|
-
We use the Sphinx framework. The documentation source files are in `docs
|
|
41
|
+
We use the Sphinx framework. The documentation source files are in `docs/`.
|
|
42
42
|
These files can be updated as necessary.
|
|
43
43
|
|
|
44
44
|
The public documentation is accessible at https://async-graph-data-flow.readthedocs.io.
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "async-graph-data-flow"
|
|
7
|
-
version = "1.
|
|
7
|
+
version = "1.6.0"
|
|
8
8
|
description = "Asynchronous functions that pass data along a directed acyclic graph"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
requires-python = ">= 3.10"
|
|
@@ -40,17 +40,17 @@ Source = "https://github.com/civisanalytics/async-graph-data-flow"
|
|
|
40
40
|
[project.optional-dependencies]
|
|
41
41
|
dev = [
|
|
42
42
|
# Running tests and linters
|
|
43
|
-
"black ==
|
|
44
|
-
"flake8 == 7.1.
|
|
45
|
-
"pytest == 8.3.
|
|
46
|
-
"mypy == 1.
|
|
43
|
+
"black == 25.1.0",
|
|
44
|
+
"flake8 == 7.1.2",
|
|
45
|
+
"pytest == 8.3.5",
|
|
46
|
+
"mypy == 1.15.0",
|
|
47
47
|
|
|
48
48
|
# Managing source distributions
|
|
49
49
|
"build == 1.2.2",
|
|
50
|
-
"twine ==
|
|
50
|
+
"twine == 6.1.0",
|
|
51
51
|
]
|
|
52
52
|
docs = [
|
|
53
|
-
"Sphinx == 8.
|
|
53
|
+
"Sphinx == 8.2.3",
|
|
54
54
|
"furo == 2024.8.6",
|
|
55
55
|
"numpydoc == 1.8.0",
|
|
56
56
|
"sphinx-copybutton == 0.5.2",
|
{async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow/executor.py
RENAMED
|
@@ -4,7 +4,8 @@ import logging
|
|
|
4
4
|
import time
|
|
5
5
|
import traceback
|
|
6
6
|
from collections import deque
|
|
7
|
-
from
|
|
7
|
+
from collections.abc import Iterable
|
|
8
|
+
from typing import Any
|
|
8
9
|
|
|
9
10
|
from .graph import AsyncGraph, InvalidAsyncGraphError
|
|
10
11
|
|
|
@@ -284,7 +285,10 @@ class AsyncExecutor:
|
|
|
284
285
|
self._exceptions = {}
|
|
285
286
|
|
|
286
287
|
for node_name, node in self._graph._nodes.items():
|
|
287
|
-
queue
|
|
288
|
+
if node.queue is None:
|
|
289
|
+
queue = asyncio.Queue(maxsize=node.queue_size)
|
|
290
|
+
else:
|
|
291
|
+
queue = node.queue
|
|
288
292
|
self._node_queues[node_name] = queue
|
|
289
293
|
self._data_flow_stats[node_name] = {"in": 0, "out": 0, "err": 0}
|
|
290
294
|
self._exceptions[node_name] = deque(maxlen=self._max_exceptions)
|
{async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow/graph.py
RENAMED
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import asyncio
|
|
1
2
|
import inspect
|
|
2
3
|
from collections import OrderedDict
|
|
3
|
-
from
|
|
4
|
+
from collections.abc import AsyncGenerator, Callable
|
|
5
|
+
from typing import Any, NamedTuple
|
|
4
6
|
|
|
5
7
|
|
|
6
8
|
class InvalidAsyncGraphError(Exception):
|
|
@@ -8,8 +10,9 @@ class InvalidAsyncGraphError(Exception):
|
|
|
8
10
|
|
|
9
11
|
|
|
10
12
|
class _Node(NamedTuple):
|
|
11
|
-
func: Callable
|
|
13
|
+
func: Callable[..., AsyncGenerator]
|
|
12
14
|
name: str
|
|
15
|
+
queue: asyncio.Queue | None
|
|
13
16
|
queue_size: int
|
|
14
17
|
max_tasks: int
|
|
15
18
|
halt_on_exception: bool
|
|
@@ -32,12 +35,13 @@ class AsyncGraph:
|
|
|
32
35
|
|
|
33
36
|
def add_node(
|
|
34
37
|
self,
|
|
35
|
-
func: Callable,
|
|
38
|
+
func: Callable[..., AsyncGenerator],
|
|
36
39
|
*,
|
|
37
40
|
name: str | None = None,
|
|
38
41
|
halt_on_exception: bool = False,
|
|
39
42
|
unpack_input: bool = True,
|
|
40
43
|
max_tasks: int = 1,
|
|
44
|
+
queue: asyncio.Queue | None = None,
|
|
41
45
|
queue_size: int = 10_000,
|
|
42
46
|
check_async_gen: bool = True,
|
|
43
47
|
) -> None:
|
|
@@ -45,8 +49,8 @@ class AsyncGraph:
|
|
|
45
49
|
|
|
46
50
|
Parameters
|
|
47
51
|
----------
|
|
48
|
-
func : Callable
|
|
49
|
-
The function that this node runs.
|
|
52
|
+
func : Callable[..., AsyncGenerator]
|
|
53
|
+
The asynchronous generator function that this node runs.
|
|
50
54
|
See notes below for the function's requirements.
|
|
51
55
|
name : str, optional
|
|
52
56
|
The name of this node. If not provided, the ``__name__`` attribute
|
|
@@ -62,10 +66,23 @@ class AsyncGraph:
|
|
|
62
66
|
See notes below for more details.
|
|
63
67
|
max_tasks : int, optional
|
|
64
68
|
The number of tasks that this node runs concurrently.
|
|
69
|
+
queue : asyncio.Queue, optional
|
|
70
|
+
The queue object that collects items from this node's source nodes,
|
|
71
|
+
via ``await queue.put(item)``, and then feed into this node
|
|
72
|
+
with items retrieved by ``await queue.get()``.
|
|
73
|
+
This queue object must be an instance of either :class:`~asyncio.Queue` or
|
|
74
|
+
a subclass of :class:`~asyncio.Queue`.
|
|
75
|
+
If ``None`` or not given, it defaults to an ``asyncio.Queue()`` with max
|
|
76
|
+
size set by ``queue_size``.
|
|
65
77
|
queue_size : int, optional
|
|
66
78
|
The maximum number of data items allowed to be
|
|
67
|
-
in the
|
|
68
|
-
and its
|
|
79
|
+
in the queue object between this node as a destination node
|
|
80
|
+
and its source node(s).
|
|
81
|
+
|
|
82
|
+
.. deprecated:: 1.6.0
|
|
83
|
+
The argument ``queue_size`` is deprecated and will be removed in
|
|
84
|
+
v2.0.0. To configure the queue size, please use the argument ``queue``
|
|
85
|
+
for a queue object whose queue size is set.
|
|
69
86
|
check_async_gen : bool, optional
|
|
70
87
|
If ``True`` (the default), the callable ``func`` is verified to be an async
|
|
71
88
|
generator function by :func:`inspect.isasyncgenfunction`.
|
|
@@ -129,9 +146,12 @@ class AsyncGraph:
|
|
|
129
146
|
raise TypeError(f"node '{name}' isn't an async generator function")
|
|
130
147
|
if name in self._nodes:
|
|
131
148
|
raise ValueError(f"node '{name}' already exists in the graph")
|
|
149
|
+
if queue is not None and not isinstance(queue, asyncio.Queue):
|
|
150
|
+
raise TypeError(f"queue must be an instance of asyncio.Queue: {queue}")
|
|
132
151
|
self._nodes[name] = _Node(
|
|
133
152
|
func=func,
|
|
134
153
|
name=name,
|
|
154
|
+
queue=queue,
|
|
135
155
|
queue_size=queue_size,
|
|
136
156
|
max_tasks=max_tasks,
|
|
137
157
|
halt_on_exception=halt_on_exception,
|
|
@@ -139,14 +159,18 @@ class AsyncGraph:
|
|
|
139
159
|
)
|
|
140
160
|
self._nodes_to_edges[name] = set()
|
|
141
161
|
|
|
142
|
-
def add_edge(
|
|
162
|
+
def add_edge(
|
|
163
|
+
self,
|
|
164
|
+
src_node: str | Callable[..., AsyncGenerator],
|
|
165
|
+
dst_node: str | Callable[..., AsyncGenerator],
|
|
166
|
+
) -> None:
|
|
143
167
|
"""Add an edge.
|
|
144
168
|
|
|
145
169
|
Parameters
|
|
146
170
|
----------
|
|
147
|
-
src_node : str | Callable
|
|
171
|
+
src_node : str | Callable[..., AsyncGenerator]
|
|
148
172
|
The source node, either the function name or the function itself.
|
|
149
|
-
dst_node : str | Callable
|
|
173
|
+
dst_node : str | Callable[..., AsyncGenerator]
|
|
150
174
|
The destination node, either the function name or the function itself.
|
|
151
175
|
"""
|
|
152
176
|
if not isinstance(src_node, str):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.2
|
|
2
2
|
Name: async-graph-data-flow
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.6.0
|
|
4
4
|
Summary: Asynchronous functions that pass data along a directed acyclic graph
|
|
5
5
|
Author-email: Civis Analytics <opensource@civisanalytics.com>
|
|
6
6
|
License: BSD 3-Clause
|
|
@@ -24,14 +24,14 @@ Requires-Python: >=3.10
|
|
|
24
24
|
Description-Content-Type: text/markdown
|
|
25
25
|
License-File: LICENSE.txt
|
|
26
26
|
Provides-Extra: dev
|
|
27
|
-
Requires-Dist: black==
|
|
28
|
-
Requires-Dist: flake8==7.1.
|
|
29
|
-
Requires-Dist: pytest==8.3.
|
|
30
|
-
Requires-Dist: mypy==1.
|
|
27
|
+
Requires-Dist: black==25.1.0; extra == "dev"
|
|
28
|
+
Requires-Dist: flake8==7.1.2; extra == "dev"
|
|
29
|
+
Requires-Dist: pytest==8.3.5; extra == "dev"
|
|
30
|
+
Requires-Dist: mypy==1.15.0; extra == "dev"
|
|
31
31
|
Requires-Dist: build==1.2.2; extra == "dev"
|
|
32
|
-
Requires-Dist: twine==
|
|
32
|
+
Requires-Dist: twine==6.1.0; extra == "dev"
|
|
33
33
|
Provides-Extra: docs
|
|
34
|
-
Requires-Dist: Sphinx==8.
|
|
34
|
+
Requires-Dist: Sphinx==8.2.3; extra == "docs"
|
|
35
35
|
Requires-Dist: furo==2024.8.6; extra == "docs"
|
|
36
36
|
Requires-Dist: numpydoc==1.8.0; extra == "docs"
|
|
37
37
|
Requires-Dist: sphinx-copybutton==0.5.2; extra == "docs"
|
|
@@ -77,7 +77,7 @@ black --check src tests examples
|
|
|
77
77
|
|
|
78
78
|
## Building Documentation
|
|
79
79
|
|
|
80
|
-
We use the Sphinx framework. The documentation source files are in `docs
|
|
80
|
+
We use the Sphinx framework. The documentation source files are in `docs/`.
|
|
81
81
|
These files can be updated as necessary.
|
|
82
82
|
|
|
83
83
|
The public documentation is accessible at https://async-graph-data-flow.readthedocs.io.
|
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
|
|
2
2
|
[dev]
|
|
3
|
-
black==
|
|
4
|
-
flake8==7.1.
|
|
5
|
-
pytest==8.3.
|
|
6
|
-
mypy==1.
|
|
3
|
+
black==25.1.0
|
|
4
|
+
flake8==7.1.2
|
|
5
|
+
pytest==8.3.5
|
|
6
|
+
mypy==1.15.0
|
|
7
7
|
build==1.2.2
|
|
8
|
-
twine==
|
|
8
|
+
twine==6.1.0
|
|
9
9
|
|
|
10
10
|
[docs]
|
|
11
|
-
Sphinx==8.
|
|
11
|
+
Sphinx==8.2.3
|
|
12
12
|
furo==2024.8.6
|
|
13
13
|
numpydoc==1.8.0
|
|
14
14
|
sphinx-copybutton==0.5.2
|
|
@@ -84,6 +84,7 @@ class TestAsyncGraphAddNode:
|
|
|
84
84
|
"halt_on_exception": False,
|
|
85
85
|
"max_tasks": 1,
|
|
86
86
|
"name": "extract_node",
|
|
87
|
+
"queue": None,
|
|
87
88
|
"queue_size": 10_000,
|
|
88
89
|
"unpack_input": True,
|
|
89
90
|
},
|
|
@@ -92,6 +93,7 @@ class TestAsyncGraphAddNode:
|
|
|
92
93
|
"halt_on_exception": False,
|
|
93
94
|
"max_tasks": 1,
|
|
94
95
|
"name": "transform_node",
|
|
96
|
+
"queue": None,
|
|
95
97
|
"queue_size": 10_000,
|
|
96
98
|
"unpack_input": True,
|
|
97
99
|
},
|
|
@@ -100,6 +102,7 @@ class TestAsyncGraphAddNode:
|
|
|
100
102
|
"halt_on_exception": False,
|
|
101
103
|
"max_tasks": 1,
|
|
102
104
|
"name": "load_node",
|
|
105
|
+
"queue": None,
|
|
103
106
|
"queue_size": 10_000,
|
|
104
107
|
"unpack_input": True,
|
|
105
108
|
},
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow/__init__.py
RENAMED
|
File without changes
|
{async_graph_data_flow-1.5.1 → async_graph_data_flow-1.6.0}/src/async_graph_data_flow/py.typed
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|