badgeshield 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.
- badgeshield-0.1.0/.github/workflows/release.yml +116 -0
- badgeshield-0.1.0/.gitignore +190 -0
- badgeshield-0.1.0/CLAUDE.md +86 -0
- badgeshield-0.1.0/LICENSE.txt +21 -0
- badgeshield-0.1.0/PKG-INFO +371 -0
- badgeshield-0.1.0/README.md +339 -0
- badgeshield-0.1.0/docs/css/extra.css +289 -0
- badgeshield-0.1.0/docs/faq.md +227 -0
- badgeshield-0.1.0/docs/getting-started/cli_usage.md +319 -0
- badgeshield-0.1.0/docs/getting-started/usage.md +276 -0
- badgeshield-0.1.0/docs/helpful_links.md +1 -0
- badgeshield-0.1.0/docs/img/badgeshield.png +0 -0
- badgeshield-0.1.0/docs/img/badgeshield_192x192.png +0 -0
- badgeshield-0.1.0/docs/img/favicon/favicon-16x16.png +0 -0
- badgeshield-0.1.0/docs/img/favicon/favicon-32x32.png +0 -0
- badgeshield-0.1.0/docs/img/favicon/favicon.ico +0 -0
- badgeshield-0.1.0/docs/img/logo.png +0 -0
- badgeshield-0.1.0/docs/includes/abbreviations.md +0 -0
- badgeshield-0.1.0/docs/index.md +143 -0
- badgeshield-0.1.0/docs/installation.md +53 -0
- badgeshield-0.1.0/docs/overrides/PLACEHOLDER +0 -0
- badgeshield-0.1.0/docs/reference/batch_generator.md +2 -0
- badgeshield-0.1.0/docs/reference/batch_generator_cli.md +3 -0
- badgeshield-0.1.0/docs/reference/coverage.md +2 -0
- badgeshield-0.1.0/docs/reference/utils.md +1 -0
- badgeshield-0.1.0/mkdocs.yml +221 -0
- badgeshield-0.1.0/pyproject.toml +55 -0
- badgeshield-0.1.0/requirements.txt +4 -0
- badgeshield-0.1.0/setup.cfg +4 -0
- badgeshield-0.1.0/setup.py +45 -0
- badgeshield-0.1.0/src/badgeshield/__init__.py +17 -0
- badgeshield-0.1.0/src/badgeshield/__main__.py +3 -0
- badgeshield-0.1.0/src/badgeshield/_version.py +34 -0
- badgeshield-0.1.0/src/badgeshield/badge_generator.py +990 -0
- badgeshield-0.1.0/src/badgeshield/coverage.py +63 -0
- badgeshield-0.1.0/src/badgeshield/fonts/DejaVuSans.ttf +0 -0
- badgeshield-0.1.0/src/badgeshield/generate_badge_cli.py +362 -0
- badgeshield-0.1.0/src/badgeshield/templates/banner.svg +35 -0
- badgeshield-0.1.0/src/badgeshield/templates/circle.svg +50 -0
- badgeshield-0.1.0/src/badgeshield/templates/circle_frame.svg +48 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame1.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame10.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame11.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame2.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame3.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame4.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame5.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame6.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame7.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame8.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/frames/frame9.png +0 -0
- badgeshield-0.1.0/src/badgeshield/templates/label.svg +70 -0
- badgeshield-0.1.0/src/badgeshield/templates/pill.svg +34 -0
- badgeshield-0.1.0/src/badgeshield/utils.py +107 -0
- badgeshield-0.1.0/src/badgeshield.egg-info/PKG-INFO +371 -0
- badgeshield-0.1.0/src/badgeshield.egg-info/SOURCES.txt +67 -0
- badgeshield-0.1.0/src/badgeshield.egg-info/dependency_links.txt +1 -0
- badgeshield-0.1.0/src/badgeshield.egg-info/entry_points.txt +2 -0
- badgeshield-0.1.0/src/badgeshield.egg-info/requires.txt +7 -0
- badgeshield-0.1.0/src/badgeshield.egg-info/top_level.txt +1 -0
- badgeshield-0.1.0/tests/__init__.py +6 -0
- badgeshield-0.1.0/tests/conftest.py +44 -0
- badgeshield-0.1.0/tests/fixtures/test_logo.png +0 -0
- badgeshield-0.1.0/tests/snapshots/_lighten_hex_4c1d95.txt +1 -0
- badgeshield-0.1.0/tests/snapshots/banner_basic.svg +18 -0
- badgeshield-0.1.0/tests/snapshots/pill_basic.svg +17 -0
- badgeshield-0.1.0/tests/test_badge_generator.py +668 -0
- badgeshield-0.1.0/tests/test_coverage.py +123 -0
- badgeshield-0.1.0/tests/test_generate_badge_cli.py +288 -0
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
# ==============================================================================
|
|
2
|
+
# 🚢 Release Workflow — Project Caller
|
|
3
|
+
# ==============================================================================
|
|
4
|
+
# Save this file in YOUR PROJECT repo at:
|
|
5
|
+
# .github/workflows/release.yml
|
|
6
|
+
#
|
|
7
|
+
# TRIGGERS & JOB MATRIX:
|
|
8
|
+
#
|
|
9
|
+
# Event │ docs │ publish
|
|
10
|
+
# ─────────────────┼──────┼────────
|
|
11
|
+
# Push to main │ ✅ │ ⛔
|
|
12
|
+
# Push tag X.X.X │ ⛔ │ ✅
|
|
13
|
+
# Manual dispatch │ ✅ │ ⛔
|
|
14
|
+
#
|
|
15
|
+
# PUBLISH TARGET FLAG (controls where the package is published):
|
|
16
|
+
#
|
|
17
|
+
# publish-target: 'both' → TestPyPI first, then PyPI ← default
|
|
18
|
+
# publish-target: 'pypi' → PyPI only
|
|
19
|
+
# publish-target: 'testpypi' → TestPyPI only
|
|
20
|
+
#
|
|
21
|
+
# RELEASE FLOW:
|
|
22
|
+
# 1. Merge PRs to main as normal — docs deploy automatically
|
|
23
|
+
# 2. When ready to release, push a bare SemVer tag:
|
|
24
|
+
# git tag 1.2.1
|
|
25
|
+
# git push origin 1.2.1
|
|
26
|
+
# 3. The publish job runs: validate → test → build → testpypi → pypi
|
|
27
|
+
#
|
|
28
|
+
# SECRETS REQUIRED (Settings → Secrets and variables → Actions):
|
|
29
|
+
# TEST_PYPI_API_TOKEN — from test.pypi.org/manage/account/token/
|
|
30
|
+
# PYPI_API_TOKEN — from pypi.org (only if not using Trusted Publishing)
|
|
31
|
+
#
|
|
32
|
+
# PRE-REQUISITES (once per project):
|
|
33
|
+
#
|
|
34
|
+
# 1. Enable GitHub Pages:
|
|
35
|
+
# Settings → Pages → Source → GitHub Actions
|
|
36
|
+
#
|
|
37
|
+
# 2. Create GitHub Environments:
|
|
38
|
+
# Settings → Environments → New environment
|
|
39
|
+
# - "pypi" (real PyPI — add Required reviewers for safety)
|
|
40
|
+
# - "test-pypi" (TestPyPI sandbox — no reviewers needed)
|
|
41
|
+
#
|
|
42
|
+
# 3. Register Trusted Publisher on pypi.org:
|
|
43
|
+
# pypi.org → your project → Publishing → Add publisher
|
|
44
|
+
# owner = vertex-ai-automations
|
|
45
|
+
# repo = THIS-REPO-NAME
|
|
46
|
+
# workflow = release.yml
|
|
47
|
+
# env = pypi
|
|
48
|
+
#
|
|
49
|
+
# 4. Create docs/requirements.txt:
|
|
50
|
+
# mkdocs-material==9.5.18
|
|
51
|
+
# mkdocstrings[python]==0.24.3
|
|
52
|
+
#
|
|
53
|
+
# CUSTOMISE PER PROJECT:
|
|
54
|
+
# python-version — match your project's Python version
|
|
55
|
+
# test-command — your test runner command
|
|
56
|
+
# publish-target — 'both' | 'pypi' | 'testpypi'
|
|
57
|
+
# src-layout — true if you use a src/ directory layout
|
|
58
|
+
# mkdocs-strict — false to allow doc build warnings
|
|
59
|
+
# ==============================================================================
|
|
60
|
+
|
|
61
|
+
name: 🚢 Release
|
|
62
|
+
|
|
63
|
+
on:
|
|
64
|
+
push:
|
|
65
|
+
branches:
|
|
66
|
+
- main # Docs deploy only
|
|
67
|
+
tags:
|
|
68
|
+
- "*.*.*" # Publish only — bare SemVer e.g. 1.2.1
|
|
69
|
+
workflow_dispatch: # Manual trigger — docs only
|
|
70
|
+
|
|
71
|
+
jobs:
|
|
72
|
+
|
|
73
|
+
# ============================================================
|
|
74
|
+
# 📚 Deploy MkDocs to GitHub Pages
|
|
75
|
+
# Runs on: push to main, manual dispatch
|
|
76
|
+
# ============================================================
|
|
77
|
+
docs:
|
|
78
|
+
name: 📚 Deploy Docs
|
|
79
|
+
uses: vertex-ai-automations/shared-workflows/.github/workflows/publish-mkdocs.yml@main
|
|
80
|
+
permissions:
|
|
81
|
+
contents: read
|
|
82
|
+
pages: write
|
|
83
|
+
id-token: write
|
|
84
|
+
with:
|
|
85
|
+
python-version: "3.11"
|
|
86
|
+
docs-requirements: "docs/requirements.txt"
|
|
87
|
+
src-layout: true # ← set false if not using src/ layout
|
|
88
|
+
mkdocs-strict: true # ← set false to allow doc build warnings
|
|
89
|
+
secrets: inherit
|
|
90
|
+
|
|
91
|
+
# ============================================================
|
|
92
|
+
# 📦 Build and Publish Package
|
|
93
|
+
# Runs on: tag push only (tag guard is enforced inside the
|
|
94
|
+
# reusable workflow — non-tag pushes skip cleanly)
|
|
95
|
+
#
|
|
96
|
+
# publish-target controls which registries receive the package:
|
|
97
|
+
# 'both' → TestPyPI first, then PyPI (recommended)
|
|
98
|
+
# 'pypi' → PyPI only
|
|
99
|
+
# 'testpypi' → TestPyPI only
|
|
100
|
+
#
|
|
101
|
+
# No permissions block needed — declared inside python-publish.yml
|
|
102
|
+
# ============================================================
|
|
103
|
+
publish:
|
|
104
|
+
name: 📦 Publish Package
|
|
105
|
+
uses: vertex-ai-automations/shared-workflows/.github/workflows/python-publish.yml@main
|
|
106
|
+
permissions:
|
|
107
|
+
contents: read
|
|
108
|
+
id-token: write
|
|
109
|
+
with:
|
|
110
|
+
python-version: "3.11"
|
|
111
|
+
run-tests: true
|
|
112
|
+
test-command: "pytest tests/ -v --tb=short"
|
|
113
|
+
publish-target: "pypi" # 'both' | 'pypi' | 'testpypi'
|
|
114
|
+
use-trusted-publishing: false # set false to use PYPI_API_TOKEN instead
|
|
115
|
+
secrets: inherit
|
|
116
|
+
|
|
@@ -0,0 +1,190 @@
|
|
|
1
|
+
# Derived from basic .gitignore template for python projects:
|
|
2
|
+
# https://github.com/github/gitignore/blob/main/Python.gitignore
|
|
3
|
+
# Please maintain the alphabetic order of the section titles
|
|
4
|
+
# To debug why a file is being ignored, use the command:
|
|
5
|
+
# git check-ignore -v $my_ignored_file
|
|
6
|
+
|
|
7
|
+
# Byte-compiled / optimized / DLL files
|
|
8
|
+
__pycache__/
|
|
9
|
+
*.py[cod]
|
|
10
|
+
*$py.class
|
|
11
|
+
|
|
12
|
+
# C extensions
|
|
13
|
+
*.so
|
|
14
|
+
|
|
15
|
+
# Cython debug symbols
|
|
16
|
+
cython_debug/
|
|
17
|
+
|
|
18
|
+
# Celery stuff
|
|
19
|
+
celerybeat-schedule
|
|
20
|
+
celerybeat.pid
|
|
21
|
+
|
|
22
|
+
# Distribution / packaging
|
|
23
|
+
.Python
|
|
24
|
+
build/
|
|
25
|
+
develop-eggs/
|
|
26
|
+
dist/
|
|
27
|
+
downloads/
|
|
28
|
+
eggs/
|
|
29
|
+
.eggs/
|
|
30
|
+
lib/
|
|
31
|
+
lib64/
|
|
32
|
+
parts/
|
|
33
|
+
sdist/
|
|
34
|
+
var/
|
|
35
|
+
wheels/
|
|
36
|
+
share/python-wheels/
|
|
37
|
+
*.egg-info/
|
|
38
|
+
.installed.cfg
|
|
39
|
+
*.egg
|
|
40
|
+
MANIFEST
|
|
41
|
+
|
|
42
|
+
# Django stuff
|
|
43
|
+
*.log
|
|
44
|
+
local_settings.py
|
|
45
|
+
db.sqlite3
|
|
46
|
+
db.sqlite3-journal
|
|
47
|
+
|
|
48
|
+
# Environments
|
|
49
|
+
.env
|
|
50
|
+
.venv
|
|
51
|
+
env/
|
|
52
|
+
venv/
|
|
53
|
+
ENV/
|
|
54
|
+
env.bak/
|
|
55
|
+
venv.bak/
|
|
56
|
+
|
|
57
|
+
# Flask stuff
|
|
58
|
+
instance/
|
|
59
|
+
.webassets-cache
|
|
60
|
+
|
|
61
|
+
# Installer logs
|
|
62
|
+
pip-log.txt
|
|
63
|
+
pip-delete-this-directory.txt
|
|
64
|
+
|
|
65
|
+
# IPython
|
|
66
|
+
profile_default/
|
|
67
|
+
ipython_config.py
|
|
68
|
+
|
|
69
|
+
# Jupyter Notebook
|
|
70
|
+
*.ipynb_checkpoints
|
|
71
|
+
|
|
72
|
+
# mkdocs documentation
|
|
73
|
+
/site
|
|
74
|
+
|
|
75
|
+
# Model saving / checkpointing
|
|
76
|
+
*.pt
|
|
77
|
+
*.pth
|
|
78
|
+
*.ckpt
|
|
79
|
+
|
|
80
|
+
# mypy
|
|
81
|
+
.mypy_cache/
|
|
82
|
+
.dmypy.json
|
|
83
|
+
dmypy.json
|
|
84
|
+
|
|
85
|
+
# PyBuilder
|
|
86
|
+
.pybuilder/
|
|
87
|
+
target/
|
|
88
|
+
|
|
89
|
+
# PyCharm
|
|
90
|
+
# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
|
|
91
|
+
# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
|
|
92
|
+
# and can be added to the global gitignore or merged into this file. For a more nuclear
|
|
93
|
+
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
|
94
|
+
#.idea/
|
|
95
|
+
|
|
96
|
+
# PyInstaller
|
|
97
|
+
# Usually these files are written by a python script from a template
|
|
98
|
+
# before PyInstaller builds the exe, so as to inject date/other infos into it.
|
|
99
|
+
*.manifest
|
|
100
|
+
#*.spec
|
|
101
|
+
|
|
102
|
+
# pyenv
|
|
103
|
+
# For a library or package, you might want to ignore these files since the code is
|
|
104
|
+
# intended to run in multiple environments; otherwise, check them in:
|
|
105
|
+
# .python-version
|
|
106
|
+
|
|
107
|
+
# pipenv
|
|
108
|
+
# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
|
|
109
|
+
# However, in case of collaboration, if having platform-specific dependencies or dependencies
|
|
110
|
+
# having no cross-platform support, pipenv may install dependencies that don't work, or not
|
|
111
|
+
# install all needed dependencies.
|
|
112
|
+
# Pipfile.lock
|
|
113
|
+
|
|
114
|
+
# poetry
|
|
115
|
+
# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
|
|
116
|
+
# This is especially recommended for binary packages to ensure reproducibility, and is more
|
|
117
|
+
# commonly ignored for libraries.
|
|
118
|
+
# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
|
|
119
|
+
# poetry.lock
|
|
120
|
+
|
|
121
|
+
# PEP 582: https://peps.python.org/pep-0582/
|
|
122
|
+
# This PEP proposes to add to Python a mechanism to automatically recognize a __pypackages__
|
|
123
|
+
# directory and prefer importing packages installed in this location over user or global site-packages.
|
|
124
|
+
# This will avoid the steps to create, activate or deactivate virtual environments. Python will use
|
|
125
|
+
# the __pypackages__ from the base directory of the script when present.
|
|
126
|
+
__pypackages__/
|
|
127
|
+
|
|
128
|
+
# Pyre type checker
|
|
129
|
+
.pyre/
|
|
130
|
+
|
|
131
|
+
# pytype static type analyzer
|
|
132
|
+
.pytype/
|
|
133
|
+
|
|
134
|
+
# Rope project settings
|
|
135
|
+
.ropeproject
|
|
136
|
+
|
|
137
|
+
# SageMath parsed files
|
|
138
|
+
*.sage.py
|
|
139
|
+
|
|
140
|
+
# Scrapy stuff:
|
|
141
|
+
.scrapy
|
|
142
|
+
|
|
143
|
+
# Sphinx documentation
|
|
144
|
+
docs/build
|
|
145
|
+
# sphinx-gallery
|
|
146
|
+
docs/source/generated_examples/
|
|
147
|
+
docs/source/gen_modules/
|
|
148
|
+
docs/source/generated/
|
|
149
|
+
docs/source/sg_execution_times.rst
|
|
150
|
+
# pytorch-sphinx-theme gets installed here
|
|
151
|
+
docs/src
|
|
152
|
+
|
|
153
|
+
# Spyder project settings
|
|
154
|
+
.spyderproject
|
|
155
|
+
.spyproject
|
|
156
|
+
|
|
157
|
+
# System / program generated files
|
|
158
|
+
*.err
|
|
159
|
+
*.log
|
|
160
|
+
*.swp
|
|
161
|
+
.DS_Store
|
|
162
|
+
|
|
163
|
+
# Translations
|
|
164
|
+
*.mo
|
|
165
|
+
*.pot
|
|
166
|
+
|
|
167
|
+
# TorchX
|
|
168
|
+
*.torchxconfig
|
|
169
|
+
|
|
170
|
+
# Unit test / coverage reports
|
|
171
|
+
htmlcov/
|
|
172
|
+
.tox/
|
|
173
|
+
.nox/
|
|
174
|
+
.coverage
|
|
175
|
+
.coverage.*
|
|
176
|
+
.cache
|
|
177
|
+
nosetests.xml
|
|
178
|
+
coverage.xml
|
|
179
|
+
*.cover
|
|
180
|
+
*.py,cover
|
|
181
|
+
.hypothesis/
|
|
182
|
+
.pytest_cache/
|
|
183
|
+
cover/
|
|
184
|
+
|
|
185
|
+
# VSCode
|
|
186
|
+
.vscode/
|
|
187
|
+
|
|
188
|
+
# wandb
|
|
189
|
+
wandb/
|
|
190
|
+
.worktrees/
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# CLAUDE.md
|
|
2
|
+
|
|
3
|
+
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
4
|
+
|
|
5
|
+
## Project Overview
|
|
6
|
+
|
|
7
|
+
**badgeshield** is a Python package for generating customizable SVG badges. It supports 5 templates (DEFAULT, CIRCLE, CIRCLE_FRAME, PILL, BANNER), 4 visual styles, 51 predefined colors, logo embedding, batch processing, and both a programmatic API and CLI.
|
|
8
|
+
|
|
9
|
+
## Commands
|
|
10
|
+
|
|
11
|
+
### Testing
|
|
12
|
+
```bash
|
|
13
|
+
pytest tests/ -v --tb=short
|
|
14
|
+
# Run a single test file
|
|
15
|
+
pytest tests/test_badge_generator.py -v
|
|
16
|
+
# Run a single test
|
|
17
|
+
pytest tests/test_badge_generator.py::test_name -v
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
### Documentation
|
|
21
|
+
```bash
|
|
22
|
+
mkdocs build # Build docs
|
|
23
|
+
mkdocs serve # Serve docs locally
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
### Install for development
|
|
27
|
+
```bash
|
|
28
|
+
pip install -e .
|
|
29
|
+
pip install -r requirements.txt
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
### CLI usage
|
|
33
|
+
```bash
|
|
34
|
+
badgeshield single --left_text "Build" --left_color GREEN --badge_name build_badge.svg
|
|
35
|
+
badgeshield single --left_text "Status" --left_color "#555555" --badge_name s.svg --style gradient
|
|
36
|
+
badgeshield batch config.json --output_path ./badges/ --style rounded
|
|
37
|
+
badgeshield coverage coverage.xml --badge_name coverage.svg --metric line
|
|
38
|
+
badgeshield audit badge.svg # check SVG for external URL references
|
|
39
|
+
badgeshield audit badge.svg --json # machine-readable output
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
Note: `badge_name` must always end with `.svg`. The `--style` option accepts `FLAT | ROUNDED | GRADIENT | SHADOWED` (case-insensitive; defaults to `flat`). Per-entry `style` keys in batch JSON take priority over the CLI flag.
|
|
43
|
+
|
|
44
|
+
## Architecture
|
|
45
|
+
|
|
46
|
+
### Source layout (`src/badgeshield/`)
|
|
47
|
+
|
|
48
|
+
- **`badge_generator.py`**: Two main classes:
|
|
49
|
+
- `BadgeBatchGenerator`: Concurrent badge generation via `ThreadPoolExecutor`. Aggregates failures and raises `RuntimeError` with a summary if any badge fails.
|
|
50
|
+
- `BadgeGenerator`: Core SVG generation. Uses Jinja2 to render templates. Text width is calculated using Pillow's `ImageFont` (DejaVuSans.ttf) with a character-width dict fallback. Logo images are base64-embedded and can be color-tinted by converting to RGBA and applying the tint while preserving alpha.
|
|
51
|
+
|
|
52
|
+
- **`generate_badge_cli.py`**: Typer + Rich CLI with four subcommands: `single`, `batch`, `coverage`, and `audit`. Enum validation (template, frame, style, log_level) is done at CLI entry before calling `BadgeGenerator`. The `batch` command shows a Rich progress bar and summary table; failures exit with code 1. The `audit` command scans an SVG for external `http`/`https` URLs in attributes and inline styles.
|
|
53
|
+
|
|
54
|
+
- **`coverage.py`**: Two standalone functions — `parse_coverage_xml(path, metric)` reads `line-rate` or `branch-rate` from a `coverage.xml` produced by `coverage run`, returning a float 0–100; `coverage_color(pct)` maps the percentage to a hex color. The `coverage` CLI subcommand wires these together to produce a DEFAULT-template badge.
|
|
55
|
+
|
|
56
|
+
- **`utils.py`**: Four enums — `BadgeColor` (51 colors), `FrameType` (11 PNG frames), `BadgeTemplate` (5 templates), `BadgeStyle` (FLAT/ROUNDED/GRADIENT/SHADOWED). These are the canonical type-safe inputs for the generator.
|
|
57
|
+
|
|
58
|
+
- **`templates/`**: Jinja2 SVG templates with autoescape enabled.
|
|
59
|
+
- `label.svg` — DEFAULT: two-part horizontal badge, dynamic width, optional logo and links
|
|
60
|
+
- `circle.svg` — CIRCLE: circle with font-size scaling based on text length
|
|
61
|
+
- `circle_frame.svg` — CIRCLE_FRAME: circle overlaid with a PNG frame asset; requires `FrameType`
|
|
62
|
+
- `pill.svg` — PILL: fully rounded ends (rx=10 always), always uses style_ctx but overrides `rx`
|
|
63
|
+
- `banner.svg` — BANNER: fixed icon-zone on left (28px) + right text section
|
|
64
|
+
|
|
65
|
+
### Public API (`from badgeshield import ...`)
|
|
66
|
+
|
|
67
|
+
`BadgeGenerator`, `BadgeBatchGenerator`, `BadgeColor`, `BadgeTemplate`, `BadgeStyle`, `FrameType`, `LogLevel`, `parse_coverage_xml`, `coverage_color`
|
|
68
|
+
|
|
69
|
+
### Batch JSON config format
|
|
70
|
+
|
|
71
|
+
The JSON file passed to `batch` must be a list of objects, each with the same keys as `BadgeGenerator.generate_badge` kwargs. Required keys per entry: `left_text`, `left_color`, `badge_name` (ending in `.svg`). The `output_path` and `template` are supplied via CLI flags, not in the JSON. An optional `style` key per entry (string, case-insensitive) overrides the CLI `--style` flag for that badge.
|
|
72
|
+
|
|
73
|
+
### Key design decisions
|
|
74
|
+
|
|
75
|
+
- **Versioning**: `setuptools_scm` derives version from git tags (format `X.X.X`). The `_version.py` file is auto-generated — do not edit it manually.
|
|
76
|
+
- **Logging**: Uses `pylogshield` (`get_logger`), not stdlib `logging`. Log level can be passed as `LogLevel` enum or string.
|
|
77
|
+
- **Color input**: Accepts either a `BadgeColor` enum member or a hex string (`#RRGGBB`). Validation is done via `is_valid_hex_color()` and `validate_color()` in `badge_generator.py`.
|
|
78
|
+
- **Pillow is optional**: Only `jinja2` and `pylogshield` are required (`requirements.txt`). If Pillow is not installed, text width falls back to a char-width heuristic dict and logo tinting is silently skipped. Install the extras group for accurate text sizing: `pip install badgeshield[image]`.
|
|
79
|
+
- **CIRCLE_FRAME template**: Requires `frame` parameter (a `FrameType` enum); it is not optional for that template.
|
|
80
|
+
- **Renderer dispatch**: `BadgeGenerator._RENDERERS` is a class-level dict mapping `BadgeTemplate` → `_render_*` method, populated after the class body. To add a new template, add a `_render_<name>` method and register it in `_RENDERERS`.
|
|
81
|
+
- **Style system**: `_style_context()` returns a dict of Jinja2 context vars (`rx`, `gradient_id`, `gradient_stop`, `gradient_base`, `shadow_id`). Templates that don't support gradient (e.g. CIRCLE_FRAME) clear gradient keys after calling `_style_context`. PILL always forces `rx="10"` regardless of style.
|
|
82
|
+
|
|
83
|
+
### CI/CD (`.github/workflows/release.yml`)
|
|
84
|
+
|
|
85
|
+
- **Docs job**: Triggers on push to `main` or manual dispatch — deploys MkDocs to GitHub Pages.
|
|
86
|
+
- **Publish job**: Triggers on tag push matching `X.X.X` — runs tests, builds, then publishes to TestPyPI then PyPI using GitHub OIDC trusted publishing.
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 Muhammad Hassan
|
|
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.
|