tasktree 0.0.21__py3-none-any.whl → 0.0.23__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/types.py CHANGED
@@ -3,7 +3,6 @@
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
@@ -22,7 +21,9 @@ class HostnameType(click.ParamType):
22
21
  r"^(?=.{1,253}$)(?!-)[A-Za-z0-9-]{1,63}(?<!-)(\.[A-Za-z0-9-]{1,63})*\.?$"
23
22
  )
24
23
 
25
- def convert(self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]) -> str:
24
+ def convert(
25
+ self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
26
+ ) -> str:
26
27
  """
27
28
  @athena: 8d921e52bcf2
28
29
  """
@@ -41,11 +42,11 @@ class EmailType(click.ParamType):
41
42
  name = "email"
42
43
 
43
44
  # Basic email validation (RFC 5322 simplified)
44
- EMAIL_PATTERN = re.compile(
45
- r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$"
46
- )
45
+ EMAIL_PATTERN = re.compile(r"^[a-zA-Z0-9_.+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-.]+$")
47
46
 
48
- def convert(self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]) -> str:
47
+ def convert(
48
+ self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
49
+ ) -> str:
49
50
  """
50
51
  @athena: 25046aeb6e6f
51
52
  """
@@ -63,7 +64,9 @@ class IPType(click.ParamType):
63
64
 
64
65
  name = "ip"
65
66
 
66
- def convert(self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]) -> str:
67
+ def convert(
68
+ self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
69
+ ) -> str:
67
70
  """
68
71
  @athena: d57618e5ad89
69
72
  """
@@ -82,7 +85,9 @@ class IPv4Type(click.ParamType):
82
85
 
83
86
  name = "ipv4"
84
87
 
85
- def convert(self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]) -> str:
88
+ def convert(
89
+ self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
90
+ ) -> str:
86
91
  """
87
92
  @athena: 7ed2d17d1f1a
88
93
  """
@@ -101,7 +106,9 @@ class IPv6Type(click.ParamType):
101
106
 
102
107
  name = "ipv6"
103
108
 
104
- def convert(self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]) -> str:
109
+ def convert(
110
+ self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
111
+ ) -> str:
105
112
  """
106
113
  @athena: 4b101e4d54cf
107
114
  """
@@ -115,14 +122,16 @@ class IPv6Type(click.ParamType):
115
122
  class DateTimeType(click.ParamType):
116
123
  """
117
124
  Validates datetime in format YYYY-MM-DDTHH:MM:SS.
118
- @athena: c3bafa3e22e3
125
+ @athena: 0b935a25fb23
119
126
  """
120
127
 
121
128
  name = "datetime"
122
129
 
123
- def convert(self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]) -> str:
130
+ def convert(
131
+ self, value: Any, param: Optional[click.Parameter], ctx: Optional[click.Context]
132
+ ) -> str:
124
133
  """
125
- @athena: 13fa66adfe94
134
+ @athena: 9c7bb2d672cc
126
135
  """
127
136
  if isinstance(value, str):
128
137
  try:
@@ -130,7 +139,11 @@ class DateTimeType(click.ParamType):
130
139
  return value
131
140
  except ValueError:
132
141
  pass
133
- self.fail(f"{value!r} is not a valid datetime (expected YYYY-MM-DDTHH:MM:SS format)", param, ctx)
142
+ self.fail(
143
+ f"{value!r} is not a valid datetime (expected YYYY-MM-DDTHH:MM:SS format)",
144
+ param,
145
+ ctx,
146
+ )
134
147
 
135
148
 
136
149
  # Type registry for dynamic parameter creation
@@ -149,7 +162,11 @@ TYPE_MAPPING = {
149
162
  }
150
163
 
151
164
 
