Basic support for task pre and post tasks

- [x] Pre run tasks
- [x] Post run tasks
- [x] _(added bonus)_ `__call__` support on task

This allows a structure such as:

```python
@task
def test():
  pass

@task
def docs():
  pass

@task('test', 'docs', post=['publish'])
def build():
  # test and docs will run first, and after all is successful, publish
  pass

@task
def publish():
  pass
```