wt-task 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.
Files changed (36) hide show
  1. wt_task-0.1.0/PKG-INFO +200 -0
  2. wt_task-0.1.0/README.md +176 -0
  3. wt_task-0.1.0/pyproject.toml +143 -0
  4. wt_task-0.1.0/setup.cfg +4 -0
  5. wt_task-0.1.0/src/wt_task/__init__.py +54 -0
  6. wt_task-0.1.0/src/wt_task/_version.py +34 -0
  7. wt_task-0.1.0/src/wt_task/async_task.py +158 -0
  8. wt_task-0.1.0/src/wt_task/base.py +326 -0
  9. wt_task-0.1.0/src/wt_task/decorator.py +121 -0
  10. wt_task-0.1.0/src/wt_task/exceptions.py +97 -0
  11. wt_task-0.1.0/src/wt_task/executors/__init__.py +16 -0
  12. wt_task-0.1.0/src/wt_task/executors/base.py +221 -0
  13. wt_task-0.1.0/src/wt_task/executors/python.py +55 -0
  14. wt_task-0.1.0/src/wt_task/py.typed +0 -0
  15. wt_task-0.1.0/src/wt_task/skip.py +147 -0
  16. wt_task-0.1.0/src/wt_task/sync_task.py +389 -0
  17. wt_task-0.1.0/src/wt_task/testing.py +224 -0
  18. wt_task-0.1.0/src/wt_task/tracing/__init__.py +24 -0
  19. wt_task-0.1.0/src/wt_task/tracing/_config.py +203 -0
  20. wt_task-0.1.0/src/wt_task/tracing/_decorator.py +58 -0
  21. wt_task-0.1.0/src/wt_task.egg-info/PKG-INFO +200 -0
  22. wt_task-0.1.0/src/wt_task.egg-info/SOURCES.txt +34 -0
  23. wt_task-0.1.0/src/wt_task.egg-info/dependency_links.txt +1 -0
  24. wt_task-0.1.0/src/wt_task.egg-info/requires.txt +10 -0
  25. wt_task-0.1.0/src/wt_task.egg-info/top_level.txt +1 -0
  26. wt_task-0.1.0/tests/test_decorator.py +107 -0
  27. wt_task-0.1.0/tests/test_exceptions.py +148 -0
  28. wt_task-0.1.0/tests/test_executors.py +155 -0
  29. wt_task-0.1.0/tests/test_map.py +137 -0
  30. wt_task-0.1.0/tests/test_mapvalues.py +138 -0
  31. wt_task-0.1.0/tests/test_partial.py +117 -0
  32. wt_task-0.1.0/tests/test_skip.py +158 -0
  33. wt_task-0.1.0/tests/test_testing.py +198 -0
  34. wt_task-0.1.0/tests/test_tracing.py +19 -0
  35. wt_task-0.1.0/tests/test_validation.py +175 -0
  36. wt_task-0.1.0/uv.lock +1093 -0
