Metadata-Version: 2.1
Name: stacklog
Version: 1.0.0
Summary: Stack log messages
Home-page: https://github.com/micahjsmith/stacklog
Author: Micah Smith
Author-email: micahjsmith@gmail.com
License: MIT license
Keywords: stacklog
Platform: UNKNOWN
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python :: 2
Classifier: Programming Language :: Python :: 2.7
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.4
Classifier: Programming Language :: Python :: 3.5
Classifier: Programming Language :: Python :: 3.6
Classifier: Programming Language :: Python :: 3.7
Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
Description-Content-Type: text/markdown
Provides-Extra: dev
Requires-Dist: bumpversion (>=0.5.3) ; extra == 'dev'
Requires-Dist: pip (>=9.0.1) ; extra == 'dev'
Requires-Dist: watchdog (>=0.8.3) ; extra == 'dev'
Requires-Dist: m2r (>=0.2.0) ; extra == 'dev'
Requires-Dist: Sphinx (>=1.7.1) ; extra == 'dev'
Requires-Dist: sphinx-rtd-theme (>=0.2.4) ; extra == 'dev'
Requires-Dist: autodocsumm (>=0.1.10) ; extra == 'dev'
Requires-Dist: flake8 (>=3.7.7) ; extra == 'dev'
Requires-Dist: isort (>=4.3.4) ; extra == 'dev'
Requires-Dist: autoflake (>=1.2) ; extra == 'dev'
Requires-Dist: autopep8 (>=1.4.3) ; extra == 'dev'
Requires-Dist: twine (>=1.10.0) ; extra == 'dev'
Requires-Dist: wheel (>=0.30.0) ; extra == 'dev'
Requires-Dist: coverage (>=4.5.1) ; extra == 'dev'
Requires-Dist: tox (>=2.9.1) ; extra == 'dev'
Requires-Dist: pytest (>=3.4.2) ; extra == 'dev'
Requires-Dist: pytest-cov (>=2.6.0) ; extra == 'dev'
Provides-Extra: test
Requires-Dist: pytest (>=3.4.2) ; extra == 'test'
Requires-Dist: pytest-cov (>=2.6.0) ; extra == 'test'

[![PyPI Shield](https://img.shields.io/pypi/v/stacklog.svg)](https://pypi.python.org/pypi/stacklog)
[![Downloads](https://pepy.tech/badge/stacklog)](https://pepy.tech/project/stacklog)
[![Travis CI Shield](https://travis-ci.org/micahjsmith/stacklog.svg?branch=master)](https://travis-ci.org/micahjsmith/stacklog)

# stacklog

Stack log messages

- Documentation: https://micahjsmith.github.io/stacklog
- Homepage: https://github.com/micahjsmith/stacklog

## Overview

Stacklog is a tiny Python library to stack log messages.

A stack-structured log is an approach to logging in which log messages are (conceptually)
pushed onto a stack and emitted only when the pusher returns. Stacklog provides a single
method, `stacklog`, which serves as either a decorator or a context manager. This is
exceptionally useful in small projects or one-off scripts.

This is illustrated best with an example:

```
with stacklog(print, 'Running some code'):
    with stacklog(print, 'Running some other code'):
        pass
```

This produces the following logging output:

```
Running some code...
Running some other code...
Running some other code...DONE
Running some code...DONE
```

When the code within a stacklog context completes, the provided message is echoed along with
the return status, one of `DONE` or `FAILURE`. That's pretty much it.

## Install

stacklog has been developed and tested on Python 2.7 and 3.4+.

```bash
pip install stacklog
```

## Quickstart

How often do you find yourself using the following logging anti-pattern in Python?

```python
import logging

def a():
    logging.info('Running a')
    do_something()
    logging.info('Done with a')

def b():
    logging.info('Running b')
    a()
    logging.info('Done with b')

try:
    b()
except:
    logging.info('There was an error running b')
```

The intention here is to log the beginning and end of procedure calls for use in debugging
or user monitoring. I call this an anti-pattern because:

- it requires excessive manual attention to writing/updating logging calls at entry/exit sites
- it results in redundant exception handling logic
- the resulting log messages can be misleading if errors occur

Instead, the approach taken by stacklog is to accomplish this using only decorators and
context managers.

### Usage as decorator

Here is the above example using the stacklog as a decorator:

```
@stacklog(logging.info, 'Running a')
def a():
    raise Exception

@stacklog(logging.info, 'Running b')
def b():
    a()

b()
```

This produces logging output:

```
INFO:root:Running b...
INFO:root:Running a...
INFO:root:Running a...FAILURE
INFO:root:Running b...FAILURE
```

### Usage as context manager

Here is another example using stacklog as a context manager:

```
>>> with stacklog(logging.info, 'Running some code'):
...     do_something()
...
INFO:root:Running some code...
INFO:root:Running some code...DONE
```

### Providing custom conditions

A *condition* is a tuple `exception, status`. If the provided exception is raised during the
execution of the provided code, the provided status is logged instead of the default
`FAILURE`.

```
>>> with stacklog(logging.info, 'Running some code', conditions=[(NotImplementedError,
'SKIPPED')]):
...     raise NotImplementedError
...
INFO:root:Running some code...
INFO:root:Running some code...SKIPPED
```


# History

## 1.0 (2019-12-10)

Initial release.


