tasktree 0.0.20__py3-none-any.whl → 0.0.22__py3-none-any.whl
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.
- tasktree/__init__.py +4 -1
- tasktree/cli.py +198 -60
- tasktree/docker.py +105 -64
- tasktree/executor.py +427 -310
- tasktree/graph.py +138 -82
- tasktree/hasher.py +81 -25
- tasktree/parser.py +554 -344
- tasktree/state.py +50 -22
- tasktree/substitution.py +188 -117
- tasktree/types.py +80 -25
- {tasktree-0.0.20.dist-info → tasktree-0.0.22.dist-info}/METADATA +147 -21
- tasktree-0.0.22.dist-info/RECORD +14 -0
- tasktree-0.0.20.dist-info/RECORD +0 -14
- {tasktree-0.0.20.dist-info → tasktree-0.0.22.dist-info}/WHEEL +0 -0
- {tasktree-0.0.20.dist-info → tasktree-0.0.22.dist-info}/entry_points.txt +0 -0
tasktree/types.py
CHANGED
|
@@ -3,14 +3,16 @@
|
|
|
3
3
|
import re
|
|
4
4
|
from datetime import datetime
|
|
5
5
|
from ipaddress import IPv4Address, IPv6Address, ip_address
|
|
6
|
-
from pathlib import Path
|
|
7
6
|
from typing import Any, Optional
|
|
8
7
|
|
|
9
8
|
import click
|
|
10
9
|
|
|
11
10
|
|
|
12
11
|
class HostnameType(click.ParamType):
|
|
13
|
-
"""
|
|
12
|
+
"""
|
|
13
|
+
Validates hostname format (not DNS resolution).
|
|
14
|
+
@athena: 84a721c40458
|
|
15
|
+
"""
|
|
14
16
|
|
|
15
17
|
name = "hostname"
|
|
16
18
|
|
|
@@ -19,7 +21,12 @@ class HostnameType(click.ParamType):
|
|
|
19
21
|
r"^(?=.{1,253}$)(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z0-9-]{1,63})*\.?$"
|
|
20
22
|
)
|
|
21
23
|
|
|
22
|
-
def convert(
|
|
24
|
+
def convert(
|
|
25
|
+
self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
|
|
26
|
+
) -> str:
|
|
27
|
+
"""
|
|
28
|
+
@athena: 8d921e52bcf2
|
|
29
|
+
"""
|
|
23
30
|
if isinstance(value, str):
|
|
24
31
|
if self.HOSTNAME_PATTERN.match(value):
|
|
25
32
|
return value
|
|
@@ -27,16 +34,22 @@ class HostnameType(click.ParamType):
|
|
|
27
34
|
|
|
28
35
|
|
|
29
36
|
class EmailType(click.ParamType):
|
|
30
|
-
"""
|
|
37
|
+
"""
|
|
38
|
+
Validates email format (not deliverability).
|
|
39
|
+
@athena: 95cfacc3f4cd
|
|
40
|
+
"""
|
|
31
41
|
|
|
32
42
|
name = "email"
|
|
33
43
|
|
|
34
44
|
# Basic email validation (RFC 5322 simplified)
|
|
35
|
-
EMAIL_PATTERN = re.compile(
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
45
|
+
EMAIL_PATTERN = re.compile(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
|
|
46
|
+
|
|
47
|
+
def convert(
|
|
48
|
+
self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
|
|
49
|
+
) -> str:
|
|
50
|
+
"""
|
|
51
|
+
@athena: 25046aeb6e6f
|
|
52
|
+
"""
|
|
40
53
|
if isinstance(value, str):
|
|
41
54
|
if self.EMAIL_PATTERN.match(value):
|
|
42
55
|
return value
|
|
@@ -44,11 +57,19 @@ class EmailType(click.ParamType):
|
|
|
44
57
|
|
|
45
58
|
|
|
46
59
|
class IPType(click.ParamType):
|
|
47
|
-
"""
|
|
60
|
+
"""
|
|
61
|
+
Validates IP address (IPv4 or IPv6).
|
|
62
|
+
@athena: dac837bf4894
|
|
63
|
+
"""
|
|
48
64
|
|
|
49
65
|
name = "ip"
|
|
50
66
|
|
|
51
|
-
def convert(
|
|
67
|
+
def convert(
|
|
68
|
+
self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
|
|
69
|
+
) -> str:
|
|
70
|
+
"""
|
|
71
|
+
@athena: d57618e5ad89
|
|
72
|
+
"""
|
|
52
73
|
try:
|
|
53
74
|
ip_address(value)
|
|
54
75
|
return str(value)
|
|
@@ -57,11 +78,19 @@ class IPType(click.ParamType):
|
|
|
57
78
|
|
|
58
79
|
|
|
59
80
|
class IPv4Type(click.ParamType):
|
|
60
|
-
"""
|
|
81
|
+
"""
|
|
82
|
+
Validates IPv4 address.
|
|
83
|
+
@athena: ea5957643fe5
|
|
84
|
+
"""
|
|
61
85
|
|
|
62
86
|
name = "ipv4"
|
|
63
87
|
|
|
64
|
-
def convert(
|
|
88
|
+
def convert(
|
|
89
|
+
self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
|
|
90
|
+
) -> str:
|
|
91
|
+
"""
|
|
92
|
+
@athena: 7ed2d17d1f1a
|
|
93
|
+
"""
|
|
65
94
|
try:
|
|
66
95
|
IPv4Address(value)
|
|
67
96
|
return str(value)
|
|
@@ -70,11 +99,19 @@ class IPv4Type(click.ParamType):
|
|
|
70
99
|
|
|
71
100
|
|
|
72
101
|
class IPv6Type(click.ParamType):
|
|
73
|
-
"""
|
|
102
|
+
"""
|
|
103
|
+
Validates IPv6 address.
|
|
104
|
+
@athena: 9bc5b38d4f23
|
|
105
|
+
"""
|
|
74
106
|
|
|
75
107
|
name = "ipv6"
|
|
76
108
|
|
|
77
|
-
def convert(
|
|
109
|
+
def convert(
|
|
110
|
+
self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
|
|
111
|
+
) -> str:
|
|
112
|
+
"""
|
|
113
|
+
@athena: 4b101e4d54cf
|
|
114
|
+
"""
|
|
78
115
|
try:
|
|
79
116
|
IPv6Address(value)
|
|
80
117
|
return str(value)
|
|
@@ -83,18 +120,30 @@ class IPv6Type(click.ParamType):
|
|
|
83
120
|
|
|
84
121
|
|
|
85
122
|
class DateTimeType(click.ParamType):
|
|
86
|
-
"""
|
|
123
|
+
"""
|
|
124
|
+
Validates datetime in format YYYY-MM-DDTHH:MM:SS.
|
|
125
|
+
@athena: c3bafa3e22e3
|
|
126
|
+
"""
|
|
87
127
|
|
|
88
128
|
name = "datetime"
|
|
89
129
|
|
|
90
|
-
def convert(
|
|
130
|
+
def convert(
|
|
131
|
+
self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
|
|
132
|
+
) -> str:
|
|
133
|
+
"""
|
|
134
|
+
@athena: 13fa66adfe94
|
|
135
|
+
"""
|
|
91
136
|
if isinstance(value, str):
|
|
92
137
|
try:
|
|
93
138
|
datetime.fromisoformat(value)
|
|
94
139
|
return value
|
|
95
140
|
except ValueError:
|
|
96
141
|
pass
|
|
97
|
-
self.fail(
|
|
142
|
+
self.fail(
|
|
143
|
+
f"{value!r} is not a valid datetime (expected YYYY-MM-DDTHH:MM:SS format)",
|
|
144
|
+
param,
|
|
145
|
+
ctx,
|
|
146
|
+
)
|
|
98
147
|
|
|
99
148
|
|
|
100
149
|
# Type registry for dynamic parameter creation
|
|
@@ -113,19 +162,25 @@ TYPE_MAPPING = {
|
|
|
113
162
|
}
|
|
114
163
|
|
|
115
164
|
|
|
116
|
-
def get_click_type(
|
|
117
|
-
|
|
165
|
+
def get_click_type(
|
|
166
|
+
type_name: str,
|
|
167
|
+
min_val: int | float | None = None,
|
|
168
|
+
max_val: int | float | None = None,
|
|
169
|
+
) -> click.ParamType:
|
|
170
|
+
"""
|
|
171
|
+
Get Click parameter type by name with optional range constraints.
|
|
118
172
|
|
|
119
173
|
Args:
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
174
|
+
type_name: Type name from task definition (e.g., 'str', 'int', 'hostname')
|
|
175
|
+
min_val: Optional minimum value for numeric types
|
|
176
|
+
max_val: Optional maximum value for numeric types
|
|
123
177
|
|
|
124
178
|
Returns:
|
|
125
|
-
|
|
179
|
+
Click parameter type instance
|
|
126
180
|
|
|
127
181
|
Raises:
|
|
128
|
-
|
|
182
|
+
ValueError: If type_name is not recognized
|
|
183
|
+
@athena: d0912868676f
|
|
129
184
|
"""
|
|
130
185
|
if type_name not in TYPE_MAPPING:
|
|
131
186
|
raise ValueError(f"Unknown type: {type_name}")
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: tasktree
|
|
3
|
-
Version: 0.0.
|
|
3
|
+
Version: 0.0.22
|
|
4
4
|
Summary: A task automation tool with incremental execution
|
|
5
5
|
Requires-Python: >=3.11
|
|
6
6
|
Requires-Dist: click>=8.1.0
|
|
@@ -10,7 +10,9 @@ Requires-Dist: pyyaml>=6.0
|
|
|
10
10
|
Requires-Dist: rich>=13.0.0
|
|
11
11
|
Requires-Dist: typer>=0.9.0
|
|
12
12
|
Provides-Extra: dev
|
|
13
|
+
Requires-Dist: black>=26.1.0; extra == 'dev'
|
|
13
14
|
Requires-Dist: pytest>=9.0.2; extra == 'dev'
|
|
15
|
+
Requires-Dist: ruff>=0.14.14; extra == 'dev'
|
|
14
16
|
Description-Content-Type: text/markdown
|
|
15
17
|
|
|
16
18
|
# Task Tree (tt)
|
|
@@ -255,20 +257,19 @@ tasks:
|
|
|
255
257
|
cmd: go build -o dist/binary # Command to execute
|
|
256
258
|
```
|
|
257
259
|
|
|
260
|
+
**Task name constraints:**
|
|
261
|
+
- Task names cannot contain dots (`.`) - they are reserved for namespacing imported tasks
|
|
262
|
+
- Example: `build.release` is invalid as a task name, but valid as a reference to task `release` in namespace `build`
|
|
263
|
+
|
|
258
264
|
### Commands
|
|
259
265
|
|
|
260
|
-
|
|
266
|
+
All commands are executed by writing them to temporary script files. This provides consistent behavior and better shell syntax support:
|
|
261
267
|
|
|
262
268
|
```yaml
|
|
263
269
|
tasks:
|
|
264
270
|
build:
|
|
265
271
|
cmd: cargo build --release
|
|
266
|
-
```
|
|
267
|
-
|
|
268
|
-
**Multi-line commands** are written to temporary script files for proper execution:
|
|
269
272
|
|
|
270
|
-
```yaml
|
|
271
|
-
tasks:
|
|
272
273
|
deploy:
|
|
273
274
|
cmd: |
|
|
274
275
|
mkdir -p dist
|
|
@@ -276,7 +277,7 @@ tasks:
|
|
|
276
277
|
rsync -av dist/ server:/opt/app/
|
|
277
278
|
```
|
|
278
279
|
|
|
279
|
-
|
|
280
|
+
Commands preserve shell syntax (line continuations, heredocs, etc.) and support shebangs on Unix/macOS.
|
|
280
281
|
|
|
281
282
|
Or use folded blocks for long single-line commands:
|
|
282
283
|
|
|
@@ -292,7 +293,7 @@ tasks:
|
|
|
292
293
|
|
|
293
294
|
### Execution Environments
|
|
294
295
|
|
|
295
|
-
Configure custom shell environments for task execution:
|
|
296
|
+
Configure custom shell environments for task execution. Use the `preamble` field to add initialization code to all commands:
|
|
296
297
|
|
|
297
298
|
```yaml
|
|
298
299
|
environments:
|
|
@@ -300,17 +301,14 @@ environments:
|
|
|
300
301
|
|
|
301
302
|
bash-strict:
|
|
302
303
|
shell: bash
|
|
303
|
-
|
|
304
|
-
preamble: | # For multi-line: prepended to script
|
|
304
|
+
preamble: | # Prepended to all commands
|
|
305
305
|
set -euo pipefail
|
|
306
306
|
|
|
307
307
|
python:
|
|
308
308
|
shell: python
|
|
309
|
-
args: ['-c']
|
|
310
309
|
|
|
311
310
|
powershell:
|
|
312
311
|
shell: powershell
|
|
313
|
-
args: ['-ExecutionPolicy', 'Bypass', '-Command']
|
|
314
312
|
preamble: |
|
|
315
313
|
$ErrorActionPreference = 'Stop'
|
|
316
314
|
|
|
@@ -339,8 +337,8 @@ tasks:
|
|
|
339
337
|
4. Platform default (bash on Unix, cmd on Windows)
|
|
340
338
|
|
|
341
339
|
**Platform defaults** when no environments are configured:
|
|
342
|
-
- **Unix/macOS**: bash
|
|
343
|
-
- **Windows**: cmd
|
|
340
|
+
- **Unix/macOS**: bash
|
|
341
|
+
- **Windows**: cmd
|
|
344
342
|
|
|
345
343
|
### Docker Environments
|
|
346
344
|
|
|
@@ -835,7 +833,7 @@ Hint: Define named outputs like: outputs: [{ missing: 'path/to/file' }]
|
|
|
835
833
|
|
|
836
834
|
### Self-References
|
|
837
835
|
|
|
838
|
-
Tasks can reference their own
|
|
836
|
+
Tasks can reference their own inputs and outputs using `{{ self.inputs.name }}` (named access) or `{{ self.inputs.0 }}` (positional access) templates. This eliminates repetition when paths contain variables or when tasks have multiple inputs/outputs.
|
|
839
837
|
|
|
840
838
|
**Named Inputs and Outputs:**
|
|
841
839
|
|
|
@@ -862,8 +860,10 @@ tasks:
|
|
|
862
860
|
|
|
863
861
|
- **Defining named inputs**: `inputs: [{ name: "path/to/file" }]`
|
|
864
862
|
- **Defining named outputs**: `outputs: [{ name: "path/to/file" }]`
|
|
865
|
-
- **
|
|
866
|
-
- **
|
|
863
|
+
- **Defining anonymous inputs**: `inputs: ["path/to/file"]`
|
|
864
|
+
- **Defining anonymous outputs**: `outputs: ["path/to/file"]`
|
|
865
|
+
- **Referencing by name**: `{{ self.inputs.input_name }}` or `{{ self.outputs.output_name }}`
|
|
866
|
+
- **Referencing by index**: `{{ self.inputs.0 }}` or `{{ self.outputs.1 }}` (0-based)
|
|
867
867
|
- **Mixed format**: Can combine named and anonymous inputs/outputs in the same task
|
|
868
868
|
|
|
869
869
|
**Why Use Self-References?**
|
|
@@ -972,6 +972,129 @@ tasks:
|
|
|
972
972
|
cmd: build-tool --config {{ self.inputs.config }} --output {{ self.outputs.binary }}
|
|
973
973
|
```
|
|
974
974
|
|
|
975
|
+
**Positional Index References:**
|
|
976
|
+
|
|
977
|
+
In addition to named references, you can access inputs and outputs by their positional index using `{{ self.inputs.0 }}`, `{{ self.inputs.1 }}`, etc. This provides an alternative way to reference items, especially useful for:
|
|
978
|
+
|
|
979
|
+
- **Anonymous inputs/outputs**: Reference items that don't have names
|
|
980
|
+
- **Simple sequential access**: When order is more important than naming
|
|
981
|
+
- **Mixed with named access**: Use both styles in the same task
|
|
982
|
+
|
|
983
|
+
**Syntax:**
|
|
984
|
+
|
|
985
|
+
```yaml
|
|
986
|
+
tasks:
|
|
987
|
+
process:
|
|
988
|
+
inputs: ["file1.txt", "file2.txt", "file3.txt"]
|
|
989
|
+
outputs: ["output1.txt", "output2.txt"]
|
|
990
|
+
cmd: |
|
|
991
|
+
cat {{ self.inputs.0 }} {{ self.inputs.1 }} > {{ self.outputs.0 }}
|
|
992
|
+
cat {{ self.inputs.2 }} > {{ self.outputs.1 }}
|
|
993
|
+
```
|
|
994
|
+
|
|
995
|
+
Indices follow YAML declaration order, starting from 0 (zero-based indexing):
|
|
996
|
+
- First input/output = index 0
|
|
997
|
+
- Second input/output = index 1
|
|
998
|
+
- Third input/output = index 2, etc.
|
|
999
|
+
|
|
1000
|
+
**Works with Both Named and Anonymous:**
|
|
1001
|
+
|
|
1002
|
+
```yaml
|
|
1003
|
+
tasks:
|
|
1004
|
+
build:
|
|
1005
|
+
inputs:
|
|
1006
|
+
- config: "build.yaml" # Index 0, also accessible as {{ self.inputs.config }}
|
|
1007
|
+
- "src/**/*.c" # Index 1, ONLY accessible as {{ self.inputs.1 }}
|
|
1008
|
+
- headers: "include/*.h" # Index 2, also accessible as {{ self.inputs.headers }}
|
|
1009
|
+
outputs:
|
|
1010
|
+
- "dist/app.js" # Index 0
|
|
1011
|
+
- bundle: "dist/bundle.js" # Index 1, also accessible as {{ self.outputs.bundle }}
|
|
1012
|
+
cmd: |
|
|
1013
|
+
# Mix positional and named references
|
|
1014
|
+
build-tool \
|
|
1015
|
+
--config {{ self.inputs.0 }} \
|
|
1016
|
+
--sources {{ self.inputs.1 }} \
|
|
1017
|
+
--headers {{ self.inputs.headers }} \
|
|
1018
|
+
--output {{ self.outputs.bundle }}
|
|
1019
|
+
```
|
|
1020
|
+
|
|
1021
|
+
**Same Item, Multiple Ways:**
|
|
1022
|
+
|
|
1023
|
+
Named items can be accessed by both name and index:
|
|
1024
|
+
|
|
1025
|
+
```yaml
|
|
1026
|
+
tasks:
|
|
1027
|
+
copy:
|
|
1028
|
+
inputs:
|
|
1029
|
+
- source: data.txt
|
|
1030
|
+
cmd: |
|
|
1031
|
+
# These are equivalent:
|
|
1032
|
+
cat {{ self.inputs.source }} > copy1.txt
|
|
1033
|
+
cat {{ self.inputs.0 }} > copy2.txt
|
|
1034
|
+
```
|
|
1035
|
+
|
|
1036
|
+
**With Variables and Arguments:**
|
|
1037
|
+
|
|
1038
|
+
Positional references work with variable-expanded paths:
|
|
1039
|
+
|
|
1040
|
+
```yaml
|
|
1041
|
+
variables:
|
|
1042
|
+
version: "1.0"
|
|
1043
|
+
|
|
1044
|
+
tasks:
|
|
1045
|
+
package:
|
|
1046
|
+
args: [platform]
|
|
1047
|
+
inputs:
|
|
1048
|
+
- "dist/app-{{ var.version }}.js"
|
|
1049
|
+
- "dist/lib-{{ arg.platform }}.so"
|
|
1050
|
+
outputs: ["release-{{ var.version }}-{{ arg.platform }}.tar.gz"]
|
|
1051
|
+
cmd: tar czf {{ self.outputs.0 }} {{ self.inputs.0 }} {{ self.inputs.1 }}
|
|
1052
|
+
```
|
|
1053
|
+
|
|
1054
|
+
**Index Boundaries:**
|
|
1055
|
+
|
|
1056
|
+
Indices are validated before execution:
|
|
1057
|
+
|
|
1058
|
+
```yaml
|
|
1059
|
+
tasks:
|
|
1060
|
+
build:
|
|
1061
|
+
inputs: ["file1.txt", "file2.txt"]
|
|
1062
|
+
cmd: cat {{ self.inputs.5 }} # Error: index 5 out of bounds!
|
|
1063
|
+
```
|
|
1064
|
+
|
|
1065
|
+
Error message:
|
|
1066
|
+
```
|
|
1067
|
+
Task 'build' references input index '5' but only has 2 inputs (indices 0-1)
|
|
1068
|
+
```
|
|
1069
|
+
|
|
1070
|
+
**Empty Lists:**
|
|
1071
|
+
|
|
1072
|
+
Referencing an index when no inputs/outputs exist:
|
|
1073
|
+
|
|
1074
|
+
```yaml
|
|
1075
|
+
tasks:
|
|
1076
|
+
generate:
|
|
1077
|
+
cmd: echo "test" > {{ self.outputs.0 }} # Error: no outputs defined!
|
|
1078
|
+
```
|
|
1079
|
+
|
|
1080
|
+
Error message:
|
|
1081
|
+
```
|
|
1082
|
+
Task 'generate' references output index '0' but has no outputs defined
|
|
1083
|
+
```
|
|
1084
|
+
|
|
1085
|
+
**When to Use Index References:**
|
|
1086
|
+
|
|
1087
|
+
- **Anonymous items**: Only way to reference inputs/outputs without names
|
|
1088
|
+
- **Order-based processing**: When the sequence matters more than naming
|
|
1089
|
+
- **Simple tasks**: Quick access without defining names
|
|
1090
|
+
- **Compatibility**: Accessing items in legacy YAML that uses anonymous format
|
|
1091
|
+
|
|
1092
|
+
**When to Use Named References:**
|
|
1093
|
+
|
|
1094
|
+
- **Clarity**: Names make commands more readable (`{{ self.inputs.config }}` vs `{{ self.inputs.2 }}`)
|
|
1095
|
+
- **Maintainability**: Adding/removing items doesn't break indices
|
|
1096
|
+
- **Complex tasks**: Many inputs/outputs are easier to manage with names
|
|
1097
|
+
|
|
975
1098
|
**Error Messages:**
|
|
976
1099
|
|
|
977
1100
|
If you reference a non-existent input or output:
|
|
@@ -1011,18 +1134,21 @@ Hint: Define named inputs like: inputs: [{ src: 'file.txt' }]
|
|
|
1011
1134
|
|
|
1012
1135
|
**Key Behaviors:**
|
|
1013
1136
|
|
|
1137
|
+
- **Two access methods**: Reference by name (`{{ self.inputs.name }}`) or by index (`{{ self.inputs.0 }}`)
|
|
1014
1138
|
- **Template resolution**: Self-references are resolved during dependency graph planning
|
|
1015
1139
|
- **Substitution order**: Variables → Dependency outputs → Self-references → Arguments/Environment
|
|
1016
|
-
- **Fail-fast validation**: Errors are caught before execution begins
|
|
1017
|
-
- **Clear error messages**: Lists available names if reference doesn't exist
|
|
1140
|
+
- **Fail-fast validation**: Errors are caught before execution begins (missing names, out-of-bounds indices)
|
|
1141
|
+
- **Clear error messages**: Lists available names/indices if reference doesn't exist
|
|
1018
1142
|
- **Backward compatible**: Existing anonymous inputs/outputs work unchanged
|
|
1019
1143
|
- **State tracking**: Works correctly with incremental execution and freshness checks
|
|
1144
|
+
- **Index order**: Positional indices follow YAML declaration order (0-based)
|
|
1020
1145
|
|
|
1021
1146
|
**Limitations:**
|
|
1022
1147
|
|
|
1023
|
-
- **Anonymous not referenceable**:
|
|
1148
|
+
- **Anonymous not referenceable by name**: Anonymous inputs/outputs cannot be referenced by name (use positional index instead: `{{ self.inputs.0 }}`)
|
|
1024
1149
|
- **Case sensitive**: `{{ self.inputs.Src }}` and `{{ self.inputs.src }}` are different
|
|
1025
1150
|
- **Argument defaults**: Self-references in argument defaults are not supported (arguments are evaluated before self-references)
|
|
1151
|
+
- **No negative indices**: Python-style negative indexing (`{{ self.inputs.-1 }}`) is not supported
|
|
1026
1152
|
|
|
1027
1153
|
**Use Cases:**
|
|
1028
1154
|
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
tasktree/__init__.py,sha256=ZfI6vy-TxinN7eK0_XjfHUFq83pFV1XiHFrai_SHNqw,1251
|
|
2
|
+
tasktree/cli.py,sha256=588ngMB27T6FqUp5LIJ_x_UNoPRlMv39b1_U0a88tfE,23577
|
|
3
|
+
tasktree/docker.py,sha256=DAvdr6kZqkhx8J9fhsz26Z41hFPreANC60vdunvPX00,15050
|
|
4
|
+
tasktree/executor.py,sha256=UF2H-qCgkJ5E2QoYt3To3a-ypwTIYJT9oyWRcBw2CzQ,46800
|
|
5
|
+
tasktree/graph.py,sha256=Ya4ATQidj0rlHxvvbWF0Xx2J18MTpz2XPAHTcJXFcBg,23637
|
|
6
|
+
tasktree/hasher.py,sha256=fvs7vNBrHdAA6pX-ZLhNnWLtd5qdxjAVFJC8SDF-DhQ,6730
|
|
7
|
+
tasktree/parser.py,sha256=OUuME_ZqITAMQEL90w-yJFLKoEquF_IIa-By8MifMvI,101074
|
|
8
|
+
tasktree/state.py,sha256=R4ZXgfs_rwrOH9nEb4mOjuHa7gAVqi7QPVCi0CouNQA,3961
|
|
9
|
+
tasktree/substitution.py,sha256=hwox1m9r8p5b0Fcln12C63GexJHc5ZMUoqOrpqQLuPk,18663
|
|
10
|
+
tasktree/types.py,sha256=nCiPrxg3r3ZX4CoZ6L5FrkJO9mgz_lFsZ-98X8tYgns,5015
|
|
11
|
+
tasktree-0.0.22.dist-info/METADATA,sha256=fuvZWDbtlwfbQNOP_TMCDRSDGKdZYUTeROo3eqVcJ6o,54519
|
|
12
|
+
tasktree-0.0.22.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
13
|
+
tasktree-0.0.22.dist-info/entry_points.txt,sha256=lQINlvRYnimvteBbnhH84A9clTg8NnpEjCWqWkqg8KE,40
|
|
14
|
+
tasktree-0.0.22.dist-info/RECORD,,
|
tasktree-0.0.20.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
tasktree/__init__.py,sha256=m7fLsPUft99oB_XXr4dOu2yUWu74zVutkw1-3zGrG5Y,1227
|
|
2
|
-
tasktree/cli.py,sha256=S5ypqQlvCxdAvlBfO8TJZhvMoc086wqgvmOm8220678,21220
|
|
3
|
-
tasktree/docker.py,sha256=qvja8G63uAcC73YMVY739egda1_CcBtoqzm0qIJU_Q8,14443
|
|
4
|
-
tasktree/executor.py,sha256=g4mHtoO3wVIxyqNALIdJOEwlEqRkSY0eY-6sl2jF-IA,46463
|
|
5
|
-
tasktree/graph.py,sha256=T78JH0whP7VquEvtOVN-8ePyHNcseTQoEouijDrgmkw,22663
|
|
6
|
-
tasktree/hasher.py,sha256=o7Akd_AgGkAsnv9biK0AcbhlcqUQ9ne5y_6r4zoFaw0,5493
|
|
7
|
-
tasktree/parser.py,sha256=R0swEkKBPGeijLHxD1CbQjtoKVn2gRJadsZuyKj1sdM,97922
|
|
8
|
-
tasktree/state.py,sha256=Cktl4D8iDZVd55aO2LqVyPrc-BnljkesxxkcMcdcfOY,3541
|
|
9
|
-
tasktree/substitution.py,sha256=FhtFI0ciK9bQxPdORvpf1coa59XxizKiBiUwHJp0PtI,16811
|
|
10
|
-
tasktree/types.py,sha256=R_YAyO5bMLB6XZnkMRT7VAtlkA_Xx6xu0aIpzQjrBXs,4357
|
|
11
|
-
tasktree-0.0.20.dist-info/METADATA,sha256=C8cdZtyz-dgiVoN1H2hy7wQNAA-K784WYFfqlZEOXnA,50237
|
|
12
|
-
tasktree-0.0.20.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
|
|
13
|
-
tasktree-0.0.20.dist-info/entry_points.txt,sha256=lQINlvRYnimvteBbnhH84A9clTg8NnpEjCWqWkqg8KE,40
|
|
14
|
-
tasktree-0.0.20.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|