birling 0.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- birling-0.1.0/.github/workflows/ci.yml +69 -0
- birling-0.1.0/.gitignore +41 -0
- birling-0.1.0/.python-version +1 -0
- birling-0.1.0/.readthedocs.yaml +21 -0
- birling-0.1.0/CHANGELOG.md +22 -0
- birling-0.1.0/LICENSE.txt +21 -0
- birling-0.1.0/PKG-INFO +82 -0
- birling-0.1.0/README.md +56 -0
- birling-0.1.0/birling/__init__.py +6 -0
- birling-0.1.0/birling/__main__.py +7 -0
- birling-0.1.0/birling/analysis.py +489 -0
- birling-0.1.0/birling/cli.py +109 -0
- birling-0.1.0/birling/config.py +273 -0
- birling-0.1.0/birling/measurement.py +240 -0
- birling-0.1.0/birling/py.typed +0 -0
- birling-0.1.0/birling/recognition.py +239 -0
- birling-0.1.0/birling/report.py +136 -0
- birling-0.1.0/birling/runtime.py +48 -0
- birling-0.1.0/birling/syntax.py +114 -0
- birling-0.1.0/docs/changelog.md +1 -0
- birling-0.1.0/docs/configuration.md +66 -0
- birling-0.1.0/docs/how-it-works.md +69 -0
- birling-0.1.0/docs/index.md +59 -0
- birling-0.1.0/docs/reference.md +61 -0
- birling-0.1.0/docs/usage.md +103 -0
- birling-0.1.0/justfile +83 -0
- birling-0.1.0/mkdocs.yml +47 -0
- birling-0.1.0/pyproject.toml +199 -0
- birling-0.1.0/release-notes/README.md +35 -0
- birling-0.1.0/scripts/extract_changelog.py +43 -0
- birling-0.1.0/tests/__init__.py +0 -0
- birling-0.1.0/tests/unit/__init__.py +0 -0
- birling-0.1.0/tests/unit/conftest.py +33 -0
- birling-0.1.0/tests/unit/test_analysis.py +519 -0
- birling-0.1.0/tests/unit/test_cli.py +189 -0
- birling-0.1.0/tests/unit/test_config.py +207 -0
- birling-0.1.0/tests/unit/test_main.py +16 -0
- birling-0.1.0/tests/unit/test_measurement.py +467 -0
- birling-0.1.0/tests/unit/test_package.py +20 -0
- birling-0.1.0/tests/unit/test_recognition.py +243 -0
- birling-0.1.0/tests/unit/test_report.py +171 -0
- birling-0.1.0/tests/unit/test_runtime.py +46 -0
- birling-0.1.0/tests/unit/test_syntax.py +133 -0
- birling-0.1.0/uv.lock +1418 -0
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
tags: ["[0-9]+.[0-9]+.[0-9]+*"]
|
|
7
|
+
pull_request:
|
|
8
|
+
|
|
9
|
+
concurrency:
|
|
10
|
+
group: ${{ github.workflow }}-${{ github.ref }}
|
|
11
|
+
cancel-in-progress: true
|
|
12
|
+
|
|
13
|
+
jobs:
|
|
14
|
+
checks:
|
|
15
|
+
name: checks + docs
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
steps:
|
|
18
|
+
- uses: actions/checkout@v7
|
|
19
|
+
- uses: astral-sh/setup-uv@v10.3.0
|
|
20
|
+
with:
|
|
21
|
+
enable-cache: true
|
|
22
|
+
- uses: extractions/setup-just@v4
|
|
23
|
+
- run: just check
|
|
24
|
+
- run: just docs-build
|
|
25
|
+
|
|
26
|
+
test:
|
|
27
|
+
name: test (${{ matrix.toxenv }})
|
|
28
|
+
runs-on: ubuntu-latest
|
|
29
|
+
strategy:
|
|
30
|
+
fail-fast: false
|
|
31
|
+
matrix:
|
|
32
|
+
toxenv: [py311, py312, py313, py314, py315]
|
|
33
|
+
steps:
|
|
34
|
+
- uses: actions/checkout@v7
|
|
35
|
+
- uses: astral-sh/setup-uv@v10.3.0
|
|
36
|
+
with:
|
|
37
|
+
enable-cache: true
|
|
38
|
+
- run: uv run tox run -e ${{ matrix.toxenv }}
|
|
39
|
+
|
|
40
|
+
publish:
|
|
41
|
+
name: publish
|
|
42
|
+
needs: [checks, test]
|
|
43
|
+
if: startsWith(github.ref, 'refs/tags/')
|
|
44
|
+
runs-on: ubuntu-latest
|
|
45
|
+
environment: pypi
|
|
46
|
+
permissions:
|
|
47
|
+
contents: write # create the GitHub release
|
|
48
|
+
id-token: write # publish to PyPI as a trusted publisher
|
|
49
|
+
steps:
|
|
50
|
+
- uses: actions/checkout@v7
|
|
51
|
+
with:
|
|
52
|
+
fetch-depth: 0 # the version comes from the tag
|
|
53
|
+
- uses: astral-sh/setup-uv@v10.3.0
|
|
54
|
+
# Outside the checkout, so the source package does not pick it up.
|
|
55
|
+
- run: uv run python scripts/extract_changelog.py "$GITHUB_REF_NAME" > "$RUNNER_TEMP/notes.md"
|
|
56
|
+
- run: uv build
|
|
57
|
+
# Skips files already on PyPI, so a rerun of a failed job can finish the release.
|
|
58
|
+
- run: uv publish --trusted-publishing always --check-url https://pypi.org/simple/birling/
|
|
59
|
+
- name: Create or update the GitHub release
|
|
60
|
+
env:
|
|
61
|
+
GH_TOKEN: ${{ github.token }}
|
|
62
|
+
run: |
|
|
63
|
+
PRERELEASE=""
|
|
64
|
+
if [[ "$GITHUB_REF_NAME" =~ (a|b|rc)[0-9]+$ ]]; then PRERELEASE="--prerelease"; fi
|
|
65
|
+
if gh release view "$GITHUB_REF_NAME" >/dev/null 2>&1; then
|
|
66
|
+
gh release edit "$GITHUB_REF_NAME" --notes-file "$RUNNER_TEMP/notes.md" $PRERELEASE
|
|
67
|
+
else
|
|
68
|
+
gh release create "$GITHUB_REF_NAME" --notes-file "$RUNNER_TEMP/notes.md" $PRERELEASE
|
|
69
|
+
fi
|
birling-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Python bytecode
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
|
|
5
|
+
# Packaging and build output
|
|
6
|
+
build/
|
|
7
|
+
dist/
|
|
8
|
+
wheels/
|
|
9
|
+
*.egg-info/
|
|
10
|
+
requirements.txt
|
|
11
|
+
|
|
12
|
+
# Environments
|
|
13
|
+
.venv/
|
|
14
|
+
.env
|
|
15
|
+
|
|
16
|
+
# Tests and coverage
|
|
17
|
+
.pytest_cache/
|
|
18
|
+
.tox/
|
|
19
|
+
.hypothesis/
|
|
20
|
+
.coverage
|
|
21
|
+
.coverage.*
|
|
22
|
+
htmlcov/
|
|
23
|
+
coverage.xml
|
|
24
|
+
test-reports/
|
|
25
|
+
|
|
26
|
+
# Documentation build output
|
|
27
|
+
site/
|
|
28
|
+
|
|
29
|
+
# Tool caches
|
|
30
|
+
.ruff_cache/
|
|
31
|
+
.pyrefly_cache/
|
|
32
|
+
|
|
33
|
+
# Editors and OS
|
|
34
|
+
.idea/
|
|
35
|
+
.vscode/
|
|
36
|
+
.DS_Store
|
|
37
|
+
|
|
38
|
+
# Agent instructions and settings, kept per checkout
|
|
39
|
+
CLAUDE.md
|
|
40
|
+
AGENTS.md
|
|
41
|
+
.claude/
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.14
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# Read the Docs configuration file
|
|
2
|
+
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
|
|
3
|
+
|
|
4
|
+
version: 2
|
|
5
|
+
|
|
6
|
+
build:
|
|
7
|
+
os: ubuntu-lts-latest
|
|
8
|
+
tools:
|
|
9
|
+
python: "latest"
|
|
10
|
+
jobs:
|
|
11
|
+
pre_create_environment:
|
|
12
|
+
- asdf plugin add uv
|
|
13
|
+
- asdf install uv latest
|
|
14
|
+
- asdf global uv latest
|
|
15
|
+
create_environment:
|
|
16
|
+
- uv venv "${READTHEDOCS_VIRTUALENV_PATH}"
|
|
17
|
+
install:
|
|
18
|
+
- UV_PROJECT_ENVIRONMENT="${READTHEDOCS_VIRTUALENV_PATH}" uv sync --frozen --no-default-groups --group docs
|
|
19
|
+
|
|
20
|
+
mkdocs:
|
|
21
|
+
configuration: mkdocs.yml
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project are documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
|
+
|
|
7
|
+
Unreleased changes are kept as news fragments in `release-notes/`, and collated into a dated section by towncrier at release time.
|
|
8
|
+
|
|
9
|
+
<!-- towncrier release notes start -->
|
|
10
|
+
|
|
11
|
+
## [0.1.0] - 2026-10-13
|
|
12
|
+
|
|
13
|
+
### Added
|
|
14
|
+
|
|
15
|
+
- The `birling` command, which finds the branches in a project's code that should log, checks whether each holds a log call, and reports a score for each module and in total:
|
|
16
|
+
|
|
17
|
+
- A minimum score, `fail-under` in the configuration or `--fail-under`, below which the command exits with status 1, so that a CI run can hold to it.
|
|
18
|
+
- Configuration in the `[tool.birling]` table of `pyproject.toml`: which kinds of branch should log, which exceptions never need a log, and how log calls are recognised, covering `logging`, structlog, loguru and a project's own helpers.
|
|
19
|
+
- A `# birling: ignore` comment on the line that opens a branch, which accepts that branch without a log.
|
|
20
|
+
- `--show-unlogged`, which lists each unlogged branch as `path:line`, with its unit and how the branch is selected.
|
|
21
|
+
- `--coverage-file`, which marks the unlogged branches that ran in the tests, read from coverage.py's data; it needs the `coverage` extra.
|
|
22
|
+
- A Python interface, `measure_source()` and `measure_paths()`, which the command is built on.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026-present Berislav Lopac <berislav@lopac.net>
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
birling-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: birling
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Measure how well Python code is covered by log calls.
|
|
5
|
+
Project-URL: documentation, https://birling.readthedocs.io
|
|
6
|
+
Project-URL: repository, https://github.com/berislavlopac/birling
|
|
7
|
+
Project-URL: issues, https://github.com/berislavlopac/birling/issues
|
|
8
|
+
Project-URL: changelog, https://birling.readthedocs.io/en/stable/changelog.html
|
|
9
|
+
Author-email: Berislav Lopac <berislav@lopac.net>
|
|
10
|
+
License-Expression: MIT
|
|
11
|
+
License-File: LICENSE.txt
|
|
12
|
+
Classifier: Development Status :: 3 - Alpha
|
|
13
|
+
Classifier: Programming Language :: Python
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
16
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.15
|
|
19
|
+
Classifier: Programming Language :: Python :: Implementation :: CPython
|
|
20
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
21
|
+
Classifier: Topic :: System :: Logging
|
|
22
|
+
Requires-Python: >=3.11
|
|
23
|
+
Provides-Extra: coverage
|
|
24
|
+
Requires-Dist: coverage>=7.16.2; extra == 'coverage'
|
|
25
|
+
Description-Content-Type: text/markdown
|
|
26
|
+
|
|
27
|
+
# birling
|
|
28
|
+
|
|
29
|
+
birling measures log coverage in Python projects: how well the code is covered by log calls, whether through the standard [`logging`](https://docs.python.org/3/library/logging.html) module, [structlog](https://www.structlog.org/), [loguru](https://github.com/Delgan/loguru) or a project's own helpers, the way [coverage.py](https://coverage.readthedocs.io/) measures how well it is covered by tests.
|
|
30
|
+
|
|
31
|
+
A handled exception that leaves no log is a failure nobody hears about. birling finds the places in the code where something should be logged, checks whether a log call is there, and gives the project a score that a CI run can hold to a minimum. By default, those places are `except` handlers that do not raise again.
|
|
32
|
+
|
|
33
|
+
```shell
|
|
34
|
+
$ birling shop
|
|
35
|
+
Name Branches Logged Score Unlogged
|
|
36
|
+
---------------------------------------------------
|
|
37
|
+
shop/orders.py 2 1 50% 12
|
|
38
|
+
shop/payments.py 2 1 50% 12
|
|
39
|
+
---------------------------------------------------
|
|
40
|
+
TOTAL 4 2 50%
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Installation
|
|
44
|
+
|
|
45
|
+
birling needs Python 3.11 or later and has no dependencies of its own. Install it from PyPI:
|
|
46
|
+
|
|
47
|
+
```shell
|
|
48
|
+
pip install birling
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
The `coverage` extra, `birling[coverage]`, adds coverage.py, which the command needs to mark the unlogged branches that ran in the tests.
|
|
52
|
+
|
|
53
|
+
## Usage
|
|
54
|
+
|
|
55
|
+
```shell
|
|
56
|
+
birling PATH... [--config FILE] [--fail-under SCORE] [--coverage-file FILE] [--show-unlogged]
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
The command reads its configuration from the `[tool.birling]` table of `pyproject.toml`, and exits with status 1 when the score is below the minimum:
|
|
60
|
+
|
|
61
|
+
```toml
|
|
62
|
+
[tool.birling]
|
|
63
|
+
fail-under = 80
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
The standard `logging` module needs no configuration; other logging libraries and a project's own logging helpers are described in the table.
|
|
67
|
+
|
|
68
|
+
## Documentation
|
|
69
|
+
|
|
70
|
+
The documentation covers the command, the configuration, how branches and log calls are found, and the Python interface. It is in `docs/`; `just docs` serves it locally.
|
|
71
|
+
|
|
72
|
+
## The name
|
|
73
|
+
|
|
74
|
+
> Log rolling, sometimes called birling, is a sparring sport involving two competitors, each standing on one end of a free-floating log in a body of water. The two battle to dislodge each other from the log while keeping their own footing on it by spinning and kicking it and various other means.
|
|
75
|
+
>
|
|
76
|
+
> — Wikipedia, [Logrolling (sport)](https://en.wikipedia.org/wiki/Logrolling_%28sport%29)
|
|
77
|
+
|
|
78
|
+
The lumberjacks' sport lends its name to a tool for keeping on top of a project's logs.
|
|
79
|
+
|
|
80
|
+
## Status
|
|
81
|
+
|
|
82
|
+
birling is experimental: its interface may change before the first release.
|
birling-0.1.0/README.md
ADDED
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# birling
|
|
2
|
+
|
|
3
|
+
birling measures log coverage in Python projects: how well the code is covered by log calls, whether through the standard [`logging`](https://docs.python.org/3/library/logging.html) module, [structlog](https://www.structlog.org/), [loguru](https://github.com/Delgan/loguru) or a project's own helpers, the way [coverage.py](https://coverage.readthedocs.io/) measures how well it is covered by tests.
|
|
4
|
+
|
|
5
|
+
A handled exception that leaves no log is a failure nobody hears about. birling finds the places in the code where something should be logged, checks whether a log call is there, and gives the project a score that a CI run can hold to a minimum. By default, those places are `except` handlers that do not raise again.
|
|
6
|
+
|
|
7
|
+
```shell
|
|
8
|
+
$ birling shop
|
|
9
|
+
Name Branches Logged Score Unlogged
|
|
10
|
+
---------------------------------------------------
|
|
11
|
+
shop/orders.py 2 1 50% 12
|
|
12
|
+
shop/payments.py 2 1 50% 12
|
|
13
|
+
---------------------------------------------------
|
|
14
|
+
TOTAL 4 2 50%
|
|
15
|
+
```
|
|
16
|
+
|
|
17
|
+
## Installation
|
|
18
|
+
|
|
19
|
+
birling needs Python 3.11 or later and has no dependencies of its own. Install it from PyPI:
|
|
20
|
+
|
|
21
|
+
```shell
|
|
22
|
+
pip install birling
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
The `coverage` extra, `birling[coverage]`, adds coverage.py, which the command needs to mark the unlogged branches that ran in the tests.
|
|
26
|
+
|
|
27
|
+
## Usage
|
|
28
|
+
|
|
29
|
+
```shell
|
|
30
|
+
birling PATH... [--config FILE] [--fail-under SCORE] [--coverage-file FILE] [--show-unlogged]
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
The command reads its configuration from the `[tool.birling]` table of `pyproject.toml`, and exits with status 1 when the score is below the minimum:
|
|
34
|
+
|
|
35
|
+
```toml
|
|
36
|
+
[tool.birling]
|
|
37
|
+
fail-under = 80
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
The standard `logging` module needs no configuration; other logging libraries and a project's own logging helpers are described in the table.
|
|
41
|
+
|
|
42
|
+
## Documentation
|
|
43
|
+
|
|
44
|
+
The documentation covers the command, the configuration, how branches and log calls are found, and the Python interface. It is in `docs/`; `just docs` serves it locally.
|
|
45
|
+
|
|
46
|
+
## The name
|
|
47
|
+
|
|
48
|
+
> Log rolling, sometimes called birling, is a sparring sport involving two competitors, each standing on one end of a free-floating log in a body of water. The two battle to dislodge each other from the log while keeping their own footing on it by spinning and kicking it and various other means.
|
|
49
|
+
>
|
|
50
|
+
> — Wikipedia, [Logrolling (sport)](https://en.wikipedia.org/wiki/Logrolling_%28sport%29)
|
|
51
|
+
|
|
52
|
+
The lumberjacks' sport lends its name to a tool for keeping on top of a project's logs.
|
|
53
|
+
|
|
54
|
+
## Status
|
|
55
|
+
|
|
56
|
+
birling is experimental: its interface may change before the first release.
|