File: README.md

package info (click to toggle)
python-taskipy 1.14.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 436 kB
  • sloc: python: 1,262; makefile: 16; sh: 1
file content (338 lines) | stat: -rw-r--r-- 10,738 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
<p align="center">
  <img src="https://github.com/illBeRoy/taskipy/raw/master/logo.svg" width="150" />
</p>

- [General](#general)
- [Requirements](#requirements)
- [Usage](#usage)
  - [Installation](#installation)
  - [Adding Tasks](#adding-tasks)
  - [Running Tasks](#running-tasks)
  - [Passing Command Line Args to Tasks](#passing-command-line-args-to-tasks)
  - [Composing Tasks](#composing-tasks)
    - [Grouping Subtasks Together](#grouping-subtasks-together)
    - [Pre Task Hook](#pre-task-hook)
    - [Post Task Hook](#post-task-hook)
  - [Using Variables](#using-variables)
    - [String Formatting](#string-formatting)
    - [Always Use Variables](#always-use-variables)
    - [Recursive Variables](#recursive-variables)
  - [Working directory](#working-directory)
  - [Using Taskipy Without Poetry](#using-taskipy-without-poetry)
    - [Installing With PIP](#installing-with-pip)
    - [Running Tasks](#running-tasks-1)
  - [Advanced Use Cases](#advanced-use-cases)
- [Contribution](#contribution)

## General

[![pypi](https://img.shields.io/pypi/v/taskipy?style=flat-square)](https://pypi.org/project/taskipy/)
[![pypi-downloads](https://img.shields.io/pypi/dm/taskipy?style=flat-square)](https://pypi.org/project/taskipy/)
[![Conda Version](https://img.shields.io/conda/vn/conda-forge/taskipy.svg)](https://anaconda.org/conda-forge/taskipy)
[![ci](https://img.shields.io/github/actions/workflow/status/taskipy/taskipy/ci.yml?style=flat-square)](https://github.com/taskipy/taskipy/actions/workflows/ci.yml)

**The complementary task runner for python.**

Every development pipeline has tasks, such as `test`, `lint` or `publish`. With taskipy, you can define those tasks in one file and run them with a simple command.

For instance, instead of running the following command:

```bash
python -m unittest tests/test_*.py
```

You can create a task called `test` and simply run:

```bash
poetry run task test
```

Or (if you're not using poetry):

```bash
task test
```

In addition, you can compose tasks and group them together, and also create dependencies between them.

This project is heavily inspired by npm's [run script command](https://docs.npmjs.com/cli/run-script).

## Requirements

Python 3.6 or newer.

Your project directory should include a valid `pyproject.toml` file, as specified in [PEP-518](https://www.python.org/dev/peps/pep-0518/).

## Usage

### Installation

To install taskipy as a dev dependency, simply run:

```bash
poetry add --dev taskipy
```

For Anaconda Python-based environments, taskipy is also available via conda-forge:

```bash
conda install -c conda-forge taskipy
```

### Adding Tasks

In your `pyproject.toml` file, add a new section called `[tool.taskipy.tasks]`.

The section is a key-value map, from the names of the task to the actual command that should be run in the shell.

There are two ways to define tasks. The easy way is to simply write the command down as a string:

__pyproject.toml__

```toml
[tool.taskipy.tasks]
test = "python -m unittest tests/test_*.py"
lint = "pylint tests taskipy"
```

Alternatively, you can define tasks more explicitly by declaring both the command and a helpful description using an inline table:

__pyproject.toml__

```toml
[tool.taskipy.tasks]
test = { cmd = "python -m unittest tests/test_*.py", help = "runs all unit tests" }
lint = { cmd = "pylint tests taskipy", help = "confirms code style using pylint" } 
```

The explicit notation is more verbose, but provides better context to anyone who uses the task.

### Running Tasks

In order to run a task, run the following command in your terminal:

```bash
$ poetry run task test
```

You can also list all existing tasks by running the following:

```bash
$ poetry run task --list
test                python -m unittest tests/test_*.py
lint                pylint tests taskipy
```

If you declared your task explicitly, you will see the description of the task by the side of the task's name:

```bash
$ poetry run task --list
test                runs all unit tests
lint                confirms code style using pylint
```

### Passing Command Line Args to Tasks

If you want to pass command line arguments to tasks (positional or named), simply append them to the end of the task command.

For example, running the above task like this:

```bash
poetry run task test -h
```

Is equivalent to running:

```bash
python -m unittest tests/test_*.py -h
```

And will show unittest's help instead of actually running it.

> ⚠️ Note: if you are using pre \ post hooks, do notice that arguments are not passed to them, only to the task itself.

### Composing Tasks

#### Grouping Subtasks Together

Some tasks are composed of multiple subtasks. Instead of writing plain shell commands and stringing them together, you can break them down into multiple subtasks:

```toml
[tool.taskipy.tasks]
lint_pylint = "pylint tests taskipy"
lint_mypy = "mypy tests taskipy"
```

And then create a composite task:

```toml
[tool.taskipy.tasks]
lint = "task lint_pylint && task lint_mypy"
lint_pylint = "pylint tests taskipy"
lint_mypy = "mypy tests taskipy"
```

#### Pre Task Hook

Tasks might also depend on one another. For example, tests might require some binaries to be built. Take the two following commands, for instance:

```toml
[tool.taskipy.tasks]
test = "python -m unittest tests/test_*.py"
build = "make ."
```

You could make tests depend on building, by using the **pretask hook**:

```toml
[tool.taskipy.tasks]
pre_test = "task build"
test = "python -m unittest tests/test_*.py"
build = "make ."
```

The pretask hook looks for `pre_<task_name>` task for a given `task_name`. It will run it before running the task itself. If the pretask fails, then taskipy will exit without running the task itself.

#### Post Task Hook

From time to time, you might want to run a task in conjunction with another. For example, you might want to run linting after a successful test run. Take the two following commands, for instance:

```toml
[tool.taskipy.tasks]
test = "python -m unittest tests/test_*.py"
lint = "pylint tests taskipy"
```

You could make tests trigger linting, by using the **posttask hook**:

```toml
[tool.taskipy.tasks]
test = "python -m unittest tests/test_*.py"
post_test = "task lint"
lint = "pylint tests taskipy"
```

The posttask hook looks for `post_<task_name>` task for a given `task_name`. It will run it after running the task itself. If the task failed, then taskipy will not run the posttask hook.

### Using Variables

In some cases, you might find yourself passing the same arguments over and over again. Let us take a look at the following tasks:

```toml
[tool.taskipy.tasks]
lint = "pylint path/to/my_module"
black = "black path/to/my_module"
```

As you can see, we provide the same path argument to both `pylint` and `black`.

In order to encourage DRY and improve your ability to change these values later on, taskipy actually lets you declare and reuse variables in your tasks:

```toml
[tool.taskipy.variables]
path = "path/to/my_module"

[tool.taskipy.tasks]
lint = { cmd = "pylint {path}", use_vars = true }
black = { cmd = "pylint {path}", use_vars = true }
```

We have made the following changes to our configuration:

1. We declared variables under `tool.taskipy.variables`
2. We flagged the relevant task using `use_vars` to note that they should use the variables
3. We replaced the repeating path with a `{path}` variable

#### String Formatting

The formatting of the task commands uses python's own `string.format` method, and therefore supports everything that python's [formatted string literals](https://docs.python.org/3/tutorial/inputoutput.html#formatted-string-literals) let you do.

#### Always Use Variables

Using variables is opt-in, which means that by default commands do **not** use them, and you will have to turn them on a task to task basis.

If you want to turn on `use_vars` globally, all you need to do is to declare that under taskipy's **settings** table:

```toml
[tool.taskipy.settings]
use_vars = true

[tool.taskipy.variables]
path = "path/to/my_module"

[tool.taskipy.tasks]
lint = "pylint {path}"
black = "black {path}"
```

#### Recursive Variables

If we want to use variables within other variables, we can utilize recursive variables. By default, variables are not recursive, but we can specify a variable to be recursive by setting the `recursive` key to `true`.

```toml
[tool.taskipy.settings]
use_vars = true

[tool.taskipy.variables]
src_dir = "src"
package_dir = { var = "{src_dir}/package", recursive = true }

[tool.taskipy.tasks]
echo = "echo {package_dir}"
```

In this example, we could run `task echo` and we would then see `src/package`.

### Working directory

By default, all tasks run from the directory where they are called. This makes possible to change folder and run flexible tasks depending on the current folder.

However, some tasks may need to always run in the same working directory, regardless from where they are called.

If you want tasks to always run relative to a specific path, you can use the `"cwd"` setting to define a current working directory of the task relative to the root of the project (where the `pyproject.toml` file is):

```toml
[tool.taskipy.tasks]
echo = { cmd = "python -c \"import os; print(os.getcwd())\"" , cwd = "."}
```

In this example, running `task echo` will print the directory path of the file `pyproject.toml` regardless of the folder that you call this task.

If you want to define `cwd` globally (setting all tasks to always run from the same working directory) you just need to declare that under taskipy's **settings** table:

```toml
[tool.taskipy.settings]
cwd = "."
```

### Using Taskipy Without Poetry

Taskipy was created with poetry projects in mind, but actually only requires a valid `pyproject.toml` file in your project's directory. As a result, you can use it even without poetry:

#### Installing With PIP

Install taskipy on your machine or in your virtualenv using:

```bash
pip install taskipy
```

#### Running Tasks

Head into your project's directory (don't forget to activate virtualenv if you're using one), and run the following command:

```bash
task TASK
```

Where `TASK` is the name of your task.

### Advanced Use Cases

If you have a more specific use case, you might not be the first to run into it! Head over to the [ADVANCED_FEATURES](./docs/ADVANCED_FEATURES.md) doc, and look it up.

## Contribution

All kinds of contributions are welcome! Feel free to request features and report bugs via issues, and contribute your own beautiful code via pull requests!

The taskipy project is maintained by [Roy Sommer](https://github.com/illBeRoy). If you're interested in joining the team, feel free to let me know!