bump version to 0.2.2
Release / Pre-release Check (push) Failing after 30s
Release / Build Artifacts (push) Has been skipped
Release / Publish to PyPI (push) Has been skipped
Release / Publish Release (push) Has been skipped

This commit is contained in:
2026-06-26 01:50:49 +08:00
parent 9285ae3782
commit 1eb7942aa9
5 changed files with 67 additions and 100 deletions
+1 -1
View File
@@ -17,7 +17,7 @@ license = { text = "MIT" }
name = "pyflowx"
readme = "README.md"
requires-python = ">=3.8"
version = "0.2.1"
version = "0.2.2"
[project.scripts]
autofmt = "pyflowx.cli.autofmt:main"
+1 -1
View File
@@ -84,7 +84,7 @@ from .runner import CliExitCode, CliRunner
from .storage import JSONBackend, MemoryBackend, StateBackend
from .task import TaskCmd, TaskEvent, TaskResult, TaskSpec, TaskStatus
__version__ = "0.2.1"
__version__ = "0.2.2"
__all__ = [
"IS_LINUX",
+1 -1
View File
@@ -41,7 +41,7 @@ test_coverage: px.TaskSpec = px.TaskSpec(
ruff_lint: px.TaskSpec = px.TaskSpec("lint", cmd=["ruff", "check", "--fix", "--unsafe-fixes"])
typecheck: px.TaskSpec = px.TaskSpec("pyrefly_check", cmd=["pyrefly", "check", "."])
git_add_all: px.TaskSpec = px.TaskSpec("git_add_all", cmd=["git", "add", "-A"])
bump: px.TaskSpec = px.TaskSpec("bumpversion", cmd=["bumpversion", "-t"])
bump: px.TaskSpec = px.TaskSpec("bumpversion", cmd=["bumpversion"])
doc: px.TaskSpec = px.TaskSpec("doc", cmd=["sphinx-build", "-b", "html", "docs", "docs/_build"])
git_push: px.TaskSpec = px.TaskSpec("git_push", cmd=["git", "push"])
git_push_tags: px.TaskSpec = px.TaskSpec("git_push_tags", cmd=["git", "push", "--tags"])
+1 -1
View File
@@ -215,7 +215,7 @@ class TestInstallEmbedPython:
packtool.install_embed_python("3.10", output_dir)
# Verify cache directory was created (now in tmp_path)
cache_dir = Path(packtool.DEFAULT_CACHE_DIR)
Path(packtool.DEFAULT_CACHE_DIR)
# Note: In test environment, cache might not persist due to mocking
+31 -64
View File
@@ -26,12 +26,10 @@ def test_sequential_basic() -> None:
def double(extract: list[int]) -> list[int]:
return [x * 2 for x in extract]
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("extract", extract),
px.TaskSpec("double", double, depends_on=("extract",)),
]
)
])
report = px.run(graph, strategy="sequential")
assert report.success
assert report["extract"] == [1, 2, 3]
@@ -48,14 +46,12 @@ def test_sequential_diamond() -> None:
return fn
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("a", make("a")),
px.TaskSpec("b", make("b"), depends_on=("a",)),
px.TaskSpec("c", make("c"), depends_on=("a",)),
px.TaskSpec("d", make("d"), depends_on=("b", "c")),
]
)
])
report = px.run(graph, strategy="sequential")
assert report.success
assert report["d"] == "d"
@@ -69,12 +65,10 @@ def test_failure_propagates() -> None:
def downstream(_boom: None) -> int:
return 1
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("boom", boom),
px.TaskSpec("downstream", downstream, depends_on=("boom",)),
]
)
])
with pytest.raises(TaskFailedError) as exc_info:
_ = px.run(graph, strategy="sequential")
assert exc_info.value.task == "boom"
@@ -116,13 +110,11 @@ def test_threaded_parallelism() -> None:
time.sleep(0.3)
return "done"
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("a", slow),
px.TaskSpec("b", slow),
px.TaskSpec("c", slow),
]
)
])
start = time.time()
report = px.run(graph, strategy="thread", max_workers=3)
elapsed = time.time() - start
@@ -145,13 +137,11 @@ def test_threaded_layer_barrier() -> None:
return fn
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("a", make("a")),
px.TaskSpec("b", make("b")),
px.TaskSpec("c", make("c"), depends_on=("a", "b")),
]
)
])
report = px.run(graph, strategy="thread", max_workers=2)
assert report.success
# c must finish after both a and b.
@@ -170,12 +160,10 @@ def test_async_basic() -> None:
async def transform(fetch: int) -> int:
return fetch * 2
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("fetch", fetch),
px.TaskSpec("transform", transform, depends_on=("fetch",)),
]
)
])
report = px.run(graph, strategy="async")
assert report.success
assert report["transform"] == 84
@@ -187,18 +175,13 @@ def test_async_parallelism() -> None:
await asyncio.sleep(0.3)
return "done"
graph = px.Graph.from_specs(
[
px.TaskSpec("a", slow),
px.TaskSpec("b", slow),
px.TaskSpec("c", slow),
]
)
graph = px.Graph.from_specs([px.TaskSpec("a", slow), px.TaskSpec("b", slow), px.TaskSpec("c", slow)])
start = time.time()
report = px.run(graph, strategy="async")
elapsed = time.time() - start
assert report.success
assert elapsed < 0.8
# 放宽时间限制以应对 CI 环境波动(理想 0.3s,串行约 0.9s,上限 1.5s 确保并行有效性)
assert elapsed < 1.5
def test_async_mixed_sync_and_async() -> None:
@@ -209,12 +192,10 @@ def test_async_mixed_sync_and_async() -> None:
await asyncio.sleep(0.01)
return sync_task + 5
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("sync_task", sync_task),
px.TaskSpec("async_task", async_task, depends_on=("sync_task",)),
]
)
])
report = px.run(graph, strategy="async")
assert report.success
assert report["async_task"] == 15
@@ -262,12 +243,10 @@ def test_memory_backend_resume() -> None:
return fn
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("a", make("a")),
px.TaskSpec("b", make("b"), depends_on=("a",)),
]
)
])
backend = MemoryBackend()
_ = px.run(graph, strategy="sequential", state=backend)
assert runs == ["a", "b"]
@@ -393,12 +372,10 @@ def test_threaded_skips_cached_tasks() -> None:
return fn
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("a", make("a")),
px.TaskSpec("b", make("b"), depends_on=("a",)),
]
)
])
backend = px.MemoryBackend()
# 第一次运行填充缓存
_ = px.run(graph, strategy="thread", max_workers=2, state=backend)
@@ -438,12 +415,10 @@ def test_async_skips_cached_tasks() -> None:
runs.append("b")
return a + "b"
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("a", a),
px.TaskSpec("b", b, depends_on=("a",)),
]
)
])
backend = px.MemoryBackend()
_ = px.run(graph, strategy="async", state=backend)
assert runs == ["a", "b"]
@@ -519,12 +494,10 @@ def test_downstream_skipped_when_upstream_skipped_sequential() -> None:
def downstream(upstream: str) -> str:
return upstream + "_processed"
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("upstream", cmd=["echo", "hello"], conditions=(never_true,)),
px.TaskSpec("downstream", downstream, depends_on=("upstream",)),
]
)
])
report = px.run(graph, strategy="sequential")
assert report.success
assert report.result_of("upstream").status == px.TaskStatus.SKIPPED
@@ -538,12 +511,10 @@ def test_downstream_skipped_when_upstream_skipped_thread() -> None:
def downstream(upstream: str) -> str:
return upstream + "_processed"
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("upstream", cmd=["echo", "hello"], conditions=(never_true,)),
px.TaskSpec("downstream", downstream, depends_on=("upstream",)),
]
)
])
report = px.run(graph, strategy="thread", max_workers=2)
assert report.success
assert report.result_of("upstream").status == px.TaskStatus.SKIPPED
@@ -561,12 +532,10 @@ def test_downstream_skipped_when_upstream_skipped_async() -> None:
never_true = lambda: False # noqa: E731
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("upstream", upstream, conditions=(never_true,)),
px.TaskSpec("downstream", downstream, depends_on=("upstream",)),
]
)
])
report = px.run(graph, strategy="async")
assert report.success
assert report.result_of("upstream").status == px.TaskStatus.SKIPPED
@@ -583,12 +552,10 @@ def test_downstream_executes_when_upstream_succeeds() -> None:
def downstream(upstream: str) -> str:
return upstream + "_processed"
graph = px.Graph.from_specs(
[
graph = px.Graph.from_specs([
px.TaskSpec("upstream", upstream, conditions=(always_true,)),
px.TaskSpec("downstream", downstream, depends_on=("upstream",)),
]
)
])
report = px.run(graph, strategy="sequential")
assert report.success
assert report.result_of("upstream").status == px.TaskStatus.SUCCESS