152
- def get_click_type(type_name: str, min_val: int | float | None = None, max_val: int | float | None = None) -> click.ParamType:
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:
153
170
  """
154
171
  Get Click parameter type by name with optional range constraints.
155
172
 
@@ -163,7 +180,7 @@ def get_click_type(type_name: str, min_val: int | float | None = None, max_val:
163
180
 
164
181
  Raises:
165
182
  ValueError: If type_name is not recognized
166
- @athena: d0912868676f
183
+ @athena: 523ff9c66303
167
184
  """
168
185
  if type_name not in TYPE_MAPPING:
169
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.21
3
+ Version: 0.0.23
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)
@@ -249,26 +251,26 @@ tasks:
249
251
  working_dir: subproject/ # Execution directory (default: project root)
250
252
  env: bash-strict # Execution environment (optional)
251
253
  private: false # Hide from --list output (default: false)
254
+ task_output: all # Control task output: all, out, err, on-err, none (default: all)
252
255
  args: # Task parameters
253
256
  - param1 # Simple argument
254
257
  - param2: { type: path, default: "." } # With type and default
255
258
  cmd: go build -o dist/binary # Command to execute
256
259
  ```
257
260
 
261
+ **Task name constraints:**
262
+ - Task names cannot contain dots (`.`) - they are reserved for namespacing imported tasks
263
+ - Example: `build.release` is invalid as a task name, but valid as a reference to task `release` in namespace `build`
264
+
258
265
  ### Commands
259
266
 
260
- **Single-line commands** are executed directly via the configured shell:
267
+ All commands are executed by writing them to temporary script files. This provides consistent behavior and better shell syntax support:
261
268
 
262
269
  ```yaml
263
270
  tasks:
264
271
  build:
265
272
  cmd: cargo build --release
266
- ```
267
-
268
- **Multi-line commands** are written to temporary script files for proper execution:
269
273
 
270
- ```yaml
271
- tasks:
272
274
  deploy:
273
275
  cmd: |
274
276
  mkdir -p dist
@@ -276,7 +278,7 @@ tasks:
276
278
  rsync -av dist/ server:/opt/app/
277
279
  ```
278
280
 
279
- Multi-line commands preserve shell syntax (line continuations, heredocs, etc.) and support shebangs on Unix/macOS.
281
+ Commands preserve shell syntax (line continuations, heredocs, etc.) and support shebangs on Unix/macOS.
280
282
 
281
283
  Or use folded blocks for long single-line commands:
282
284
 
@@ -292,7 +294,7 @@ tasks:
292
294
 
293
295
  ### Execution Environments
294
296
 
295
- Configure custom shell environments for task execution:
297
+ Configure custom shell environments for task execution. Use the `preamble` field to add initialization code to all commands:
296
298
 
297
299
  ```yaml
298
300
  environments:
@@ -300,17 +302,14 @@ environments:
300
302
 
301
303
  bash-strict:
302
304
  shell: bash
303
- args: ['-c'] # For single-line: bash -c "command"
304
- preamble: | # For multi-line: prepended to script
305
+ preamble: | # Prepended to all commands
305
306
  set -euo pipefail
306
307
 
307
308
  python:
308
309
  shell: python
309
- args: ['-c']
310
310
 
311
311
  powershell:
312
312
  shell: powershell
313
- args: ['-ExecutionPolicy', 'Bypass', '-Command']
314
313
  preamble: |
315
314
  $ErrorActionPreference = 'Stop'
316
315
 
@@ -339,8 +338,8 @@ tasks:
339
338
  4. Platform default (bash on Unix, cmd on Windows)
340
339
 
341
340
  **Platform defaults** when no environments are configured:
342
- - **Unix/macOS**: bash with `-c` args
343
- - **Windows**: cmd with `/c` args
341
+ - **Unix/macOS**: bash
342
+ - **Windows**: cmd
344
343
 
345
344
  ### Docker Environments
346
345
 
@@ -879,7 +878,8 @@ tasks:
879
878
  inputs: [src/app-{{ var.version }}.c]
880
879
  outputs: [build/app-{{ var.version }}.o]
881
880
  cmd: gcc src/app-{{ var.version }}.c -o build/app-{{ var.version }}.o