wt_task-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,200 @@
1
+ Metadata-Version: 2.4
2
+ Name: wt-task
3
+ Version: 0.1.0
4
+ Summary: Task decorator and execution features for wt ecosystem
5
+ Author: Ecoscope Workflows Team
6
+ License: Apache-2.0
7
+ Keywords: workflow,task,execution,decorator
8
+ Classifier: Development Status :: 3 - Alpha
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: License :: OSI Approved :: Apache Software License
11
+ Classifier: Programming Language :: Python :: 3
12
+ Classifier: Programming Language :: Python :: 3.10
13
+ Classifier: Programming Language :: Python :: 3.11
14
+ Classifier: Programming Language :: Python :: 3.12
15
+ Requires-Python: >=3.10
16
+ Description-Content-Type: text/markdown
17
+ Requires-Dist: wt-contracts<1.0.0,>=0.1.0
18
+ Requires-Dist: pydantic<3.0.0,>=2.0.0
19
+ Requires-Dist: typing-extensions>=4.0.0; python_version < "3.11"
20
+ Provides-Extra: gcp
21
+ Requires-Dist: opentelemetry-api>=1.20.0; extra == "gcp"
22
+ Requires-Dist: opentelemetry-sdk>=1.20.0; extra == "gcp"
23
+ Requires-Dist: opentelemetry-exporter-gcp-trace>=1.6.0; extra == "gcp"
24
+
25
+ # wt-task
26
+
27
+ Task decorator and execution features for the wt ecosystem.
28
+
29
+ ## Overview
30
+
31
+ `wt-task` provides the `@task` decorator and task execution capabilities for workflow systems. It implements the `TaskProtocol` from `wt-contracts`, enabling type-safe task execution across the wt ecosystem.
32
+
33
+ ## Features
34
+
35
+ - **Dual-purpose `task` decorator**: Works as both a decorator (`@task`) and wrapper function (`task(func)`)
36
+ - **Execution methods**: `call`, `map`, `mapvalues` for different execution patterns
37
+ - **Partial application**: Bind arguments with `.partial()` before execution
38
+ - **Validation**: Pydantic-based validation with `.validate()`
39
+ - **Error handling**: Wrap errors with task instance context
40
+ - **Conditional skipping**: Skip execution based on conditions with `.skipif()`
41
+ - **Custom executors**: Switch execution backends with `.set_executor()`
42
+ - **OpenTelemetry tracing**: Optional tracing support (requires `wt-task[gcp]`)
43
+
44
+ ## Installation
45
+
46
+ ```bash
47
+ # Basic installation
48
+ pip install wt-task
49
+
50
+ # With tracing support
51
+ pip install wt-task[gcp]
52
+
53
+ # Development installation
54
+ cd wt/wt-task
55
+ uv sync
56
+ ```
57
+
58
+ ## Usage
59
+
60
+ ### Basic Task Definition
61
+
62
+ ```python
63
+ from wt_task import task
64
+
65
+ @task
66
+ def add(a: int, b: int) -> int:
67
+ return a + b
68
+
69
+ # Direct call
70
+ result = add(1, 2) # 3
71
+
72
+ # Explicit call
73
+ result = add.call(1, 2) # 3
74
+ ```
75
+
76
+ ### Partial Application
77
+
78
+ ```python
79
+ @task
80
+ def multiply(a: int, b: int) -> int:
81
+ return a * b
82
+
83
+ # Bind one argument
84
+ multiply_by_2 = multiply.partial(b=2)
85
+ result = multiply_by_2.call(a=5) # 10
86
+ ```
87
+
88
+ ### Mapping Over Values
89
+
90
+ ```python
91
+ @task
92
+ def square(x: int) -> int:
93
+ return x * x
94
+
95
+ # Map over a sequence
96
+ results = square.map("x", [1, 2, 3, 4]) # [1, 4, 9, 16]
97
+ ```
98
+
99
+ ### Mapping Over Key-Value Pairs
100
+
101
+ ```python
102
+ @task
103
+ def process(data: str) -> int:
104
+ return len(data)
105
+
106
+ # Map over key-value pairs, preserving keys
107
+ results = process.mapvalues("data", [
108
+ ("a", "hello"),
109
+ ("b", "world"),
110
+ ])
111
+ # [("a", 5), ("b", 5)]
112
+ ```
113
+
114
+ ### Validation
115
+
116
+ ```python
117
+ @task
118
+ def add_numbers(a: int, b: int) -> int:
119
+ return a + b
120
+
121
+ # Parse string inputs to ints
122
+ result = add_numbers.validate().call("10", "20") # 30
123
+ ```
124
+
125
+ ### Error Handling
126
+
127
+ ```python
128
+ @task
129
+ def divide(a: int, b: int) -> float:
130
+ return a / b
131
+
132
+ # Add task instance context to errors
133
+ task_with_id = divide.set_task_instance_id("task-1")
134
+ try:
135
+ task_with_id.handle_errors().call(10, 0)
136
+ except TaskInstanceError as e:
137
+ print(e) # Task instance 'task-1' raised ZeroDivisionError(...)
138
+ ```
139
+
140
+ ### Method Chaining
141
+
142
+ All methods return a new task instance, enabling clean method chaining:
143
+
144
+ ```python
145
+ result = (
146
+ add
147
+ .partial(a=10)
148
+ .validate()
149
+ .set_task_instance_id("add-task")
150
+ .handle_errors()
151
+ .call(b="20")
152
+ ) # 30
153
+ ```
154
+
155
+ ## Architecture
156
+
157
+ `wt-task` is designed to work seamlessly with other wt packages:
158
+
159
+ - **wt-contracts**: Implements the `TaskProtocol` interface
160
+ - **wt-compiler**: Generated DAG code uses `task()` wrapper function
161
+ - **wt-registry**: Task functions are registered separately with `@register`
162
+
163
+ ## Development
164
+
165
+ ```bash
166
+ # Create environment and install dependencies
167
+ cd wt/wt-task
168
+ uv sync
169
+
170
+ # Run tests
171
+ uv run pytest
172
+
173
+ # Type checking
174
+ uv run mypy src/
175
+
176
+ # Linting
177
+ uv run ruff check .
178
+
179
+ # Formatting
180
+ uv run ruff format .
181
+ ```
182
+
183
+ ## Testing
184
+
185
+ The package includes comprehensive tests for all features:
186
+
187
+ ```bash
188
+ # Run all tests
189
+ uv run pytest
190
+
191
+ # Run with coverage
192
+ uv run pytest --cov=wt_task --cov-report=html
193
+
194
+ # Run specific test file
195
+ uv run pytest tests/test_decorator.py
196
+ ```
197
+
198
+ ## License
199
+
200
+ Apache-2.0
@@ -0,0 +1,176 @@
1
+ # wt-task
2
+
3
+ Task decorator and execution features for the wt ecosystem.
4
+
5
+ ## Overview
6
+
7
+ `wt-task` provides the `@task` decorator and task execution capabilities for workflow systems. It implements the `TaskProtocol` from `wt-contracts`, enabling type-safe task execution across the wt ecosystem.
8
+
9
+ ## Features
10
+
11
+ - **Dual-purpose `task` decorator**: Works as both a decorator (`@task`) and wrapper function (`task(func)`)
12
+ - **Execution methods**: `call`, `map`, `mapvalues` for different execution patterns
13
+ - **Partial application**: Bind arguments with `.partial()` before execution
14
+ - **Validation**: Pydantic-based validation with `.validate()`
15
+ - **Error handling**: Wrap errors with task instance context
16
+ - **Conditional skipping**: Skip execution based on conditions with `.skipif()`
17
+ - **Custom executors**: Switch execution backends with `.set_executor()`
18
+ - **OpenTelemetry tracing**: Optional tracing support (requires `wt-task[gcp]`)
19
+
20
+ ## Installation
21
+
22
+ ```bash
23
+ # Basic installation
24
+ pip install wt-task
25
+
26
+ # With tracing support
27
+ pip install wt-task[gcp]
28
+
29
+ # Development installation
30
+ cd wt/wt-task
31
+ uv sync
32
+ ```
33
+
34
+ ## Usage
35
+
36
+ ### Basic Task Definition
37
+
38
+ ```python
39
+ from wt_task import task
40
+
41
+ @task
42
+ def add(a: int, b: int) -> int:
43
+ return a + b
44
+
45
+ # Direct call
46
+ result = add(1, 2) # 3
47
+
48
+ # Explicit call
49
+ result = add.call(1, 2) # 3
50
+ ```
51
+
52
+ ### Partial Application
53
+
54
+ ```python
55
+ @task
56
+ def multiply(a: int, b: int) -> int:
57
+ return a * b
58
+
59
+ # Bind one argument
60
+ multiply_by_2 = multiply.partial(b=2)
61
+ result = multiply_by_2.call(a=5) # 10
62
+ ```
63
+
64
+ ### Mapping Over Values
65
+
66
+ ```python
67
+ @task
68
+ def square(x: int) -> int:
69
+ return x * x
70
+
71
+ # Map over a sequence
72
+ results = square.map("x", [1, 2, 3, 4]) # [1, 4, 9, 16]
73
+ ```
74
+
75
+ ### Mapping Over Key-Value Pairs
76
+
77
+ ```python
78
+ @task
79
+ def process(data: str) -> int:
80
+ return len(data)
81
+
82
+ # Map over key-value pairs, preserving keys
83
+ results = process.mapvalues("data", [
84
+ ("a", "hello"),
85
+ ("b", "world"),
86
+ ])
87
+ # [("a", 5), ("b", 5)]
88
+ ```
89
+
90
+ ### Validation
91
+
92
+ ```python
93
+ @task
94
+ def add_numbers(a: int, b: int) -> int:
95
+ return a + b
96
+
97
+ # Parse string inputs to ints
98
+ result = add_numbers.validate().call("10", "20") # 30
99
+ ```
100
+
101
+ ### Error Handling
102
+
103
+ ```python
104
+ @task
105
+ def divide(a: int, b: int) -> float:
106
+ return a / b
107
+
108
+ # Add task instance context to errors
109
+ task_with_id = divide.set_task_instance_id("task-1")
110
+ try:
111
+ task_with_id.handle_errors().call(10, 0)
112
+ except TaskInstanceError as e:
113
+ print(e) # Task instance 'task-1' raised ZeroDivisionError(...)
114
+ ```
115
+
116
+ ### Method Chaining
117
+
118
+ All methods return a new task instance, enabling clean method chaining:
119
+
120
+ ```python
121
+ result = (
122
+ add
123
+ .partial(a=10)
124
+ .validate()
125
+ .set_task_instance_id("add-task")
126
+ .handle_errors()
127
+ .call(b="20")
128
+ ) # 30
129
+ ```
130
+
131
+ ## Architecture
132
+
133
+ `wt-task` is designed to work seamlessly with other wt packages:
134
+
135
+ - **wt-contracts**: Implements the `TaskProtocol` interface
136
+ - **wt-compiler**: Generated DAG code uses `task()` wrapper function
137
+ - **wt-registry**: Task functions are registered separately with `@register`
138
+
139
+ ## Development
140
+
141
+ ```bash
142
+ # Create environment and install dependencies
143
+ cd wt/wt-task
144
+ uv sync
145
+
146
+ # Run tests
147
+ uv run pytest
148
+
149
+ # Type checking
150
+ uv run mypy src/
151
+
152
+ # Linting
153
+ uv run ruff check .
154
+
155
+ # Formatting
156
+ uv run ruff format .
157
+ ```
158
+
159
+ ## Testing
160
+
161
+ The package includes comprehensive tests for all features:
162
+
163
+ ```bash
164
+ # Run all tests
165
+ uv run pytest
166
+
167
+ # Run with coverage
168
+ uv run pytest --cov=wt_task --cov-report=html
169
+
170
+ # Run specific test file
171
+ uv run pytest tests/test_decorator.py
172
+ ```
173
+
174
+ ## License
175
+
176
+ Apache-2.0
@@ -0,0 +1,143 @@
1
+ [build-system]
2
+ requires = ["setuptools>=64", "setuptools-scm>=8"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "wt-task"
7
+ dynamic = ["version"]
8
+ description = "Task decorator and execution features for wt ecosystem"
9
+ readme = "README.md"
10
+ requires-python = ">=3.10"
11
+ license = { text = "Apache-2.0" }
12
+ authors = [
13
+ { name = "Ecoscope Workflows Team" }
14
+ ]
15
+ keywords = ["workflow", "task", "execution", "decorator"]
16
+ classifiers = [
17
+ "Development Status :: 3 - Alpha",
18
+ "Intended Audience :: Developers",
19
+ "License :: OSI Approved :: Apache Software License",
20
+ "Programming Language :: Python :: 3",
21
+ "Programming Language :: Python :: 3.10",
22
+ "Programming Language :: Python :: 3.11",
23
+ "Programming Language :: Python :: 3.12",
24
+ ]
25
+ dependencies = [
26
+ "wt-contracts>=0.1.0,<1.0.0",
27
+ "pydantic>=2.0.0,<3.0.0",
28
+ "typing-extensions>=4.0.0; python_version < '3.11'",
29
+ ]
30
+
31
+ [project.optional-dependencies]
32
+ gcp = [
33
+ "opentelemetry-api>=1.20.0",
34
+ "opentelemetry-sdk>=1.20.0",
35
+ "opentelemetry-exporter-gcp-trace>=1.6.0",
36
+ ]
37
+
38
+ [dependency-groups]
39
+ dev = [
40
+ "pytest>=7.0.0",
41
+ "pytest-cov>=4.0.0",
42
+ "pytest-asyncio>=0.21.0",
43
+ "mypy>=1.0.0",
44
+ "ruff>=0.1.0",
45
+ ]
46
+
47
+ [tool.uv.sources]
48
+ # Development override - uses local editable wt-contracts
49
+ # Published packages will reference PyPI version normally
50
+ wt-contracts = { path = "../wt-contracts", editable = true }
51
+
52
+ [tool.setuptools.packages.find]
53
+ where = ["src"]
54
+
55
+ [tool.setuptools_scm]
56
+ # Version comes from git tags matching this pattern
57
+ tag_regex = "^wt-task/v(?P<version>[0-9.]+)$"
58
+ # Root is the git repository root (parent of wt/)
59
+ root = ".."
60
+ # Generate version file
61
+ version_file = "src/wt_task/_version.py"
62
+ git_describe_command = ["git", "describe", "--dirty", "--tags", "--long", "--match", "wt-task/v*"]
63
+
64
+ [tool.pytest.ini_options]
65
+ testpaths = ["tests"]
66
+ python_files = ["test_*.py"]
67
+ addopts = "--doctest-modules --doctest-continue-on-failure --cov=wt_task --cov-report=term-missing"
68
+
69
+ [tool.mypy]
70
+ python_version = "3.10"
71
+ strict = true
72
+ warn_return_any = true
73
+ warn_unused_configs = true
74
+ disallow_untyped_defs = true
75
+ disallow_any_generics = true
76
+ disallow_subclassing_any = true
77
+ disallow_untyped_calls = true
78
+ disallow_incomplete_defs = true
79
+ check_untyped_defs = true
80
+ no_implicit_optional = true
81
+ warn_redundant_casts = true
82
+ warn_unused_ignores = true
83
+ warn_no_return = true
84
+
85
+ [[tool.mypy.overrides]]
86
+ module = [
87
+ "opentelemetry",
88
+ "opentelemetry.*",
89
+ ]
90
+ ignore_missing_imports = true
91
+
92
+ [[tool.mypy.overrides]]
93
+ module = [
94
+ "wt_task.tracing._config",
95
+ "wt_task.tracing._decorator",
96
+ ]
97
+ warn_unused_ignores = false
98
+
99
+ [tool.ruff]
100
+ line-length = 100
101
+ target-version = "py310"
102
+
103
+ [tool.ruff.lint]
104
+ select = [
105
+ "E", # pycodestyle errors
106
+ "W", # pycodestyle warnings
107
+ "F", # pyflakes
108
+ "I", # isort
109
+ "B", # flake8-bugbear
110
+ "C4", # flake8-comprehensions
111
+ "UP", # pyupgrade
112
+ ]
113
+ ignore = [
114
+ "E501", # line too long (handled by formatter)
115
+ ]
116
+
117
+ [tool.ruff.lint.per-file-ignores]
118
+ "__init__.py" = ["F401"] # unused imports in __init__.py are often intentional
119
+
120
+ # ============================================================================
121
+ # Pixi Build Configuration (conda package building)
122
+ # ============================================================================
123
+
124
+ [tool.pixi.package]
125
+ name = "wt-task"
126
+ version = "0.1.0"
127
+
128
+ [tool.pixi.package.build]
129
+ backend = { name = "pixi-build-python", version = "*", channels = ["conda-forge", "https://prefix.dev/pixi-build-backends"] }
130
+
131
+ [tool.pixi.package.build.config]
132
+ noarch = true
133
+
134
+ [tool.pixi.package.host-dependencies]
135
+ python = ">=3.10,<3.16"
136
+ setuptools = ">=64"
137
+ setuptools-scm = ">=8"
138
+ pip = "*"
139
+
140
+ [tool.pixi.package.run-dependencies]
141
+ python = ">=3.10,<3.16"
142
+ pydantic = ">=2.0.0,<3.0.0"
143
+ wt-contracts = ">=0.1.0,<1.0.0"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,54 @@
1
+ """Task decorator and execution features for wt ecosystem.
2
+
3
+ This package provides the @task decorator and task execution capabilities
4
+ for workflow systems. It implements the TaskProtocol from wt-contracts.
5
+ """
6
+
7
+ from .async_task import AsyncTask
8
+ from .decorator import Task, task
9
+ from .exceptions import TaskInstanceError, handle_errors
10
+ from .executors import (
11
+ AsyncExecutor,
12
+ Future,
13
+ FutureSequence,
14
+ PythonExecutor,
15
+ SyncExecutor,
16
+ )
17
+ from .skip import (
18
+ SKIP_SENTINEL,
19
+ SkippedDependencyFallback,
20
+ SkipSentinel,
21
+ skipif,
22
+ unpack_listlike,
23
+ )
24
+ from .sync_task import SyncTask
25
+
26
+ __all__ = [
27
+ # Main decorator and task types
28
+ "task",
29
+ "Task",
30
+ "SyncTask",
31
+ "AsyncTask",
32
+ # Exceptions
33
+ "TaskInstanceError",
34
+ "handle_errors",
35
+ # Executors
36
+ "SyncExecutor",
37
+ "AsyncExecutor",
38
+ "PythonExecutor",
39
+ "Future",
40
+ "FutureSequence",
41
+ # Skip utilities
42
+ "SkipSentinel",
43
+ "SKIP_SENTINEL",
44
+ "SkippedDependencyFallback",
45
+ "skipif",
46
+ "unpack_listlike",
47
+ ]
48
+
49
+ # Version will be set by setuptools-scm
50
+ try:
51
+ from ._version import __version__, __version_tuple__
52
+ except ImportError:
53
+ __version__ = "0.0.0.dev0"
54
+ __version_tuple__ = (0, 0, 0, "dev0")
@@ -0,0 +1,34 @@
1
+ # file generated by setuptools-scm
2
+ # don't change, don't track in version control
3
+
4
+ __all__ = [
5
+ "__version__",
6
+ "__version_tuple__",
7
+ "version",
8
+ "version_tuple",
9
+ "__commit_id__",
10
+ "commit_id",
11
+ ]
12
+
13
+ TYPE_CHECKING = False
14
+ if TYPE_CHECKING:
15
+ from typing import Tuple
16
+ from typing import Union
17
+
18
+ VERSION_TUPLE = Tuple[Union[int, str], ...]
19
+ COMMIT_ID = Union[str, None]
20
+ else:
21
+ VERSION_TUPLE = object
22
+ COMMIT_ID = object
23
+
24
+ version: str
25
+ __version__: str
26
+ __version_tuple__: VERSION_TUPLE
27
+ version_tuple: VERSION_TUPLE
28
+ commit_id: COMMIT_ID
29
+ __commit_id__: COMMIT_ID
30
+
31
+ __version__ = version = '0.1.0'
32
+ __version_tuple__ = version_tuple = (0, 1, 0)
33
+
34
+ __commit_id__ = commit_id = 'gfa96100'