async-graph-data-flow 1.2.0__tar.gz → 1.4.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.
Files changed (18) hide show
  1. {async-graph-data-flow-1.2.0/src/async_graph_data_flow.egg-info → async-graph-data-flow-1.4.0}/PKG-INFO +13 -2
  2. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/pyproject.toml +11 -10
  3. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/src/async_graph_data_flow/executor.py +5 -5
  4. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/src/async_graph_data_flow/graph.py +15 -10
  5. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0/src/async_graph_data_flow.egg-info}/PKG-INFO +13 -2
  6. async-graph-data-flow-1.4.0/src/async_graph_data_flow.egg-info/requires.txt +12 -0
  7. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/tests/test_executor.py +1 -1
  8. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/tests/test_graph.py +25 -0
  9. async-graph-data-flow-1.2.0/src/async_graph_data_flow.egg-info/requires.txt +0 -12
  10. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/LICENSE.txt +0 -0
  11. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/README.md +0 -0
  12. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/setup.cfg +0 -0
  13. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/src/async_graph_data_flow/__init__.py +0 -0
  14. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/src/async_graph_data_flow.egg-info/SOURCES.txt +0 -0
  15. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/src/async_graph_data_flow.egg-info/dependency_links.txt +0 -0
  16. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/src/async_graph_data_flow.egg-info/not-zip-safe +0 -0
  17. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/src/async_graph_data_flow.egg-info/top_level.txt +0 -0
  18. {async-graph-data-flow-1.2.0 → async-graph-data-flow-1.4.0}/tests/test_version_number.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: async-graph-data-flow
3
- Version: 1.2.0
3
+ Version: 1.4.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
@@ -16,11 +16,22 @@ Classifier: Programming Language :: Python :: 3
16
16
  Classifier: Programming Language :: Python :: 3 :: Only
17
17
  Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
19
20
  Classifier: Framework :: AsyncIO
20
21
  Requires-Python: >=3.10
21
22
  Description-Content-Type: text/markdown
22
- Provides-Extra: dev
23
23
  License-File: LICENSE.txt
24
+ Provides-Extra: dev
25
+ Requires-Dist: black==23.11.0; extra == "dev"
26
+ Requires-Dist: flake8==6.1.0; extra == "dev"
27
+ Requires-Dist: pytest==7.4.3; extra == "dev"
28
+ Requires-Dist: build==1.0.3; extra == "dev"
29
+ Requires-Dist: twine==4.0.2; extra == "dev"
30
+ Requires-Dist: Sphinx==7.2.6; extra == "dev"
31
+ Requires-Dist: furo==2023.9.10; extra == "dev"
32
+ Requires-Dist: numpydoc==1.6.0; extra == "dev"
33
+ Requires-Dist: sphinx-copybutton==0.5.2; extra == "dev"
34
+ Requires-Dist: sphinxcontrib-mermaid==0.9.2; extra == "dev"
24
35
 
25
36
  # async-graph-data-flow
26
37
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "async-graph-data-flow"
7
- version = "1.2.0"
7
+ version = "1.4.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"
@@ -28,6 +28,7 @@ classifiers = [
28
28
  "Programming Language :: Python :: 3 :: Only",
29
29
  "Programming Language :: Python :: 3.10",
30
30
  "Programming Language :: Python :: 3.11",
31
+ "Programming Language :: Python :: 3.12",
31
32
  "Framework :: AsyncIO",
32
33
  ]
33
34
 
@@ -37,20 +38,20 @@ Source = "https://github.com/civisanalytics/async-graph-data-flow"
37
38
  [project.optional-dependencies]
38
39
  dev = [
39
40
  # Running tests and linters
40
- "black == 23.1.0",
41
- "flake8 == 6.0.0",
42
- "pytest == 7.2.1",
41
+ "black == 23.11.0",
42
+ "flake8 == 6.1.0",
43
+ "pytest == 7.4.3",
43
44
 
44
45
  # Managing source distributions
45
- "build == 0.10.0",
46
+ "build == 1.0.3",
46
47
  "twine == 4.0.2",
47
48
 
48
49
  # Documentation
49
- "Sphinx == 6.1.3",
50
- "furo == 2022.12.7",
51
- "numpydoc == 1.5.0",
52
- "sphinx-copybutton == 0.5.1",
53
- "sphinxcontrib-mermaid == 0.8",
50
+ "Sphinx == 7.2.6",
51
+ "furo == 2023.9.10",
52
+ "numpydoc == 1.6.0",
53
+ "sphinx-copybutton == 0.5.2",
54
+ "sphinxcontrib-mermaid == 0.9.2",
54
55
  ]