882
-
881
+ ```
882
+ ```yaml
883
883
  # With self-references - DRY
884
884
  tasks:
885
885
  build:
@@ -1621,6 +1621,14 @@ tt -o deploy
1621
1621
  # Override environment for all tasks
1622
1622
  tt --env python analyze
1623
1623
  tt -e powershell build
1624
+
1625
+ # Control task subprocess output display
1626
+ tt --task-output all build # Show both stdout and stderr (default)
1627
+ tt --task-output out test # Show only stdout
1628
+ tt --task-output err deploy # Show only stderr
1629
+ tt --task-output on-err ci # Show stderr only if task fails
1630
+ tt --task-output none build # Suppress all task output
1631
+ tt -O none build # Short form
1624
1632
  ```
1625
1633
 
1626
1634
  ### Information Commands
@@ -1649,8 +1657,6 @@ tt --init
1649
1657
  ```bash
1650
1658
  # Remove state file (reset task cache)
1651
1659
  tt --clean
1652
- tt --clean-state
1653
- tt --reset
1654
1660
  ```
1655
1661
 
1656
1662
  ### Common Workflows
@@ -1669,6 +1675,194 @@ tt --env python test
1669
1675
  tt --force deploy production
1670
1676
  ```
1671
1677
 
1678
+ ### Logging Control
1679
+
1680
+ Task Tree provides fine-grained control over diagnostic logging verbosity through the `--log-level` flag. This allows you to adjust the amount of information displayed about task execution, from minimal error-only output to detailed trace logging.
1681
+
1682
+ **Log Levels:**
1683
+
1684
+ ```bash
1685
+ # Show only fatal errors (malformed task files, missing dependencies)
1686
+ tt --log-level fatal build
1687
+
1688
+ # Show fatal errors and task execution failures
1689
+ tt --log-level error build
1690
+
1691
+ # Show errors and warnings (deprecated features, configuration issues)
1692
+ tt --log-level warn build
1693
+
1694
+ # Show normal execution progress (default)
1695
+ tt --log-level info build
1696
+ tt build # Same as above
1697
+
1698
+ # Show detailed diagnostics (variable values, resolved paths, environment details)
1699
+ tt --log-level debug build
1700
+
1701
+ # Show fine-grained execution tracing
1702
+ tt --log-level trace build
1703
+ ```
1704
+
1705
+ **Short Form:**
1706
+
1707
+ ```bash
1708
+ tt -L debug build
1709
+ tt -L trace test
1710
+ ```
1711
+
1712
+ **Case Insensitive:**
1713
+
1714
+ ```bash
1715
+ tt --log-level INFO build # Works
1716
+ tt --log-level Debug test # Works
1717
+ tt --log-level TRACE deploy # Works
1718
+ ```
1719
+
1720
+ **Common Use Cases:**
1721
+
1722
+ **Debugging Workflows:**
1723
+ ```bash
1724
+ # See variable substitution and resolved paths
1725
+ tt --log-level debug deploy production
1726
+
1727
+ # See detailed execution steps and internal state
1728
+ tt --log-level trace build
1729
+ ```
1730
+
1731
+ **CI/CD Environments:**
1732
+ ```bash
1733
+ # Suppress progress messages, show only errors
1734
+ tt --log-level error build test package
1735
+
1736
+ # Minimal output for clean build logs
1737
+ tt --log-level warn ci
1738
+ ```
1739
+
1740
+ **Normal Development:**
1741
+ ```bash
1742
+ # Default level shows normal execution progress
1743
+ tt build test
1744
+ ```
1745
+
1746
+ **Understanding Log Levels:**
1747
+
1748
+ - **FATAL** (least verbose): Only unrecoverable errors that prevent execution
1749
+ - **ERROR**: Fatal errors plus individual task failures
1750
+ - **WARN**: Errors plus warnings about deprecated features or configuration issues
1751
+ - **INFO** (default): Normal execution progress messages
1752
+ - **DEBUG**: Info plus variable values, resolved paths, environment configuration
1753
+ - **TRACE** (most verbose): Debug plus fine-grained execution tracing
1754
+
1755
+ Log levels are hierarchical - setting a higher verbosity level (e.g., DEBUG) includes all messages from lower levels (FATAL, ERROR, WARN, INFO).
1756
+
1757
+ **Note:** The `--log-level` flag controls Task Tree's own diagnostic messages. It does not affect the output of task commands themselves - use `--task-output` to control task subprocess output (see below).
1758
+
1759
+ ### Task Output Control
1760
+
1761
+ Task Tree provides fine-grained control over task subprocess output through the `--task-output` flag. This allows you to control whether tasks display their stdout, stderr, both, or neither, independent of Task Tree's own diagnostic logging.
1762
+
1763
+ **Output Modes:**
1764
+
1765
+ ```bash
1766
+ # Show both stdout and stderr (default)
1767
+ tt --task-output all build
1768
+ tt -O all build
1769
+ tt build # Same as above
1770
+
1771
+ # Show only stdout, suppress stderr
1772
+ tt --task-output out build
1773
+ tt -O out test
1774
+
1775
+ # Show only stderr, suppress stdout
1776
+ tt --task-output err build
1777
+ tt -O err deploy
1778
+
1779
+ # Show stderr only if the task fails (stdout always suppressed)
1780
+ tt --task-output on-err build
1781
+ tt -O on-err ci
1782
+
1783
+ # Suppress all task output
1784
+ tt --task-output none build
1785
+ tt -O none build
1786
+ ```
1787
+
1788
+ **Case Insensitive:**
1789
+
1790
+ ```bash
1791
+ tt --task-output ALL build # Works
1792
+ tt --task-output Out test # Works
1793
+ tt --task-output ON-ERR ci # Works
1794
+ ```
1795
+
1796
+ **Common Use Cases:**
1797
+
1798
+ **CI/CD Environments:**
1799
+ ```bash
1800
+ # Suppress task output, show only tasktree diagnostics
1801
+ tt --log-level info --task-output none build test
1802
+
1803
+ # Show errors only if they occur
1804
+ tt --log-level error --task-output on-err ci
1805
+ ```
1806
+
1807
+ **Debugging:**
1808
+ ```bash
1809
+ # Show only stderr to focus on warnings/errors
1810
+ tt --task-output err build
1811
+
1812
+ # Show everything for full visibility
1813
+ tt --log-level debug --task-output all build
1814
+ ```
1815
+
1816
+ **Clean Build Logs:**
1817
+ ```bash
1818
+ # Suppress noisy build output, show only tasktree progress
1819
+ tt --task-output none build package deploy
1820
+ ```
1821
+
1822
+ **Task-Level Configuration:**
1823
+
1824
+ Tasks can specify their own default output behavior in the recipe file:
1825
+
1826
+ ```yaml
1827
+ tasks:
1828
+ # Noisy task - suppress output by default
1829
+ install-deps:
1830
+ task_output: none
1831
+ cmd: npm install
1832
+
1833
+ # Let pytest manage its own output - it's already good at that
1834
+ test:
1835
+ cmd: pytest tests/
1836
+
1837
+ # Don't clutter CI logs with loads of output, unless something goes wrong
1838
+ build:
1839
+ task_output: on-err
1840
+ cmd: cargo build --release
1841
+ ```
1842
+
1843
+ **Understanding Output Modes:**
1844
+
1845
+ | Mode | Stdout | Stderr | Notes |
1846
+ |------|--------|--------|-------|
1847
+ | `all` | ✓ | ✓ | Default behavior, shows everything |
1848
+ | `out` | ✓ | ✗ | Good for capturing command results |
1849
+ | `err` | ✗ | ✓ | Focus on warnings and errors |
1850
+ | `on-err` | ✗ | ✓ (on failure) | Stderr buffered, shown only if task fails |
1851
+ | `none` | ✗ | ✗ | Silent execution, useful for noisy tasks |
1852
+
1853
+ **Override Behavior:**
1854
+
1855
+ - Command-line `--task-output` overrides task-level `task_output` settings for all tasks
1856
+ - Task-level `task_output` applies only if no command-line flag is provided
1857
+ - Default behavior is `all` if neither is specified
1858
+
1859
+ **Important Notes:**
1860
+
1861
+ - Task output control is independent of `--log-level` - you can suppress task output while still seeing tasktree diagnostics
1862
+ - The `on-err` mode buffers stderr in memory and only displays it if the task fails
1863
+ - Output suppression does not affect the task's execution - files are still created, commands still run
1864
+ - Task exit codes are always checked regardless of output mode
1865
+
1672
1866
  ## Example: Full Build Pipeline
