byexamples / byexamples/byexample
Defer examples to last for cleaning up tasks (like the Go feature defer)
- Dominant language
- Python
- Stars
- 67
- Forks
- 9
- PR merge metrics
- No merged PRs in 30d
Description
**Describe the feature you'd like**
You can tag an example with `+defer` and its execution will be deferred at the end. If multiple examples have `+defer`, the execution order will be reversed as they were seen: first example seen last executed.
This is based on the [Go lang's defer feature](https://blog.golang.org/defer-panic-and-recover)
For example:
```python
>>> f = open()
>>> f.close() # byexample: +defer
>>> c = connect()
>>> c.close() # byexample: +defer
>>> do_something(f, c)
```
In the above example the examples will be executed like if they were written like this:
```python
>>> f = open()
>>> c = connect()
>>> do_something(f, c)
>>> c.close()
>>> f.close()
```
On failures, the fail fast mode enters in action (examples are skipped). For example if `c = connect()` fails, the equivalent execution would be:
```python
>>> f = open()
>>> c = connect() # <-- Imagine that this example fails
>>> do_something(f, c) # <-- This will be skipped
>>> c.close() # <-- This will be skipped
>>> f.close() # <-- This will NOT be skipped
```
The reasoning is that `c.close() # byexample: +defer` was seen *after* one example failed and therefore it should be skipped while `f.close() # byexample: +defer` was seen *before* the failing example so it should be executed as usual.
The equivalent file would be (note the `skip`):
```python
>>> f = open()
>>> c = connect() # <-- Imagine that this example fails
>>> do_something(f, c) # <-- This will be skipped
>>> c.close() # byexample: +skip # <-- This will be skipped
>>> f.close() # byexample: -skip # <-- This will NOT be skipped
```
`+defer` not only *"reschedule"* the example but also adds `-skip` to it if it was seen before a failing test or `+skip` it it was seen after.
An explicit `+skip` or `-skip` could be used to ensure a particular flag and it should be honored regardless of the default behavior of `+defer`: if `+skip +defer` is used, the example is deferred but always is skipped for example.
## Additional links (experience from people using `golang`)
The good, the bad and the ugly of `defer`:
- https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling-overview.md
- https://go.googlesource.com/proposal/+/master/design/go2draft-error-values-overview.md
- https://go.googlesource.com/proposal/+/master/design/go2draft-error-handling.md
- https://golang.org/doc/effective_go#errors
Not related, but interesting articles:
- https://devblogs.microsoft.com/oldnewthing/20050114-00/?p=36693
- https://devblogs.microsoft.com/oldnewthing/20040422-00/?p=39683
Contributor guide
Assessment
This issue has not been assessed yet.