tasktree 0.0.19__py3-none-any.whl → 0.0.21__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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tasktree
3
- Version: 0.0.19
3
+ Version: 0.0.21
4
4
  Summary: A task automation tool with incremental execution
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: click>=8.1.0
@@ -833,6 +833,369 @@ Hint: Define named outputs like: outputs: [{ missing: 'path/to/file' }]
833
833
  - **Deployment pipelines**: Reference exact artifacts to deploy
834
834
  - **Configuration propagation**: Pass generated config files through build stages
835
835
 
836
+ ### Self-References
837
+
838
+ 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
+
840
+ **Named Inputs and Outputs:**
841
+
842
+ Just like dependency output references, inputs and outputs can have names:
843
+
844
+ ```yaml
845
+ tasks:
846
+ process:
847
+ inputs:
848
+ - src: "data/input.json" # Named input
849
+ - config: "config.yaml" # Named input
850
+ outputs:
851
+ - result: "output/result.json" # Named output
852
+ - log: "output/process.log" # Named output
853
+ cmd: |
854
+ process-tool \
855
+ --input {{ self.inputs.src }} \
856
+ --config {{ self.inputs.config }} \
857
+ --output {{ self.outputs.result }} \
858
+ --log {{ self.outputs.log }}
859
+ ```
860
+
861
+ **Syntax:**
862
+
863
+ - **Defining named inputs**: `inputs: [{ name: "path/to/file" }]`
864
+ - **Defining named outputs**: `outputs: [{ name: "path/to/file" }]`
865
+ - **Defining anonymous inputs**: `inputs: ["path/to/file"]`
866
+ - **Defining anonymous outputs**: `outputs: ["path/to/file"]`
867
+ - **Referencing by name**: `{{ self.inputs.input_name }}` or `{{ self.outputs.output_name }}`
868
+ - **Referencing by index**: `{{ self.inputs.0 }}` or `{{ self.outputs.1 }}` (0-based)
869
+ - **Mixed format**: Can combine named and anonymous inputs/outputs in the same task
870
+
871
+ **Why Use Self-References?**
872
+
873
+ Self-references follow the DRY (Don't Repeat Yourself) principle:
874
+
875
+ ```yaml
876
+ # Without self-references - repetitive
877
+ tasks:
878
+ build:
879
+ inputs: [src/app-{{ var.version }}.c]
880
+ outputs: [build/app-{{ var.version }}.o]
881
+ cmd: gcc src/app-{{ var.version }}.c -o build/app-{{ var.version }}.o
882
+
883
+ # With self-references - DRY
884
+ tasks:
885
+ build:
886
+ inputs:
887
+ - source: src/app-{{ var.version }}.c
888
+ outputs:
889
+ - object: build/app-{{ var.version }}.o
890
+ cmd: gcc {{ self.inputs.source }} -o {{ self.outputs.object }}
891
+ ```
892
+
893
+ **Working with Variables:**
894
+
895
+ Self-references work seamlessly with variables:
896
+
897
+ ```yaml
898
+ variables:
899
+ platform: linux
900
+ arch: x86_64
901
+
902
+ tasks:
903
+ compile:
904
+ inputs:
905
+ - src: src/{{ var.platform }}/main.c
906
+ - header: include/{{ var.arch }}/defs.h
907
+ outputs:
908
+ - binary: build/{{ var.platform }}-{{ var.arch }}/app
909
+ cmd: |
910
+ gcc {{ self.inputs.src }} \
911
+ -include {{ self.inputs.header }} \
912
+ -o {{ self.outputs.binary }}
913
+ ```
914
+
915
+ Variables are evaluated first, then self-references substitute the expanded paths.
916
+
917
+ **Working with Arguments:**
918
+
919
+ Self-references work with parameterized tasks:
920
+
921
+ ```yaml
922
+ tasks:
923
+ deploy:
924
+ args: [environment]
925
+ inputs:
926
+ - config: configs/{{ arg.environment }}/app.yaml
927
+ outputs:
928
+ - deployed: deployed-{{ arg.environment }}.yaml
929
+ cmd: |
930
+ validate {{ self.inputs.config }}
931
+ deploy {{ self.inputs.config }} > {{ self.outputs.deployed }}
932
+ ```
933
+
934
+ ```bash
935
+ tt deploy production # Uses configs/production/app.yaml
936
+ tt deploy staging # Uses configs/staging/app.yaml
937
+ ```
938
+
939
+ **Working with Dependency Outputs:**
940
+
941
+ Self-references and dependency references can be used together:
942
+
943
+ ```yaml
944
+ tasks:
945
+ build:
946
+ outputs:
947
+ - artifact: dist/app.js
948
+ cmd: webpack build
949
+
950
+ package:
951
+ deps: [build]
952
+ inputs:
953
+ - manifest: package.json
954
+ outputs:
955
+ - tarball: release.tar.gz
956
+ cmd: tar czf {{ self.outputs.tarball }} \
957
+ {{ self.inputs.manifest }} \
958
+ {{ dep.build.outputs.artifact }}
959
+ ```
960
+
961
+ **Mixed Named and Anonymous:**
962
+
963
+ Tasks can mix named and anonymous inputs/outputs:
964
+
965
+ ```yaml
966
+ tasks:
967
+ build:
968
+ inputs:
969
+ - config: build.yaml # Named - can reference
970
+ - src/**/*.c # Anonymous - tracked but not referenceable
971
+ outputs:
972
+ - binary: bin/app # Named - can reference
973
+ - bin/app.debug # Anonymous - tracked but not referenceable
974
+ cmd: build-tool --config {{ self.inputs.config }} --output {{ self.outputs.binary }}
975
+ ```
976
+
977
+ **Positional Index References:**
978
+
979
+ 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:
980
+
981
+ - **Anonymous inputs/outputs**: Reference items that don't have names
982
+ - **Simple sequential access**: When order is more important than naming
983
+ - **Mixed with named access**: Use both styles in the same task
984
+
985
+ **Syntax:**
986
+
987
+ ```yaml
988
+ tasks:
989
+ process:
990
+ inputs: ["file1.txt", "file2.txt", "file3.txt"]
991
+ outputs: ["output1.txt", "output2.txt"]
992
+ cmd: |
993
+ cat {{ self.inputs.0 }} {{ self.inputs.1 }} > {{ self.outputs.0 }}
994
+ cat {{ self.inputs.2 }} > {{ self.outputs.1 }}
995
+ ```
996
+
997
+ Indices follow YAML declaration order, starting from 0 (zero-based indexing):
998
+ - First input/output = index 0
999
+ - Second input/output = index 1
1000
+ - Third input/output = index 2, etc.
1001
+
1002
+ **Works with Both Named and Anonymous:**
1003
+
1004
+ ```yaml
1005
+ tasks:
1006
+ build:
1007
+ inputs:
1008
+ - config: "build.yaml" # Index 0, also accessible as {{ self.inputs.config }}
1009
+ - "src/**/*.c" # Index 1, ONLY accessible as {{ self.inputs.1 }}
1010
+ - headers: "include/*.h" # Index 2, also accessible as {{ self.inputs.headers }}
1011
+ outputs:
1012
+ - "dist/app.js" # Index 0
1013
+ - bundle: "dist/bundle.js" # Index 1, also accessible as {{ self.outputs.bundle }}
1014
+ cmd: |
1015
+ # Mix positional and named references
1016
+ build-tool \
1017
+ --config {{ self.inputs.0 }} \
1018
+ --sources {{ self.inputs.1 }} \
1019
+ --headers {{ self.inputs.headers }} \
1020
+ --output {{ self.outputs.bundle }}
1021
+ ```
1022
+
1023
+ **Same Item, Multiple Ways:**
1024
+
1025
+ Named items can be accessed by both name and index:
1026
+
1027
+ ```yaml
1028
+ tasks:
1029
+ copy:
1030
+ inputs:
1031
+ - source: data.txt
1032
+ cmd: |
1033
+ # These are equivalent:
1034
+ cat {{ self.inputs.source }} > copy1.txt
1035
+ cat {{ self.inputs.0 }} > copy2.txt
1036
+ ```
1037
+
1038
+ **With Variables and Arguments:**
1039
+
1040
+ Positional references work with variable-expanded paths:
1041
+
1042
+ ```yaml
1043
+ variables:
1044
+ version: "1.0"
1045
+
1046
+ tasks:
1047
+ package:
1048
+ args: [platform]
1049
+ inputs:
1050
+ - "dist/app-{{ var.version }}.js"
1051
+ - "dist/lib-{{ arg.platform }}.so"
1052
+ outputs: ["release-{{ var.version }}-{{ arg.platform }}.tar.gz"]
1053
+ cmd: tar czf {{ self.outputs.0 }} {{ self.inputs.0 }} {{ self.inputs.1 }}
1054
+ ```
1055
+
1056
+ **Index Boundaries:**
1057
+
1058
+ Indices are validated before execution:
1059
+
1060
+ ```yaml
1061
+ tasks:
1062
+ build:
1063
+ inputs: ["file1.txt", "file2.txt"]
1064
+ cmd: cat {{ self.inputs.5 }} # Error: index 5 out of bounds!
1065
+ ```
1066
+
1067
+ Error message:
1068
+ ```
1069
+ Task 'build' references input index '5' but only has 2 inputs (indices 0-1)
1070
+ ```
1071
+
1072
+ **Empty Lists:**
1073
+
1074
+ Referencing an index when no inputs/outputs exist:
1075
+
1076
+ ```yaml
1077
+ tasks:
1078
+ generate:
1079
+ cmd: echo "test" > {{ self.outputs.0 }} # Error: no outputs defined!
1080
+ ```
1081
+
1082
+ Error message:
1083
+ ```
1084
+ Task 'generate' references output index '0' but has no outputs defined
1085
+ ```
1086
+
1087
+ **When to Use Index References:**
1088
+
1089
+ - **Anonymous items**: Only way to reference inputs/outputs without names
1090
+ - **Order-based processing**: When the sequence matters more than naming
1091
+ - **Simple tasks**: Quick access without defining names
1092
+ - **Compatibility**: Accessing items in legacy YAML that uses anonymous format
1093
+
1094
+ **When to Use Named References:**
1095
+
1096
+ - **Clarity**: Names make commands more readable (`{{ self.inputs.config }}` vs `{{ self.inputs.2 }}`)
1097
+ - **Maintainability**: Adding/removing items doesn't break indices
1098
+ - **Complex tasks**: Many inputs/outputs are easier to manage with names
1099
+
1100
+ **Error Messages:**
1101
+
1102
+ If you reference a non-existent input or output:
1103
+
1104
+ ```yaml
1105
+ tasks:
1106
+ build:
1107
+ inputs:
1108
+ - src: input.txt
1109
+ cmd: cat {{ self.inputs.missing }} # Error!
1110
+ ```
1111
+
1112
+ You'll get a clear error before execution:
1113
+
1114
+ ```
1115
+ Task 'build' references input 'missing' but has no input named 'missing'.
1116
+ Available named inputs: src
1117
+ Hint: Define named inputs like: inputs: [{ missing: 'path/to/file' }]
1118
+ ```
1119
+
1120
+ Similarly, if you try to reference an anonymous input:
1121
+
1122
+ ```yaml
1123
+ tasks:
1124
+ build:
1125
+ inputs: [file.txt] # Anonymous input
1126
+ cmd: cat {{ self.inputs.src }} # Error!
1127
+ ```
1128
+
1129
+ You'll get:
1130
+
1131
+ ```
1132
+ Task 'build' references input 'src' but has no input named 'src'.
1133
+ Available named inputs: (none - all inputs are anonymous)
1134
+ Hint: Define named inputs like: inputs: [{ src: 'file.txt' }]
1135
+ ```
1136
+
1137
+ **Key Behaviors:**
1138
+
1139
+ - **Two access methods**: Reference by name (`{{ self.inputs.name }}`) or by index (`{{ self.inputs.0 }}`)
1140
+ - **Template resolution**: Self-references are resolved during dependency graph planning
1141
+ - **Substitution order**: Variables → Dependency outputs → Self-references → Arguments/Environment
1142
+ - **Fail-fast validation**: Errors are caught before execution begins (missing names, out-of-bounds indices)
1143
+ - **Clear error messages**: Lists available names/indices if reference doesn't exist
1144
+ - **Backward compatible**: Existing anonymous inputs/outputs work unchanged
1145
+ - **State tracking**: Works correctly with incremental execution and freshness checks
1146
+ - **Index order**: Positional indices follow YAML declaration order (0-based)
1147
+
1148
+ **Limitations:**
1149
+
1150
+ - **Anonymous not referenceable by name**: Anonymous inputs/outputs cannot be referenced by name (use positional index instead: `{{ self.inputs.0 }}`)
1151
+ - **Case sensitive**: `{{ self.inputs.Src }}` and `{{ self.inputs.src }}` are different
1152
+ - **Argument defaults**: Self-references in argument defaults are not supported (arguments are evaluated before self-references)
1153
+ - **No negative indices**: Python-style negative indexing (`{{ self.inputs.-1 }}`) is not supported
1154
+
1155
+ **Use Cases:**
1156
+
1157
+ - **Eliminate repetition**: Define complex paths once, use them multiple times
1158
+ - **Variable composition**: Combine variables with self-references for clean commands
1159
+ - **Multiple inputs/outputs**: Reference specific files when tasks have many
1160
+ - **Complex build pipelines**: Keep commands readable with named artifacts
1161
+ - **Glob patterns**: Use self-references with glob patterns for dynamic inputs
1162
+
1163
+ **Example: Multi-Stage Build:**
1164
+
1165
+ ```yaml
1166
+ variables:
1167
+ version: "2.1.0"
1168
+ platform: "linux"
1169
+
1170
+ tasks:
1171
+ prepare:
1172
+ outputs:
1173
+ - builddir: build/{{ var.platform }}-{{ var.version }}
1174
+ cmd: mkdir -p {{ self.outputs.builddir }}
1175
+
1176
+ compile:
1177
+ deps: [prepare]
1178
+ inputs:
1179
+ - source: src/main.c
1180
+ - headers: include/*.h
1181
+ outputs:
1182
+ - object: build/{{ var.platform }}-{{ var.version }}/main.o
1183
+ cmd: |
1184
+ gcc -c {{ self.inputs.source }} \
1185
+ -I include \
1186
+ -o {{ self.outputs.object }}
1187
+
1188
+ link:
1189
+ deps: [compile]
1190
+ outputs:
1191
+ - executable: build/{{ var.platform }}-{{ var.version }}/app
1192
+ - symbols: build/{{ var.platform }}-{{ var.version }}/app.sym
1193
+ cmd: |
1194
+ gcc build/{{ var.platform }}-{{ var.version }}/main.o \
1195
+ -o {{ self.outputs.executable }}
1196
+ objcopy --only-keep-debug {{ self.outputs.executable }} {{ self.outputs.symbols }}
1197
+ ```
1198
+
836
1199
 
837
1200
  ### Private Tasks
838
1201
 
@@ -0,0 +1,14 @@
1
+ tasktree/__init__.py,sha256=ZfI6vy-TxinN7eK0_XjfHUFq83pFV1XiHFrai_SHNqw,1251
2
+ tasktree/cli.py,sha256=pyXMUENz1ldl8z9SPXBZ1zhOHzmvIRUGu2y5VwRUdgo,22960
3
+ tasktree/docker.py,sha256=EeIUqptvDqSXbjWKXwWGhA4hWvsBjOk0Z-3cS3cqEOM,14857
4
+ tasktree/executor.py,sha256=x0K-TIVRmiKuUlur1UTOpB2xOJOE_Cv3-3MlE7xUNEk,47271
5
+ tasktree/graph.py,sha256=BjpLaa7EE2vmOcUlqhvp1KK7yT5VbXHQCbxljOhF84k,23603
6
+ tasktree/hasher.py,sha256=UM-2dqRE-rspQUbhA-noGHc80-Hu-QaxCTPRb_UzPto,6661
7
+ tasktree/parser.py,sha256=sXgotDdDQiNSmo7FaESFQ4j1OytaheyplJSdFrFXTYk,99286
8
+ tasktree/state.py,sha256=0fxKbMNYbo-dCpCTTnKTmJhGRy72G5kLnh99FScMLGU,3985
9
+ tasktree/substitution.py,sha256=2ubFn6jIX5qmtzyWSCxTut-_Cn0zew8KnwxMqDIPq1o,18545
10
+ tasktree/types.py,sha256=2uHdUncfyfw4jNWbQTBUirew-frmTjuk1ZYNd15cyQQ,4908
11
+ tasktree-0.0.21.dist-info/METADATA,sha256=nyjDhb1hdQMEiLx0t_qqonqPoyFZVMCrIg7xFIKxMs8,54353
12
+ tasktree-0.0.21.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
13
+ tasktree-0.0.21.dist-info/entry_points.txt,sha256=lQINlvRYnimvteBbnhH84A9clTg8NnpEjCWqWkqg8KE,40
14
+ tasktree-0.0.21.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- tasktree/__init__.py,sha256=N-dZcggJDe4WaloC1MdEh0oMTHlUpBN9AEcAm6leDf4,1167
2
- tasktree/cli.py,sha256=_GzqQIk2z2Hz17bkTOWhtNW4X4_Ijxn-uEL-WZGt8LM,20858
3
- tasktree/docker.py,sha256=qvja8G63uAcC73YMVY739egda1_CcBtoqzm0qIJU_Q8,14443
4
- tasktree/executor.py,sha256=7pzcH2wLWMZPk3hwhzWgz18RVkIPFCKdu23MboWUQs4,45914
5
- tasktree/graph.py,sha256=9O5LByzMYa8ccedznqKBTb0Xe9N_aajSR1cAcb8zGQE,20366
6
- tasktree/hasher.py,sha256=o7Akd_AgGkAsnv9biK0AcbhlcqUQ9ne5y_6r4zoFaw0,5493
7
- tasktree/parser.py,sha256=PVgtGORCpnkb8wcXHFfsyVqDhJ3PwzwCqO3VWiuLQl4,94777
8
- tasktree/state.py,sha256=Cktl4D8iDZVd55aO2LqVyPrc-BnljkesxxkcMcdcfOY,3541
9
- tasktree/substitution.py,sha256=3-gdvHbBwPkQPflx3GVSpEEa0vTL_ivdcMIba77gtJc,14225
10
- tasktree/types.py,sha256=R_YAyO5bMLB6XZnkMRT7VAtlkA_Xx6xu0aIpzQjrBXs,4357
11
- tasktree-0.0.19.dist-info/METADATA,sha256=KTLp0p1Mkzzvah-Hy15KrXnTcKju5dlQyvDvEdnDOmg,43609
12
- tasktree-0.0.19.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
13
- tasktree-0.0.19.dist-info/entry_points.txt,sha256=lQINlvRYnimvteBbnhH84A9clTg8NnpEjCWqWkqg8KE,40
14
- tasktree-0.0.19.dist-info/RECORD,,