tasktree 0.0.18__py3-none-any.whl → 0.0.20__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.18
3
+ Version: 0.0.20
4
4
  Summary: A task automation tool with incremental execution
5
5
  Requires-Python: >=3.11
6
6
  Requires-Dist: click>=8.1.0
@@ -248,6 +248,7 @@ tasks:
248
248
  outputs: [dist/binary] # Output files (glob patterns)
249
249
  working_dir: subproject/ # Execution directory (default: project root)
250
250
  env: bash-strict # Execution environment (optional)
251
+ private: false # Hide from --list output (default: false)
251
252
  args: # Task parameters
252
253
  - param1 # Simple argument
253
254
  - param2: { type: path, default: "." } # With type and default
@@ -687,6 +688,420 @@ tasks:
687
688
  cmd: echo "All tests passed"
688
689
  ```
689
690
 
691
+ ### Dependency Output References
692
+
693
+ Tasks can reference named outputs from their dependencies, enabling dynamic workflows where build artifacts, generated filenames, and other values are passed between tasks.
694
+
695
+ **Named Outputs:**
696
+
697
+ Tasks can define outputs with names for easy referencing:
698
+
699
+ ```yaml
700
+ tasks:
701
+ build:
702
+ outputs:
703
+ - bundle: "dist/app.js" # Named output
704
+ - sourcemap: "dist/app.js.map" # Named output
705
+ cmd: webpack build
706
+
707
+ deploy:
708
+ deps: [build]
709
+ cmd: |
710
+ echo "Deploying {{ dep.build.outputs.bundle }}"
711
+ scp {{ dep.build.outputs.bundle }} server:/var/www/
712
+ scp {{ dep.build.outputs.sourcemap }} server:/var/www/
713
+ ```
714
+
715
+ **Syntax:**
716
+
717
+ - **Defining named outputs**: `outputs: [{ name: "path/to/file" }]`
718
+ - **Referencing outputs**: `{{ dep.task_name.outputs.output_name }}`
719
+ - **Mixed format**: Can combine named and anonymous outputs in the same task
720
+
721
+ **Examples:**
722
+
723
+ ```yaml
724
+ tasks:
725
+ # Generate a config file
726
+ generate-config:
727
+ outputs:
728
+ - config: "build/config.json"
729
+ cmd: |
730
+ mkdir -p build
731
+ echo '{"version": "1.0.0"}' > build/config.json
732
+
733
+ # Compile using the generated config
734
+ compile:
735
+ deps: [generate-config]
736
+ outputs:
737
+ - binary: "build/app"
738
+ - symbols: "build/app.sym"
739
+ cmd: |
740
+ echo "Using config: {{ dep.generate-config.outputs.config }}"
741
+ gcc -o build/app src/*.c
742
+
743
+ # Package multiple dependency outputs
744
+ package:
745
+ deps: [compile]
746
+ outputs:
747
+ - archive: "dist/app.tar.gz"
748
+ cmd: |
749
+ mkdir -p dist
750
+ tar czf {{ dep.package.outputs.archive }} \
751
+ {{ dep.compile.outputs.binary }} \
752
+ {{ dep.compile.outputs.symbols }}
753
+ ```
754
+
755
+ **Mixed Named and Anonymous Outputs:**
756
+
757
+ Tasks can have both named and anonymous outputs:
758
+
759
+ ```yaml
760
+ tasks:
761
+ build:
762
+ outputs:
763
+ - binary: "build/app" # Named - can be referenced
764
+ - "build/app.debug" # Anonymous - tracked but not referenceable
765
+ - manifest: "build/manifest.json" # Named - can be referenced
766
+ cmd: make all
767
+ ```
768
+
769
+ **Transitive References:**
770
+
771
+ Output references work across multiple levels of dependencies:
772
+
773
+ ```yaml
774
+ tasks:
775
+ base:
776
+ outputs:
777
+ - lib: "out/libbase.a"
778
+ cmd: gcc -c base.c -o out/libbase.a
779
+
780
+ middleware:
781
+ deps: [base]
782
+ outputs:
783
+ - lib: "out/libmiddleware.a"
784
+ cmd: |
785
+ # Reference the base library
786
+ gcc -c middleware.c {{ dep.base.outputs.lib }} -o out/libmiddleware.a
787
+
788
+ app:
789
+ deps: [middleware]
790
+ cmd: |
791
+ # Reference middleware, which transitively used base
792
+ gcc main.c {{ dep.middleware.outputs.lib }} -o app
793
+ ```
794
+
795
+ **Key Behaviors:**
796
+
797
+ - **Template resolution**: Output references are resolved during dependency graph planning (in topological order)
798
+ - **Fail-fast validation**: Errors are caught before execution begins
799
+ - **Clear error messages**: If an output name doesn't exist, you get a list of available named outputs
800
+ - **Backward compatible**: Existing anonymous outputs (`outputs: ["file.txt"]`) work unchanged
801
+ - **Automatic input tracking**: Named outputs are automatically tracked as implicit inputs for dependent tasks
802
+
803
+ **Error Messages:**
804
+
805
+ If you reference a non-existent output:
806
+
807
+ ```yaml
808
+ tasks:
809
+ build:
810
+ outputs:
811
+ - bundle: "dist/app.js"
812
+ cmd: webpack build
813
+
814
+ deploy:
815
+ deps: [build]
816
+ cmd: echo "{{ dep.build.outputs.missing }}" # Error!
817
+ ```
818
+
819
+ You'll get a clear error before execution:
820
+
821
+ ```
822
+ Task 'deploy' references output 'missing' from task 'build',
823
+ but 'build' has no output named 'missing'.
824
+ Available named outputs in 'build': bundle
825
+ Hint: Define named outputs like: outputs: [{ missing: 'path/to/file' }]
826
+ ```
827
+
828
+ **Use Cases:**
829
+
830
+ - **Dynamic artifact names**: Pass generated filenames between tasks
831
+ - **Build metadata**: Reference manifests, checksums, or version files
832
+ - **Multi-stage builds**: Chain compilation steps with specific output references
833
+ - **Deployment pipelines**: Reference exact artifacts to deploy
834
+ - **Configuration propagation**: Pass generated config files through build stages
835
+
836
+ ### Self-References
837
+
838
+ Tasks can reference their own named inputs and outputs using `{{ self.inputs.name }}` and `{{ self.outputs.name }}` 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
+ - **Referencing inputs**: `{{ self.inputs.input_name }}`
866
+ - **Referencing outputs**: `{{ self.outputs.output_name }}`
867
+ - **Mixed format**: Can combine named and anonymous inputs/outputs in the same task
868
+
869
+ **Why Use Self-References?**
870
+
871
+ Self-references follow the DRY (Don't Repeat Yourself) principle:
872
+
873
+ ```yaml
874
+ # Without self-references - repetitive
875
+ tasks:
876
+ build:
877
+ inputs: [src/app-{{ var.version }}.c]
878
+ outputs: [build/app-{{ var.version }}.o]
879
+ cmd: gcc src/app-{{ var.version }}.c -o build/app-{{ var.version }}.o
880
+
881
+ # With self-references - DRY
882
+ tasks:
883
+ build:
884
+ inputs:
885
+ - source: src/app-{{ var.version }}.c
886
+ outputs:
887
+ - object: build/app-{{ var.version }}.o
888
+ cmd: gcc {{ self.inputs.source }} -o {{ self.outputs.object }}
889
+ ```
890
+
891
+ **Working with Variables:**
892
+
893
+ Self-references work seamlessly with variables:
894
+
895
+ ```yaml
896
+ variables:
897
+ platform: linux
898
+ arch: x86_64
899
+
900
+ tasks:
901
+ compile:
902
+ inputs:
903
+ - src: src/{{ var.platform }}/main.c
904
+ - header: include/{{ var.arch }}/defs.h
905
+ outputs:
906
+ - binary: build/{{ var.platform }}-{{ var.arch }}/app
907
+ cmd: |
908
+ gcc {{ self.inputs.src }} \
909
+ -include {{ self.inputs.header }} \
910
+ -o {{ self.outputs.binary }}
911
+ ```
912
+
913
+ Variables are evaluated first, then self-references substitute the expanded paths.
914
+
915
+ **Working with Arguments:**
916
+
917
+ Self-references work with parameterized tasks:
918
+
919
+ ```yaml
920
+ tasks:
921
+ deploy:
922
+ args: [environment]
923
+ inputs:
924
+ - config: configs/{{ arg.environment }}/app.yaml
925
+ outputs:
926
+ - deployed: deployed-{{ arg.environment }}.yaml
927
+ cmd: |
928
+ validate {{ self.inputs.config }}
929
+ deploy {{ self.inputs.config }} > {{ self.outputs.deployed }}
930
+ ```
931
+
932
+ ```bash
933
+ tt deploy production # Uses configs/production/app.yaml
934
+ tt deploy staging # Uses configs/staging/app.yaml
935
+ ```
936
+
937
+ **Working with Dependency Outputs:**
938
+
939
+ Self-references and dependency references can be used together:
940
+
941
+ ```yaml
942
+ tasks:
943
+ build:
944
+ outputs:
945
+ - artifact: dist/app.js
946
+ cmd: webpack build
947
+
948
+ package:
949
+ deps: [build]
950
+ inputs:
951
+ - manifest: package.json
952
+ outputs:
953
+ - tarball: release.tar.gz
954
+ cmd: tar czf {{ self.outputs.tarball }} \
955
+ {{ self.inputs.manifest }} \
956
+ {{ dep.build.outputs.artifact }}
957
+ ```
958
+
959
+ **Mixed Named and Anonymous:**
960
+
961
+ Tasks can mix named and anonymous inputs/outputs:
962
+
963
+ ```yaml
964
+ tasks:
965
+ build:
966
+ inputs:
967
+ - config: build.yaml # Named - can reference
968
+ - src/**/*.c # Anonymous - tracked but not referenceable
969
+ outputs:
970
+ - binary: bin/app # Named - can reference
971
+ - bin/app.debug # Anonymous - tracked but not referenceable
972
+ cmd: build-tool --config {{ self.inputs.config }} --output {{ self.outputs.binary }}
973
+ ```
974
+
975
+ **Error Messages:**
976
+
977
+ If you reference a non-existent input or output:
978
+
979
+ ```yaml
980
+ tasks:
981
+ build:
982
+ inputs:
983
+ - src: input.txt
984
+ cmd: cat {{ self.inputs.missing }} # Error!
985
+ ```
986
+
987
+ You'll get a clear error before execution:
988
+
989
+ ```
990
+ Task 'build' references input 'missing' but has no input named 'missing'.
991
+ Available named inputs: src
992
+ Hint: Define named inputs like: inputs: [{ missing: 'path/to/file' }]
993
+ ```
994
+
995
+ Similarly, if you try to reference an anonymous input:
996
+
997
+ ```yaml
998
+ tasks:
999
+ build:
1000
+ inputs: [file.txt] # Anonymous input
1001
+ cmd: cat {{ self.inputs.src }} # Error!
1002
+ ```
1003
+
1004
+ You'll get:
1005
+
1006
+ ```
1007
+ Task 'build' references input 'src' but has no input named 'src'.
1008
+ Available named inputs: (none - all inputs are anonymous)
1009
+ Hint: Define named inputs like: inputs: [{ src: 'file.txt' }]
1010
+ ```
1011
+
1012
+ **Key Behaviors:**
1013
+
1014
+ - **Template resolution**: Self-references are resolved during dependency graph planning
1015
+ - **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
1018
+ - **Backward compatible**: Existing anonymous inputs/outputs work unchanged
1019
+ - **State tracking**: Works correctly with incremental execution and freshness checks
1020
+
1021
+ **Limitations:**
1022
+
1023
+ - **Anonymous not referenceable**: Only named inputs/outputs can be referenced
1024
+ - **Case sensitive**: `{{ self.inputs.Src }}` and `{{ self.inputs.src }}` are different
1025
+ - **Argument defaults**: Self-references in argument defaults are not supported (arguments are evaluated before self-references)
1026
+
1027
+ **Use Cases:**
1028
+
1029
+ - **Eliminate repetition**: Define complex paths once, use them multiple times
1030
+ - **Variable composition**: Combine variables with self-references for clean commands
1031
+ - **Multiple inputs/outputs**: Reference specific files when tasks have many
1032
+ - **Complex build pipelines**: Keep commands readable with named artifacts
1033
+ - **Glob patterns**: Use self-references with glob patterns for dynamic inputs
1034
+
1035
+ **Example: Multi-Stage Build:**
1036
+
1037
+ ```yaml
1038
+ variables:
1039
+ version: "2.1.0"
1040
+ platform: "linux"
1041
+
1042
+ tasks:
1043
+ prepare:
1044
+ outputs:
1045
+ - builddir: build/{{ var.platform }}-{{ var.version }}
1046
+ cmd: mkdir -p {{ self.outputs.builddir }}
1047
+
1048
+ compile:
1049
+ deps: [prepare]
1050
+ inputs:
1051
+ - source: src/main.c
1052
+ - headers: include/*.h
1053
+ outputs:
1054
+ - object: build/{{ var.platform }}-{{ var.version }}/main.o
1055
+ cmd: |
1056
+ gcc -c {{ self.inputs.source }} \
1057
+ -I include \
1058
+ -o {{ self.outputs.object }}
1059
+
1060
+ link:
1061
+ deps: [compile]
1062
+ outputs:
1063
+ - executable: build/{{ var.platform }}-{{ var.version }}/app
1064
+ - symbols: build/{{ var.platform }}-{{ var.version }}/app.sym
1065
+ cmd: |
1066
+ gcc build/{{ var.platform }}-{{ var.version }}/main.o \
1067
+ -o {{ self.outputs.executable }}
1068
+ objcopy --only-keep-debug {{ self.outputs.executable }} {{ self.outputs.symbols }}
1069
+ ```
1070
+
1071
+
1072
+ ### Private Tasks
1073
+
1074
+ Sometimes you may want to define helper tasks that are useful as dependencies but shouldn't be listed when users run `tt --list`. Mark these tasks as private:
1075
+
1076
+ ```yaml
1077
+ tasks:
1078
+ # Private helper task - hidden from --list
1079
+ setup-deps:
1080
+ private: true
1081
+ cmd: |
1082
+ npm install
1083
+ pip install -r requirements.txt
1084
+
1085
+ # Public task that uses the helper
1086
+ build:
1087
+ deps: [setup-deps]
1088
+ cmd: npm run build
1089
+ ```
1090
+
1091
+ **Behavior:**
1092
+ - `tt --list` shows only public tasks (`build` in this example)
1093
+ - Private tasks can still be executed: `tt setup-deps` works
1094
+ - Private tasks work normally as dependencies
1095
+ - By default, all tasks are public (`private: false`)
1096
+
1097
+ **Use cases:**
1098
+ - Internal helper tasks that shouldn't be run directly
1099
+ - Implementation details you want to hide from users
1100
+ - Shared setup tasks across multiple public tasks
1101
+
1102
+ Note that private tasks remain fully functional - they're only hidden from the list view. Users who know the task name can still execute it directly.
1103
+
1104
+
690
1105
  ## Environment Variables
691
1106
 
692
1107
  Task Tree supports reading environment variables in two ways:
@@ -1028,6 +1443,42 @@ At the start of each invocation, state is checked for invalid task hashes and no
1028
1443
 
1029
1444
  Task Tree provides several command-line options for controlling task execution:
1030
1445
 
1446
+ ### Recipe File Selection
1447
+
1448
+ Task Tree automatically discovers recipe files in the current directory and parent directories. You can also explicitly specify which file to use.
1449
+
1450
+ **Automatic Discovery:**
1451
+
1452
+ Task Tree searches for recipe files in the following order of preference:
1453
+
1454
+ 1. **Standard recipe files** (searched first, in order):
1455
+ - `tasktree.yaml`
1456
+ - `tasktree.yml`
1457
+ - `tt.yaml`
1458
+
1459
+ 2. **Import files** (searched only if no standard files found):
1460
+ - `*.tasks` files (e.g., `build.tasks`, `deploy.tasks`)
1461
+
1462
+ If multiple files of the same priority level exist in the same directory, Task Tree will report an error and ask you to specify which file to use with `--tasks`.
1463
+
1464
+ **Manual Selection:**
1465
+
1466
+ ```bash
1467
+ # Specify a recipe file explicitly
1468
+ tt --tasks build.tasks build
1469
+ tt -T custom-recipe.yaml test
1470
+
1471
+ # Useful when you have multiple recipe files in the same directory
1472
+ tt --tasks ci.yaml deploy
1473
+ ```
1474
+
1475
+ **File Search Behavior:**
1476
+
1477
+ - Task Tree searches **upward** from the current directory to find recipe files
1478
+ - **Standard recipe files** (`.yaml`/`.yml`) are always preferred over `*.tasks` files
1479
+ - `*.tasks` files are typically used for imports and are only used as main recipes if no standard files exist
1480
+ - The `.tasktree-state` file is created in the directory containing the recipe file
1481
+
1031
1482
  ### Execution Control
1032
1483
 
1033
1484
  ```bash
@@ -0,0 +1,14 @@
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,,
@@ -1,14 +0,0 @@
1
- tasktree/__init__.py,sha256=MVmdvKb3JdqLlo0x2_TPGMfgFC0HsDnP79HAzGnFnjI,1081
2
- tasktree/cli.py,sha256=Uhv0RNFrogjvqxBYKYIfxEPd0SdYAIpXH7SPGIxQnmk,20136
3
- tasktree/docker.py,sha256=qvja8G63uAcC73YMVY739egda1_CcBtoqzm0qIJU_Q8,14443
4
- tasktree/executor.py,sha256=QQcABThmof0MLTtwpJKpyqh80hr3YRIqqs3NZ-Ry-Bk,44873
5
- tasktree/graph.py,sha256=yITp71RfhJ7sdC-2zRf89SHYZqQyF3XVAnaqX-XnMdE,15821
6
- tasktree/hasher.py,sha256=0GrnCfwAXnwq_kpnHFFb12B5_2VFNXx6Ng7hTdcCyXo,4415
7
- tasktree/parser.py,sha256=o2AQuk9xeM9JCtyMzDeM0uJBsbJEhzPDxsPg9GwmJt4,88940
8
- tasktree/state.py,sha256=Cktl4D8iDZVd55aO2LqVyPrc-BnljkesxxkcMcdcfOY,3541
9
- tasktree/substitution.py,sha256=qG7SyEHn1PAKteWA0AgA1dUNbJfwQTupCLRq9FvOBD0,10724
10
- tasktree/types.py,sha256=R_YAyO5bMLB6XZnkMRT7VAtlkA_Xx6xu0aIpzQjrBXs,4357
11
- tasktree-0.0.18.dist-info/METADATA,sha256=u70mwnKCeb3sQkn5_B4cf0AOc8mI-FhvdTUbW0hoB3A,37234
12
- tasktree-0.0.18.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
13
- tasktree-0.0.18.dist-info/entry_points.txt,sha256=lQINlvRYnimvteBbnhH84A9clTg8NnpEjCWqWkqg8KE,40
14
- tasktree-0.0.18.dist-info/RECORD,,