55
56
 
56
57
  [tool.setuptools.packages.find]
@@ -4,7 +4,7 @@ import logging
4
4
  import time
5
5
  import traceback
6
6
  from collections import deque
7
- from typing import Any, Iterable, Optional
7
+ from typing import Any, Iterable
8
8
 
9
9
  from .graph import AsyncGraph, InvalidAsyncGraphError
10
10
 
@@ -102,10 +102,10 @@ class AsyncExecutor:
102
102
 
103
103
  def turn_on_data_flow_logging(
104
104
  self,
105
- node_format: Optional[str] = None,
106
- node_filter: Iterable[str] = None,
107
- time_interval: Optional[int] = None,
108
- logger: logging.Logger = None,
105
+ node_format: str | None = None,
106
+ node_filter: Iterable[str] | None = None,
107
+ time_interval: int | None = None,
108
+ logger: logging.Logger | None = None,
109
109
  ):
110
110
  """Turn on and configure data flow logging.
111
111
 
@@ -1,6 +1,6 @@
1
1
  import inspect
2
2
  from collections import OrderedDict
3
- from typing import Any, Callable, NamedTuple, Optional
3
+ from typing import Any, Callable, NamedTuple
4
4
 
5
5
 
6
6
  _DEFAULT_NUM_OF_WORKERS = 1
@@ -37,11 +37,12 @@ class AsyncGraph:
37
37
  self,
38
38
  func: Callable,
39
39
  *,
40
- name: Optional[str] = None,
41
- halt_on_exception: Optional[bool] = False,
42
- unpack_input: Optional[bool] = True,
43
- max_tasks: Optional[int] = 1,
44
- queue_size: Optional[int] = 10_000,
40
+ name: str | None = None,
41
+ halt_on_exception: bool = False,
42
+ unpack_input: bool = True,
43
+ max_tasks: int = 1,
44
+ queue_size: int = 10_000,
45
+ check_async_gen: bool = True,
45
46
  ) -> None:
46
47
  """Add a node by providing its function and optional configurations.
47
48
 
@@ -68,16 +69,20 @@ class AsyncGraph:
68
69
  The maximum number of data items allowed to be
69
70
  in the :class:`~asyncio.Queue` object between this node as a source
70
71
  and its destination node(s).
72
+ check_async_gen : bool, optional
73
+ If ``True`` (the default), the callable ``func`` is verified to be an async
74
+ generator function by :func:`inspect.isasyncgenfunction`.
75
+ Pass in ``False`` to disable this check if ``func`` would fail the check
76
+ while the callable under the hood is still an async generator function
77
+ (e.g., your function is wrapped by a decorator).
71
78
 
72
79
  Notes
73
80
  -----
74
- These details concern the reqiurements of the node's function and the keyword
81
+ These details concern the requirements of the node's function and the keyword
75
82
  argument ``unpack_input``.
76
83
 
77
84
  * Each function in the graph must be an **asynchronous generator function**,
78
85
  i.e., it's defined by ``async def`` and it yields.
79
- Implementationally, calling :func:`inspect.isasyncgenfunction`
80
- on your function must return ``True``.
81
86
 
82
87
  * Each function can have any signature,
83
88
  with no arguments or with any valid argument types
