0
# Variables
1
2
Template variable system with recursive variable support for DRY task configuration and flexible command composition.
3
4
## Capabilities
5
6
### Variable Class
7
8
Represents a single variable with its value and recursion configuration.
9
10
```python { .api }
11
class Variable:
12
def __init__(self, name: str, value: str, recursive: bool):
13
"""
14
Create a Variable instance.
15
16
Args:
17
name: Variable name identifier
18
value: Variable value (may contain template references)
19
recursive: Whether variable supports recursive substitution
20
"""
21
```
22
23
### Variable Properties
24
25
Access to variable metadata and configuration.
26
27
```python { .api }
28
@property
29
def name(self) -> str:
30
"""Variable name identifier."""
31
32
@property
33
def value(self) -> str:
34
"""Variable value string."""
35
36
@property
37
def recursive(self) -> bool:
38
"""Whether variable supports recursive substitution."""
39
```
40
41
## Usage Examples
42
43
### Basic Variable Usage
44
45
```python
46
from taskipy.variable import Variable
47
48
# Simple variable
49
var = Variable('src_path', 'src/mypackage', False)
50
print(f"Variable: {var.name} = {var.value}")
51
52
# Recursive variable
53
recursive_var = Variable('full_path', '{base_path}/mypackage', True)
54
print(f"Recursive: {recursive_var.recursive}")
55
```
56
57
### Variable Configuration
58
59
Variables are typically configured in pyproject.toml rather than created directly:
60
61
```toml
62
[tool.taskipy.variables]
63
src_dir = "src"
64
test_dir = "tests"
65
package_name = "mypackage"
66
```
67
68
## Variable Definition Formats
69
70
### Simple String Variables
71
72
Direct value assignment:
73
74
```toml
75
[tool.taskipy.variables]
76
src_path = "src/mypackage"
77
test_path = "tests"
78
python_version = "3.9"
79
```
80
81
### Recursive Variables
82
83
Variables that reference other variables:
84
85
```toml
86
[tool.taskipy.variables]
87
base_dir = "src"
88
package_dir = { var = "{base_dir}/mypackage", recursive = true }
89
test_path = { var = "{package_dir}/tests", recursive = true }
90
```
91
92
## Variable Substitution
93
94
### Basic Substitution
95
96
Use variables in task commands with Python string formatting:
97
98
```toml
99
[tool.taskipy.variables]
100
src_path = "src/mypackage"
101
test_path = "tests"
102
103
[tool.taskipy.tasks]
104
lint = { cmd = "pylint {src_path}", use_vars = true }
105
test = { cmd = "pytest {test_path}", use_vars = true }
106
```
107
108
### Global Variable Usage
109
110
Enable variables for all tasks:
111
112
```toml
113
[tool.taskipy.settings]
114
use_vars = true
115
116
[tool.taskipy.variables]
117
src_path = "src/mypackage"
118
test_path = "tests"
119
120
[tool.taskipy.tasks]
121
lint = "pylint {src_path}"
122
test = "pytest {test_path}"
123
```
124
125
### Per-Task Variable Control
126
127
Control variable usage per task:
128
129
```toml
130
[tool.taskipy.variables]
131
src_path = "src/mypackage"
132
133
[tool.taskipy.tasks]
134
lint = { cmd = "pylint {src_path}", use_vars = true }
135
simple_task = "echo 'No variables here'" # use_vars defaults to false
136
```
137
138
## Recursive Variables
139
140
### Simple Recursion
141
142
Variables that reference other variables:
143
144
```toml
145
[tool.taskipy.variables]
146
base_dir = "src"
147
package_dir = { var = "{base_dir}/mypackage", recursive = true }
148
149
[tool.taskipy.tasks]
150
lint = { cmd = "pylint {package_dir}", use_vars = true }
151
# Resolves to: pylint src/mypackage
152
```
153
154
### Multi-Level Recursion
155
156
Complex variable dependency chains:
157
158
```toml
159
[tool.taskipy.variables]
160
root = "."
161
src_dir = { var = "{root}/src", recursive = true }
162
package_dir = { var = "{src_dir}/mypackage", recursive = true }
163
module_dir = { var = "{package_dir}/core", recursive = true }
164
165
[tool.taskipy.tasks]
166
lint = { cmd = "pylint {module_dir}", use_vars = true }
167
# Resolves to: pylint ./src/mypackage/core
168
```
169
170
### Circular Dependency Detection
171
172
Taskipy detects and prevents circular variable dependencies:
173
174
```toml
175
[tool.taskipy.variables]
176
var_a = { var = "{var_b}/path", recursive = true }
177
var_b = { var = "{var_a}/other", recursive = true }
178
# This configuration will raise CircularVariableError
179
```
180
181
## Advanced Variable Patterns
182
183
### Environment-Specific Variables
184
185
```toml
186
[tool.taskipy.variables]
187
env = "development"
188
db_host = { var = "db-{env}.example.com", recursive = true }
189
api_url = { var = "https://api-{env}.example.com", recursive = true }
190
191
[tool.taskipy.tasks]
192
test_integration = { cmd = "pytest --db-host {db_host}", use_vars = true }
193
```
194
195
### Path Management
196
197
```toml
198
[tool.taskipy.variables]
199
project_root = "."
200
src_dir = { var = "{project_root}/src", recursive = true }
201
tests_dir = { var = "{project_root}/tests", recursive = true }
202
docs_dir = { var = "{project_root}/docs", recursive = true }
203
build_dir = { var = "{project_root}/build", recursive = true }
204
205
[tool.taskipy.tasks]
206
lint = { cmd = "pylint {src_dir} {tests_dir}", use_vars = true }
207
test = { cmd = "pytest {tests_dir}", use_vars = true }
208
docs = { cmd = "sphinx-build {docs_dir} {build_dir}/docs", use_vars = true }
209
```
210
211
### Configuration Templates
212
213
```toml
214
[tool.taskipy.variables]
215
python_version = "3.9"
216
package_name = "mypackage"
217
test_pattern = "test_*.py"
218
coverage_threshold = "90"
219
220
[tool.taskipy.tasks]
221
test = {
222
cmd = "python{python_version} -m pytest {test_pattern} --cov={package_name} --cov-fail-under={coverage_threshold}",
223
use_vars = true
224
}
225
```
226
227
## String Formatting Features
228
229
### Python Format Strings
230
231
Variables use Python's `str.format()` method, supporting all formatting options:
232
233
```toml
234
[tool.taskipy.variables]
235
version = "1.2.3"
236
width = "80"
237
238
[tool.taskipy.tasks]
239
version_info = { cmd = "echo 'Version: {version:>10}'", use_vars = true }
240
banner = { cmd = "echo '{version:=^{width}}'", use_vars = true }
241
```
242
243
### Conditional Formatting
244
245
```toml
246
[tool.taskipy.variables]
247
debug = "true"
248
log_level = "DEBUG"
249
250
[tool.taskipy.tasks]
251
run_app = {
252
cmd = "python app.py{' --debug' if debug == 'true' else ''} --log-level {log_level}",
253
use_vars = true
254
}
255
```
256
257
## Error Handling
258
259
### Missing Variables
260
261
```toml
262
[tool.taskipy.tasks]
263
broken_task = { cmd = "echo {undefined_var}", use_vars = true }
264
# Raises MalformedTaskError: undefined_var variable expected
265
```
266
267
### Invalid Variable Format
268
269
```toml
270
[tool.taskipy.variables]
271
invalid_var = 123 # Must be string or dict with 'var' key
272
# Raises InvalidVariableError
273
```
274
275
### Circular Dependencies
276
277
```toml
278
[tool.taskipy.variables]
279
a = { var = "{b}", recursive = true }
280
b = { var = "{a}", recursive = true }
281
# Raises CircularVariableError
282
```
283
284
## Variable Resolution Process
285
286
1. **Collection**: Gather all defined variables
287
2. **Classification**: Separate recursive and non-recursive variables
288
3. **Initial Resolution**: Resolve non-recursive variables first
289
4. **Recursive Resolution**: Iteratively resolve recursive variables
290
5. **Circular Detection**: Detect and prevent infinite loops
291
6. **Template Application**: Apply resolved variables to task commands
292
293
## Best Practices
294
295
### Naming Conventions
296
297
```toml
298
[tool.taskipy.variables]
299
# Use descriptive names
300
src_directory = "src"
301
test_directory = "tests"
302
python_executable = "python3.9"
303
304
# Use consistent naming patterns
305
api_host_dev = "api-dev.example.com"
306
api_host_prod = "api-prod.example.com"
307
```
308
309
### Variable Organization
310
311
```toml
312
[tool.taskipy.variables]
313
# Group related variables
314
# Paths
315
src_path = "src"
316
test_path = "tests"
317
docs_path = "docs"
318
319
# Configuration
320
python_version = "3.9"
321
coverage_threshold = "85"
322
323
# Derived paths
324
package_path = { var = "{src_path}/mypackage", recursive = true }
325
```
326
327
### Avoiding Complexity
328
329
```toml
330
# Good: Simple, clear variable usage
331
[tool.taskipy.variables]
332
test_dir = "tests"
333
334
[tool.taskipy.tasks]
335
test = { cmd = "pytest {test_dir}", use_vars = true }
336
337
# Avoid: Overly complex recursive chains
338
[tool.taskipy.variables]
339
a = { var = "{b}/{c}", recursive = true }
340
b = { var = "{d}/{e}", recursive = true }
341
c = { var = "{f}", recursive = true }
342
# This becomes hard to debug and maintain
343
```