taskflow-tr 0.1.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 gaoxinge
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,345 @@
1
+ Metadata-Version: 2.4
2
+ Name: taskflow-tr
3
+ Version: 0.1.0
4
+ Summary: Compile Python functions into GraphIR DAGs and execute them inline, with threads, or with processes.
5
+ Author-email: gaoxinge <gaoxx5@gmail.com>
6
+ Maintainer-email: gaoxinge <gaoxx5@gmail.com>
7
+ License: MIT License
8
+
9
+ Copyright (c) 2026 gaoxinge
10
+
11
+ Permission is hereby granted, free of charge, to any person obtaining a copy
12
+ of this software and associated documentation files (the "Software"), to deal
13
+ in the Software without restriction, including without limitation the rights
14
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
15
+ copies of the Software, and to permit persons to whom the Software is
16
+ furnished to do so, subject to the following conditions:
17
+
18
+ The above copyright notice and this permission notice shall be included in all
19
+ copies or substantial portions of the Software.
20
+
21
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
26
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
27
+ SOFTWARE.
28
+
29
+ Project-URL: Homepage, https://github.com/gaoxinge/task_flow
30
+ Project-URL: Repository, https://github.com/gaoxinge/task_flow
31
+ Project-URL: Issues, https://github.com/gaoxinge/task_flow/issues
32
+ Project-URL: Documentation, https://github.com/gaoxinge/task_flow#readme
33
+ Keywords: dag,graph-ir,workflow,concurrency,threading,multiprocessing
34
+ Classifier: Development Status :: 3 - Alpha
35
+ Classifier: Intended Audience :: Developers
36
+ Classifier: License :: OSI Approved :: MIT License
37
+ Classifier: Operating System :: OS Independent
38
+ Classifier: Programming Language :: Python :: 3
39
+ Classifier: Programming Language :: Python :: 3.8
40
+ Classifier: Programming Language :: Python :: 3.9
41
+ Classifier: Programming Language :: Python :: 3.10
42
+ Classifier: Programming Language :: Python :: 3.11
43
+ Classifier: Programming Language :: Python :: 3.12
44
+ Classifier: Programming Language :: Python :: 3.13
45
+ Classifier: Programming Language :: Python :: 3.14
46
+ Classifier: Topic :: Software Development :: Libraries :: Python Modules
47
+ Classifier: Topic :: System :: Distributed Computing
48
+ Requires-Python: >=3.8
49
+ Description-Content-Type: text/markdown
50
+ License-File: LICENSE
51
+ Provides-Extra: examples
52
+ Requires-Dist: flask>=2; extra == "examples"
53
+ Requires-Dist: grpcio>=1.48; extra == "examples"
54
+ Requires-Dist: grpcio-tools>=1.48; extra == "examples"
55
+ Requires-Dist: protobuf>=3.20; extra == "examples"
56
+ Requires-Dist: requests>=2; extra == "examples"
57
+ Dynamic: license-file
58
+
59
+ # taskflow-tr
60
+
61
+ taskflow-tr 将一小部分 Python 函数编译成静态 `GraphIR`,可打印计算图,也可使用串行、线程池或进程池执行。PyPI 发行名是 `taskflow-tr`,Python 导入名是 `task_flow`。
62
+
63
+ ## 环境与安装
64
+
65
+ 项目最低支持 Python 3.8。通过 PyPI 安装核心包:
66
+
67
+ ```bash
68
+ pip install taskflow-tr
69
+ ```
70
+
71
+ 如需运行 README 中的 HTTP 和 gRPC 集成示例:
72
+
73
+ ```bash
74
+ pip install "taskflow-tr[examples]"
75
+ ```
76
+
77
+ 项目开发环境使用 [uv](https://docs.astral.sh/uv/) 管理:
78
+
79
+ ```bash
80
+ uv sync --all-groups
81
+ ```
82
+
83
+ ## 直接执行函数
84
+
85
+ `@transform` 默认使用 `InlineExecutor`:
86
+
87
+ ```python
88
+ from task_flow import transform
89
+
90
+
91
+ @transform
92
+ def add(a, b):
93
+ return a + b
94
+
95
+
96
+ assert add(2, b=1) == 3
97
+ ```
98
+
99
+ 显式使用线程池或进程池时必须指定工作数量:
100
+
101
+ ```python
102
+ @transform(executor="thread", workers=4)
103
+ def threaded_add(a, b):
104
+ return a + b
105
+
106
+
107
+ @transform(executor="process", workers=4)
108
+ def process_add(a, b):
109
+ return a + b
110
+ ```
111
+
112
+ `@transform()` 是非法形式;带括号时必须显式传入 `executor`。
113
+
114
+ ## 编译和打印 GraphIR
115
+
116
+ `@compile` 只编译函数,不绑定执行策略。`print()` 默认输出 JSON:
117
+
118
+ ```python
119
+ from task_flow import compile
120
+
121
+
122
+ @compile
123
+ def add(a, b):
124
+ return a + b
125
+
126
+
127
+ print(add)
128
+ print(format(add, "dict"))
129
+ print(format(add, "mermaid"))
130
+ print(format(add, "graphviz"))
131
+ ```
132
+
133
+ 也可以在装饰时改变默认打印格式:
134
+
135
+ ```python
136
+ @compile(format="mermaid")
137
+ def workflow(a, b):
138
+ return a + b
139
+
140
+
141
+ print(workflow)
142
+ ```
143
+
144
+ 支持 `dict`、`json`、`mermaid` 和 `graphviz` 四种格式。Graphviz 格式返回 DOT 源码,不要求 Runtime 安装 Graphviz。
145
+
146
+ `@compile()` 是非法形式;带括号时必须显式传入 `format`。
147
+
148
+ ## 显式选择 Executor
149
+
150
+ 编译结果可以被不同 Executor 重复执行,无需重新编译:
151
+
152
+ ```python
153
+ from task_flow import InlineExecutor, ProcessExecutor, ThreadExecutor
154
+
155
+
156
+ with InlineExecutor() as executor:
157
+ assert executor.run(add, args=(2,), kwargs={"b": 1}) == 3
158
+
159
+ with ThreadExecutor(thread_num=4) as executor:
160
+ assert executor.run(add, args=(2, 1)) == 3
161
+
162
+ with ProcessExecutor(process_num=4) as executor:
163
+ assert executor.run(add, args=(2, 1)) == 3
164
+ ```
165
+
166
+ 线程执行适合 I/O 或会释放 GIL 的扩展调用;进程执行适合 CPU 密集型 Python 代码。进程池中的调用函数与参数必须能被 `pickle` 序列化,应优先使用模块顶层命名函数,避免 lambda 和局部函数。
167
+
168
+ ## 完整示例
169
+
170
+ ### 并行计算与 Graphviz 输出
171
+
172
+ 下面的计算图包含四个相互独立的运算节点,线程 Executor 可以并发执行它们:
173
+
174
+ ```python
175
+ import time
176
+ from operator import add, floordiv, mul, sub
177
+
178
+ from task_flow import compile, transform
179
+
180
+
181
+ def delayed(operation, x, y):
182
+ time.sleep(0.1)
183
+ return operation(x, y)
184
+
185
+
186
+ def add0(x, y):
187
+ return delayed(add, x, y)
188
+
189
+
190
+ def sub0(x, y):
191
+ return delayed(sub, x, y)
192
+
193
+
194
+ def mul0(x, y):
195
+ return delayed(mul, x, y)
196
+
197
+
198
+ def div0(x, y):
199
+ return delayed(floordiv, x, y)
200
+
201
+
202
+ @transform(executor="thread", workers=4)
203
+ def compute_graph(a, b):
204
+ result_add = add0(a, b)
205
+ result_sub = sub0(a, b)
206
+ result_mul = mul0(a, b)
207
+ result_div = div0(a, b)
208
+ return result_add, result_sub, result_mul, result_div
209
+
210
+
211
+ assert compute_graph(2, 1) == (3, 1, 2, 2)
212
+
213
+
214
+ @compile(format="graphviz")
215
+ def printable_graph(a, b):
216
+ result_add = a + b
217
+ result_sub = a - b
218
+ result_mul = a * b
219
+ result_div = a // b
220
+ return result_add, result_sub, result_mul, result_div
221
+
222
+
223
+ print(printable_graph) # 输出 DOT 源码
224
+ ```
225
+
226
+ ### 集成 HTTP 服务
227
+
228
+ HTTP 和 gRPC 只是 `TransformedFunction` 的调用入口,调度逻辑仍由 taskflow-tr 管理。安装示例依赖:
229
+
230
+ ```bash
231
+ uv sync --extra examples
232
+ ```
233
+
234
+ 使用 Flask 暴露计算接口:
235
+
236
+ ```python
237
+ from flask import Flask, jsonify, request
238
+
239
+
240
+ app = Flask(__name__)
241
+
242
+
243
+ @app.post("/compute")
244
+ def compute():
245
+ inputs = request.get_json()
246
+ x, y, z, w = compute_graph(inputs["x"], inputs["y"])
247
+ return jsonify({"x": x, "y": y, "z": z, "w": w})
248
+
249
+
250
+ if __name__ == "__main__":
251
+ app.run(host="0.0.0.0", port=8000)
252
+ ```
253
+
254
+ 请求示例:
255
+
256
+ ```python
257
+ import requests
258
+
259
+
260
+ response = requests.post(
261
+ "http://127.0.0.1:8000/compute",
262
+ json={"x": 2, "y": 1},
263
+ timeout=30,
264
+ )
265
+ assert response.json() == {"x": 3, "y": 1, "z": 2, "w": 2}
266
+ ```
267
+
268
+ ### 集成 gRPC 服务
269
+
270
+ 先定义 `compute.proto`:
271
+
272
+ ```proto
273
+ syntax = "proto3";
274
+ package example;
275
+
276
+ message Inputs {
277
+ int32 x = 1;
278
+ int32 y = 2;
279
+ }
280
+
281
+ message Outputs {
282
+ int32 x = 1;
283
+ int32 y = 2;
284
+ int32 z = 3;
285
+ int32 w = 4;
286
+ }
287
+
288
+ service App {
289
+ rpc Compute (Inputs) returns (Outputs);
290
+ }
291
+ ```
292
+
293
+ 生成 Python 代码:
294
+
295
+ ```bash
296
+ uv run python -m grpc_tools.protoc \
297
+ -I. \
298
+ --python_out=. \
299
+ --grpc_python_out=. \
300
+ compute.proto
301
+ ```
302
+
303
+ 在生成的服务接口中调用同一个 `compute_graph`:
304
+
305
+ ```python
306
+ from concurrent import futures
307
+
308
+ import grpc
309
+ import compute_pb2
310
+ import compute_pb2_grpc
311
+
312
+
313
+ class App(compute_pb2_grpc.AppServicer):
314
+ def Compute(self, inputs, context):
315
+ x, y, z, w = compute_graph(inputs.x, inputs.y)
316
+ return compute_pb2.Outputs(x=x, y=y, z=z, w=w)
317
+
318
+
319
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=3))
320
+ compute_pb2_grpc.add_AppServicer_to_server(App(), server)
321
+ server.add_insecure_port("0.0.0.0:8000")
322
+ server.start()
323
+ server.wait_for_termination()
324
+ ```
325
+
326
+ ## V1 编译范围
327
+
328
+ V1 支持普通位置或关键字参数、常量、简单赋值、普通函数调用、`+`、`-`、`*`、`/`、`//`,以及 `None`、单值、tuple 和 list 返回。条件、循环、递归、可变参数、默认参数和关键字调用参数尚未纳入 V1。
329
+
330
+ 总体流程:
331
+
332
+ ```text
333
+ Python Source -> Python AST -> GraphIR -> Executor -> Result
334
+ |
335
+ +-> Printer -> dict / JSON / Mermaid / Graphviz
336
+ ```
337
+
338
+ V1 不包含 Planner、ExecutablePlanIR、Dask、Ray 或 MPI 后端。设计说明见 [`docs/v1/dev.md`](docs/v1/dev.md)。
339
+
340
+ ## 开发
341
+
342
+ ```bash
343
+ uv run pytest
344
+ uv run python -m benchmarks.benchmark_executor
345
+ ```
@@ -0,0 +1,287 @@
1
+ # taskflow-tr
2
+
3
+ taskflow-tr 将一小部分 Python 函数编译成静态 `GraphIR`,可打印计算图,也可使用串行、线程池或进程池执行。PyPI 发行名是 `taskflow-tr`,Python 导入名是 `task_flow`。
4
+
5
+ ## 环境与安装
6
+
7
+ 项目最低支持 Python 3.8。通过 PyPI 安装核心包:
8
+
9
+ ```bash
10
+ pip install taskflow-tr
11
+ ```
12
+
13
+ 如需运行 README 中的 HTTP 和 gRPC 集成示例:
14
+
15
+ ```bash
16
+ pip install "taskflow-tr[examples]"
17
+ ```
18
+
19
+ 项目开发环境使用 [uv](https://docs.astral.sh/uv/) 管理:
20
+
21
+ ```bash
22
+ uv sync --all-groups
23
+ ```
24
+
25
+ ## 直接执行函数
26
+
27
+ `@transform` 默认使用 `InlineExecutor`:
28
+
29
+ ```python
30
+ from task_flow import transform
31
+
32
+
33
+ @transform
34
+ def add(a, b):
35
+ return a + b
36
+
37
+
38
+ assert add(2, b=1) == 3
39
+ ```
40
+
41
+ 显式使用线程池或进程池时必须指定工作数量:
42
+
43
+ ```python
44
+ @transform(executor="thread", workers=4)
45
+ def threaded_add(a, b):
46
+ return a + b
47
+
48
+
49
+ @transform(executor="process", workers=4)
50
+ def process_add(a, b):
51
+ return a + b
52
+ ```
53
+
54
+ `@transform()` 是非法形式;带括号时必须显式传入 `executor`。
55
+
56
+ ## 编译和打印 GraphIR
57
+
58
+ `@compile` 只编译函数,不绑定执行策略。`print()` 默认输出 JSON:
59
+
60
+ ```python
61
+ from task_flow import compile
62
+
63
+
64
+ @compile
65
+ def add(a, b):
66
+ return a + b
67
+
68
+
69
+ print(add)
70
+ print(format(add, "dict"))
71
+ print(format(add, "mermaid"))
72
+ print(format(add, "graphviz"))
73
+ ```
74
+
75
+ 也可以在装饰时改变默认打印格式:
76
+
77
+ ```python
78
+ @compile(format="mermaid")
79
+ def workflow(a, b):
80
+ return a + b
81
+
82
+
83
+ print(workflow)
84
+ ```
85
+
86
+ 支持 `dict`、`json`、`mermaid` 和 `graphviz` 四种格式。Graphviz 格式返回 DOT 源码,不要求 Runtime 安装 Graphviz。
87
+
88
+ `@compile()` 是非法形式;带括号时必须显式传入 `format`。
89
+
90
+ ## 显式选择 Executor
91
+
92
+ 编译结果可以被不同 Executor 重复执行,无需重新编译:
93
+
94
+ ```python
95
+ from task_flow import InlineExecutor, ProcessExecutor, ThreadExecutor
96
+
97
+
98
+ with InlineExecutor() as executor:
99
+ assert executor.run(add, args=(2,), kwargs={"b": 1}) == 3
100
+
101
+ with ThreadExecutor(thread_num=4) as executor:
102
+ assert executor.run(add, args=(2, 1)) == 3
103
+
104
+ with ProcessExecutor(process_num=4) as executor:
105
+ assert executor.run(add, args=(2, 1)) == 3
106
+ ```
107
+
108
+ 线程执行适合 I/O 或会释放 GIL 的扩展调用;进程执行适合 CPU 密集型 Python 代码。进程池中的调用函数与参数必须能被 `pickle` 序列化,应优先使用模块顶层命名函数,避免 lambda 和局部函数。
109
+
110
+ ## 完整示例
111
+
112
+ ### 并行计算与 Graphviz 输出
113
+
114
+ 下面的计算图包含四个相互独立的运算节点,线程 Executor 可以并发执行它们:
115
+
116
+ ```python
117
+ import time
118
+ from operator import add, floordiv, mul, sub
119
+
120
+ from task_flow import compile, transform
121
+
122
+
123
+ def delayed(operation, x, y):
124
+ time.sleep(0.1)
125
+ return operation(x, y)
126
+
127
+
128
+ def add0(x, y):
129
+ return delayed(add, x, y)
130
+
131
+
132
+ def sub0(x, y):
133
+ return delayed(sub, x, y)
134
+
135
+
136
+ def mul0(x, y):
137
+ return delayed(mul, x, y)
138
+
139
+
140
+ def div0(x, y):
141
+ return delayed(floordiv, x, y)
142
+
143
+
144
+ @transform(executor="thread", workers=4)
145
+ def compute_graph(a, b):
146
+ result_add = add0(a, b)
147
+ result_sub = sub0(a, b)
148
+ result_mul = mul0(a, b)
149
+ result_div = div0(a, b)
150
+ return result_add, result_sub, result_mul, result_div
151
+
152
+
153
+ assert compute_graph(2, 1) == (3, 1, 2, 2)
154
+
155
+
156
+ @compile(format="graphviz")
157
+ def printable_graph(a, b):
158
+ result_add = a + b
159
+ result_sub = a - b
160
+ result_mul = a * b
161
+ result_div = a // b
162
+ return result_add, result_sub, result_mul, result_div
163
+
164
+
165
+ print(printable_graph) # 输出 DOT 源码
166
+ ```
167
+
168
+ ### 集成 HTTP 服务
169
+
170
+ HTTP 和 gRPC 只是 `TransformedFunction` 的调用入口,调度逻辑仍由 taskflow-tr 管理。安装示例依赖:
171
+
172
+ ```bash
173
+ uv sync --extra examples
174
+ ```
175
+
176
+ 使用 Flask 暴露计算接口:
177
+
178
+ ```python
179
+ from flask import Flask, jsonify, request
180
+
181
+
182
+ app = Flask(__name__)
183
+
184
+
185
+ @app.post("/compute")
186
+ def compute():
187
+ inputs = request.get_json()
188
+ x, y, z, w = compute_graph(inputs["x"], inputs["y"])
189
+ return jsonify({"x": x, "y": y, "z": z, "w": w})
190
+
191
+
192
+ if __name__ == "__main__":
193
+ app.run(host="0.0.0.0", port=8000)
194
+ ```
195
+
196
+ 请求示例:
197
+
198
+ ```python
199
+ import requests
200
+
201
+
202
+ response = requests.post(
203
+ "http://127.0.0.1:8000/compute",
204
+ json={"x": 2, "y": 1},
205
+ timeout=30,
206
+ )
207
+ assert response.json() == {"x": 3, "y": 1, "z": 2, "w": 2}
208
+ ```
209
+
210
+ ### 集成 gRPC 服务
211
+
212
+ 先定义 `compute.proto`:
213
+
214
+ ```proto
215
+ syntax = "proto3";
216
+ package example;
217
+
218
+ message Inputs {
219
+ int32 x = 1;
220
+ int32 y = 2;
221
+ }
222
+
223
+ message Outputs {
224
+ int32 x = 1;
225
+ int32 y = 2;
226
+ int32 z = 3;
227
+ int32 w = 4;
228
+ }
229
+
230
+ service App {
231
+ rpc Compute (Inputs) returns (Outputs);
232
+ }
233
+ ```
234
+
235
+ 生成 Python 代码:
236
+
237
+ ```bash
238
+ uv run python -m grpc_tools.protoc \
239
+ -I. \
240
+ --python_out=. \
241
+ --grpc_python_out=. \
242
+ compute.proto
243
+ ```
244
+
245
+ 在生成的服务接口中调用同一个 `compute_graph`:
246
+
247
+ ```python
248
+ from concurrent import futures
249
+
250
+ import grpc
251
+ import compute_pb2
252
+ import compute_pb2_grpc
253
+
254
+
255
+ class App(compute_pb2_grpc.AppServicer):
256
+ def Compute(self, inputs, context):
257
+ x, y, z, w = compute_graph(inputs.x, inputs.y)
258
+ return compute_pb2.Outputs(x=x, y=y, z=z, w=w)
259
+
260
+
261
+ server = grpc.server(futures.ThreadPoolExecutor(max_workers=3))
262
+ compute_pb2_grpc.add_AppServicer_to_server(App(), server)
263
+ server.add_insecure_port("0.0.0.0:8000")
264
+ server.start()
265
+ server.wait_for_termination()
266
+ ```
267
+
268
+ ## V1 编译范围
269
+
270
+ V1 支持普通位置或关键字参数、常量、简单赋值、普通函数调用、`+`、`-`、`*`、`/`、`//`,以及 `None`、单值、tuple 和 list 返回。条件、循环、递归、可变参数、默认参数和关键字调用参数尚未纳入 V1。
271
+
272
+ 总体流程:
273
+
274
+ ```text
275
+ Python Source -> Python AST -> GraphIR -> Executor -> Result
276
+ |
277
+ +-> Printer -> dict / JSON / Mermaid / Graphviz
278
+ ```
279
+
280
+ V1 不包含 Planner、ExecutablePlanIR、Dask、Ray 或 MPI 后端。设计说明见 [`docs/v1/dev.md`](docs/v1/dev.md)。
281
+
282
+ ## 开发
283
+
284
+ ```bash
285
+ uv run pytest
286
+ uv run python -m benchmarks.benchmark_executor
287
+ ```
@@ -0,0 +1,57 @@
1
+ [build-system]
2
+ requires = ["setuptools>=61"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "taskflow-tr"
7
+ version = "0.1.0"
8
+ description = "Compile Python functions into GraphIR DAGs and execute them inline, with threads, or with processes."
9
+ readme = "README.md"
10
+ license = {file = "LICENSE"}
11
+ requires-python = ">=3.8"
12
+ authors = [{name = "gaoxinge", email = "gaoxx5@gmail.com"}]
13
+ maintainers = [{name = "gaoxinge", email = "gaoxx5@gmail.com"}]
14
+ keywords = ["dag", "graph-ir", "workflow", "concurrency", "threading", "multiprocessing"]
15
+ classifiers = [
16
+ "Development Status :: 3 - Alpha",
17
+ "Intended Audience :: Developers",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Operating System :: OS Independent",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.8",
22
+ "Programming Language :: Python :: 3.9",
23
+ "Programming Language :: Python :: 3.10",
24
+ "Programming Language :: Python :: 3.11",
25
+ "Programming Language :: Python :: 3.12",
26
+ "Programming Language :: Python :: 3.13",
27
+ "Programming Language :: Python :: 3.14",
28
+ "Topic :: Software Development :: Libraries :: Python Modules",
29
+ "Topic :: System :: Distributed Computing",
30
+ ]
31
+ dependencies = []
32
+
33
+ [project.optional-dependencies]
34
+ examples = ["flask>=2", "grpcio>=1.48", "grpcio-tools>=1.48", "protobuf>=3.20", "requests>=2"]
35
+
36
+ [project.urls]
37
+ Homepage = "https://github.com/gaoxinge/task_flow"
38
+ Repository = "https://github.com/gaoxinge/task_flow"
39
+ Issues = "https://github.com/gaoxinge/task_flow/issues"
40
+ Documentation = "https://github.com/gaoxinge/task_flow#readme"
41
+
42
+ [dependency-groups]
43
+ dev = ["pytest>=7,<8.4", "ruff>=0.6"]
44
+
45
+ [tool.pytest.ini_options]
46
+ testpaths = ["tests"]
47
+ addopts = "-ra --capture=no"
48
+
49
+ [tool.setuptools.packages.find]
50
+ include = ["task_flow*"]
51
+
52
+ [tool.ruff]
53
+ target-version = "py38"
54
+ line-length = 100
55
+
56
+ [tool.ruff.lint]
57
+ select = ["E", "F", "I"]
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+