@@ -123,7 +128,7 @@ class AsyncGraph:
123
128
  """ # noqa: E501
124
129
 
125
130
  name = name or func.__name__
126
- if not inspect.isasyncgenfunction(func):
131
+ if check_async_gen and not inspect.isasyncgenfunction(func):
127
132
  raise TypeError(f"node '{name}' isn't an async generator function")
128
133
  if name in self._nodes:
129
134
  raise ValueError(f"node '{name}' already exists in the graph")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: async-graph-data-flow
3
- Version: 1.2.0
3
+ Version: 1.4.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
@@ -16,11 +16,22 @@ Classifier: Programming Language :: Python :: 3
16
16
  Classifier: Programming Language :: Python :: 3 :: Only
17
17
  Classifier: Programming Language :: Python :: 3.10
18
18
  Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
19
20
  Classifier: Framework :: AsyncIO
20
21
  Requires-Python: >=3.10
21
22
  Description-Content-Type: text/markdown
22
- Provides-Extra: dev
23
23
  License-File: LICENSE.txt
24
+ Provides-Extra: dev
25
+ Requires-Dist: black==23.11.0; extra == "dev"
26
+ Requires-Dist: flake8==6.1.0; extra == "dev"
27
+ Requires-Dist: pytest==7.4.3; extra == "dev"
28
+ Requires-Dist: build==1.0.3; extra == "dev"
29
+ Requires-Dist: twine==4.0.2; extra == "dev"
30
+ Requires-Dist: Sphinx==7.2.6; extra == "dev"
31
+ Requires-Dist: furo==2023.9.10; extra == "dev"
32
+ Requires-Dist: numpydoc==1.6.0; extra == "dev"
33
+ Requires-Dist: sphinx-copybutton==0.5.2; extra == "dev"
34
+ Requires-Dist: sphinxcontrib-mermaid==0.9.2; extra == "dev"
24
35
 
25
36
  # async-graph-data-flow
26
37
 
@@ -0,0 +1,12 @@
1
+
2
+ [dev]
3
+ black==23.11.0
4
+ flake8==6.1.0
5
+ pytest==7.4.3
6
+ build==1.0.3
7
+ twine==4.0.2
8
+ Sphinx==7.2.6
9
+ furo==2023.9.10
10
+ numpydoc==1.6.0
11
+ sphinx-copybutton==0.5.2
12
+ sphinxcontrib-mermaid==0.9.2
@@ -442,7 +442,7 @@ def test_exceptions():
442
442
  actual_exc_msgs = [e.args[0] for e in excs["node2"]]
443
443
  expected_exc_msgs = ["bad data: hello", "bad data: world"]
444
444
  assert actual_exc_msgs == expected_exc_msgs
445
- assert all(type(e) == ValueError for e in excs["node2"])
445
+ assert all(type(e) is ValueError for e in excs["node2"])
446
446
 
447
447
  assert executor.data_flow_stats["node1"].get("in") == 0
448
448
  assert executor.data_flow_stats["node1"].get("out") == 2
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  from unittest import mock
2
3
 
3
4
  import pytest
@@ -39,6 +40,30 @@ class TestAsyncGraphAddNode:
39
40
  "node 'none_node' isn't an async generator function"
40
41
  )
41
42
 
43
+ def test_add_node_disable_async_gen_func_check(self):
44
+ async def some_func():
45
+ yield "foo"
46
+
47
+ def some_decorator(func):
48
+ def inner_func(*args, **kwargs):
49
+ yield from func(*args, **kwargs)
50
+
51
+ inner_func.__name__ = func.__name__
52
+ return inner_func
53
+
54
+ assert inspect.isasyncgenfunction(some_func)
55
+ AsyncGraph().add_node(some_func) # Should raise no error, compare with below
56
+
57
+ some_func = some_decorator(some_func)
58
+
59
+ assert not inspect.isasyncgenfunction(some_func)
60
+ with pytest.raises(TypeError) as excinfo:
61
+ AsyncGraph().add_node(some_func)
62
+ assert str(excinfo.value) == (
63
+ "node 'some_func' isn't an async generator function"
64
+ )
65
+ AsyncGraph().add_node(some_func, check_async_gen=False)
66
+
42
67
  def test_add_node_with_valid_node_args(self):
43
68
  etl_graph = async_graph_without_nodes_mock()
44
69
  assert len(etl_graph._nodes.keys()) == 0
@@ -1,12 +0,0 @@
1
-
2
- [dev]
3
- black==23.1.0
4
- flake8==6.0.0
5
- pytest==7.2.1
6
- build==0.10.0
7
- twine==4.0.2
8
- Sphinx==6.1.3
9
- furo==2022.12.7
10
- numpydoc==1.5.0
11
- sphinx-copybutton==0.5.1
12
- sphinxcontrib-mermaid==0.8