Metadata-Version: 2.4
Name: computational_stopwatch
Version: 1.0.8
Summary: Simple stopwatch to easily print the elapsed time of a set of operations
Home-page: https://gitlab.com/luca.baronti/computational-stopwatch
Download-URL: https://pypi.org/project/computational_stopwatch/
Author: Luca Baronti
Author-email: lbaronti@gmail.com
License: MIT
Keywords: computation,time,elapsed time
Classifier: Development Status :: 5 - Production/Stable
Classifier: Intended Audience :: Developers
Classifier: Topic :: Software Development
Classifier: License :: OSI Approved :: MIT License
Classifier: Programming Language :: Python :: 3
Requires-Python: >=3.6
Description-Content-Type: text/markdown
License-File: LICENSE
Dynamic: author
Dynamic: author-email
Dynamic: classifier
Dynamic: description
Dynamic: description-content-type
Dynamic: download-url
Dynamic: home-page
Dynamic: keywords
Dynamic: license
Dynamic: license-file
Dynamic: requires-python
Dynamic: summary

# Computational Stopwatch

Simple stopwatch to easily print the elapsed time of a set of operations. It's a minimalistic library, but it is very useful in many real cases.

## Installation

```bash
pip install computational_stopwatch
```
or
```bash
conda install -c <your-anaconda-channel> computational_stopwatch
```

## Usage
The easiest way to use this tool is in conjunction with the **with** python statement:
```python
>> from computational_stopwatch import Stopwatch
>>
>> with Stopwatch():
>>  time.sleep(3) # <- simulates a computation 
Elapsed time 0:00:03.003106
```
Anything within the scope of the **with** statement will count against the elapsed time. An optional task name to be printed along the elapsed time (e.g. for better identification in a log) can be set in the constructor. This name will be prepended to the printed message. This is useful to track the elapsed time of several tasks ran in sequence.
```python
>> with Stopwatch("My short task"):
>>  time.sleep(3) # <- simulates a computation 
My short task complete. Elapsed time 0:00:03.003106
```
Alternatively to the use with the **with** statment, the class can be directly instantiated and the print function explicitly called.
```python
>> sw = Stopwatch()
>> time.sleep(3)
>> sw.print_elapsed_time()
Elapsed time 0:00:03.003280
```
or simply
```python
>> sw = Stopwatch()
>> time.sleep(3)
>> print(sw)
0:00:03.003269
```
The start time can be reset with the **reset_time** function and the **get_elapsed_time** method returns the unformatted elapsed time, which is useful for numerical comparisons.

Different **verbosity** levels can be set in the constructor, with 2 as the default level, with 1 only the time is printed when the object is deleted, and with 0 nothing is printed. This is convenient to directly assess the elapsed time in seconds without any rogue prints on deletion:
```python
>> sw = Stopwatch(verbosity=0)
>> time.sleep(3)
>> t = sw.get_elapsed_time()
>> print(t)
3.0032315254211426
```
By default, everything is printed on the standard output. Further or alternative streams can be set in the constructor. For instance, the folowing snipped: 
```python
>> log_file = open('/tmp/my_log_file.txt','w')
>> with Stopwatch("My logged task", streams=[sys.stdout, log_file]):
>>  time.sleep(3) # <- simulates a computation 
My logged task complete. Elapsed time 0:00:03.002731
```
prints the message both on the standard output as well as in the log file for future perusal.

## Releasing

Releases are cut by pushing a git tag; nothing is published by hand.

The version lives in exactly one place, `__version__` in
`computational_stopwatch/stopwatch.py`. Both `setup.py` and
`conda-recipe/meta.yaml` read it from there, so the PyPI and conda packages can
never disagree about what they ship.

### Release steps

1. **Bump the version** in `computational_stopwatch/stopwatch.py`:
   ```python
   __version__     = '1.0.6'
   ```
2. **Write the changelog entry** in `HISTORY.md`, with a heading that matches the
   new version exactly:
   ```markdown
   ## v1.0.6

   - what changed
   ```
3. **Commit onto `main`:**
   ```bash
   git checkout main
   git add computational_stopwatch/stopwatch.py HISTORY.md
   git commit -m 'release v1.0.6'
   ```
4. **Tag and push.** The tag must be `v` + the version from step 1:
   ```bash
   git tag -a v1.0.6 -m 'v1.0.6'
   git push origin main --follow-tags
   ```
5. **Watch the pipeline** in GitLab → Build → Pipelines. On success the release
   is live on both indexes:
   ```bash
   pip install computational_stopwatch==1.0.6
   conda install -c <your-anaconda-channel> computational_stopwatch=1.0.6
   ```

### What the pipeline does

The `v*` tag triggers `.gitlab-ci.yml`, which runs three stages:

| Stage | Job | What it does |
| --- | --- | --- |
| `verify` | `verify tag` | Refuses the release unless the tag matches `__version__`, the tagged commit is an ancestor of `main`, and `HISTORY.md` has the matching section |
| `build` | `build sdist and wheel` | `python -m build` plus `twine check` |
| `release` | `publish to pypi` | Uploads `dist/*` to PyPI |
| `release` | `publish to anaconda` | `conda build conda-recipe` and uploads the `noarch` package to anaconda.org |

If `verify tag` fails, nothing is uploaded anywhere — fix the mismatch, delete
the tag (`git tag -d v1.0.6 && git push origin :refs/tags/v1.0.6`), and tag again.

### Required CI/CD variables

Set these in GitLab → Settings → CI/CD → Variables, all **Masked** and
**Protected**. No secret belongs in the repository.

| Variable | Value |
| --- | --- |
| `PYPI_API_TOKEN` | PyPI API token, including the `pypi-` prefix |
| `ANACONDA_API_TOKEN` | anaconda.org token with *allow write* permission |
| `ANACONDA_USER` | anaconda.org user or organisation to upload into |

Because the variables are Protected, add `v*` under Settings → Repository →
**Protected tags**, otherwise the release jobs cannot see them.

### Running the tests

The suite is developer-only and is not part of any published package.

```bash
pip install -e . pytest
pytest
```

It runs in the `verify` stage of the pipeline on every branch, merge request and
tag, and a tagged release will not publish unless it is green.

### Building locally

```bash
python -m build                             # dist/*.whl, dist/*.tar.gz
conda build conda-recipe -c conda-forge     # noarch conda package
```


# Versions History

## v1.0.8

- package version (pip and conda) is now derived directly from the git tag via `setuptools_scm`, instead of a hardcoded `__version__`

## v1.0.5

- minor fix

## v1.0.4

- added `HISTORY.md` in the pip package for compatibility with the conda packaging

## v1.0.3

- added ```__str__ ``` function to easily include just the time stamp inside other strings

## v1.0.2

- updated the README
- added multiple streams functionality

## v1.0.1

- minor fixes

## v1.0.0

- first reelease
