Metadata-Version: 2.4
Name: time_executioner
Version: 0.1.0
Summary: Common library to time the execution of functions
Author-email: Barclay Loftus <barclay.loftus@rmdevmgmt.com>
License-Expression: MIT
Project-URL: Homepage, https://github.com/Rapid-Medical/time_executioner
Project-URL: Issues, https://github.com/Rapid-Medical/time_executioner/issues
Keywords: timing,profiling,performance,benchmark,logging,decorator,context-manager,async
Classifier: Development Status :: 4 - Beta
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Classifier: Topic :: System :: Benchmark
Classifier: Topic :: System :: Logging
Classifier: Typing :: Typed
Requires-Python: >=3.11
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: dev
Requires-Dist: build; extra == "dev"
Requires-Dist: flake8; extra == "dev"
Requires-Dist: mypy; extra == "dev"
Requires-Dist: pre-commit; extra == "dev"
Requires-Dist: pytest; extra == "dev"
Requires-Dist: pytest-asyncio; extra == "dev"
Requires-Dist: pytest-cov; extra == "dev"
Requires-Dist: twine; extra == "dev"
Dynamic: license-file

# Time Executioner

A simple common decorator and context manager library for timing and logging function calls in python,
including support for both sync and async function types.

Requires Python 3.11+. Fully type annotated and ships a `py.typed` marker, so
`mypy` and other type checkers see the annotations in your project.

## Installation

```bash
pip install time_executioner
```

## Usage

To use the `TimeExecutioner` package you can simply use the python decorator features around your method.

### Example Code

```python
from time_executioner import TimeExecutioner


@TimeExecutioner.log
def my_cool_method_to_time():
    x = 2
    # ...


# no difference for async methods:
@TimeExecutioner.log
async def my_cool_async_method_to_time():
    x = 2
    # ...


# or you can use it as a context manager
with TimeExecutioner.time("my-expensive-codeblock"):
    y = 4
    # ...
```

Which will result in automatic logging to the default logger:

```
my_cool_method_to_time() executed in 0.697 seconds
my_cool_async_method_to_time() executed in 0.173 seconds
time_execute.my-expensive-codeblock executed in 2.401 seconds
```

You can also provide specific logging levels in the decorator (`INFO` is the default) as a parameter.

```python
from time_executioner import TimeExecutioner


@TimeExecutioner.log(log_level="debug")
def my_cool_method_to_time():
    x = 2
    # ...


# or as a context manager: 
with TimeExecutioner.time("my-expensive-codeblock", log_level="critical"):
    sleep(1)
```

And, finally, if you'd like to provide a custom logger, assuming that implements the logging.Logger, that is also
supported:

```python
logger = EliteCustomLogger()
TimeExecutioner.set_logger(logger)
```

`set_logger()` sets the default for the whole process, so the last caller wins. If you
are writing a library, or share a process with code you do not control, pass `logger=`
per use instead — it overrides the default without mutating it:

```python
from time_executioner import TimeExecutioner


@TimeExecutioner.log(logger=my_logger)
def my_cool_method_to_time():
    ...


with TimeExecutioner.time("my-expensive-codeblock", logger=my_logger):
    ...
```

`TimeExecutioner.reset_logger()` restores the built-in default, which is useful for
undoing a `set_logger()` call in test teardown.