1673
1867
 
1674
1868
  ```yaml
@@ -1680,6 +1874,7 @@ tasks:
1680
1874
  compile:
1681
1875
  desc: Build application binaries
1682
1876
  outputs: [target/release/app]
1877
+ task_output: "on-err" # We only care about seeing this if it fails.
1683
1878
  cmd: cargo build --release
1684
1879
 
1685
1880
  test-unit:
@@ -0,0 +1,17 @@
1
+ tasktree/__init__.py,sha256=I5ICzU0vQn0Nal-P9IMdtOzKr_henQRlCBf-66j6yak,1251
2
+ tasktree/cli.py,sha256=_jfaGLTLoFIl_LsjYgaHhIStd4JkC4UzFf0gDTUTGbA,24694
3
+ tasktree/console_logger.py,sha256=k8A23zfX0Jp3rjs0VIDIOCmksVehtnhC8HKH0o8ybFQ,2175
4
+ tasktree/docker.py,sha256=r9rejuxpYdHcXbLPLEwUJ1_KTyTRr29wIMnk6dtF1Ko,15363
5
+ tasktree/executor.py,sha256=dDOTKB0VCcgNcZVOyeQlnA-XvqDbeBhs7qr_1mfLq7E,51488
6
+ tasktree/graph.py,sha256=EQUEwJ3WW6tNH0_DSGM3OCwobwWJ73ok_Ih6KiraZEo,23637
7
+ tasktree/hasher.py,sha256=Tq16Hh8lnIDkLHkQr-COz-BRqAOzZ_cEA8YQTYHP5bc,6722
8
+ tasktree/logging.py,sha256=CQi7MMCgWxgnVW0xW_qw4zZF3LzNyobkzVCOyXVxqKw,3154
9
+ tasktree/parser.py,sha256=8gx3TbtcLLMnMELoz6plgq8TNgvvYrmONbTpM3sX5eM,101232
10
+ tasktree/process_runner.py,sha256=lDaU2rWUDcmF--QTV1GmNKe7cdT8Hi1uT4fziUUU3iM,13358
11
+ tasktree/state.py,sha256=R4ZXgfs_rwrOH9nEb4mOjuHa7gAVqi7QPVCi0CouNQA,3961
12
+ tasktree/substitution.py,sha256=W1aOYSGDtpd3R4j5Mhgh69vxPSYG6BijPeyPqMSQY7I,18663
13
+ tasktree/types.py,sha256=34-Y2Jn6c6FHem94PCqkNPzqthn-1-QX55smvjWRE_o,5015
14
+ tasktree-0.0.23.dist-info/METADATA,sha256=LSIKyFHsx1hvHRSr7kfppfiYHEvWmt9ybce2s-Dp5V8,60438
15
+ tasktree-0.0.23.dist-info/WHEEL,sha256=WLgqFyCfm_KASv4WHyYy0P3pM_m7J5L9k2skdKLirC8,87
16
+ tasktree-0.0.23.dist-info/entry_points.txt,sha256=lQINlvRYnimvteBbnhH84A9clTg8NnpEjCWqWkqg8KE,40
17
+ tasktree-0.0.23.dist-info/RECORD,,
@@ -1,14 +0,0 @@
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,,