Add pre-commit config and apply changes (#54)
- Add .pre-commit-config.yaml with initial config. - Add python black pre-commit config - Apply pre-commit code changes - Add information to CONTRIBUTING.md - Add pre-commit to build requirements - Run pre-commit during travis CI build - Use a travis build matrix to control when pre-commit runs in the CI process. Use explicit include to only run pre-commit on Python 3.9.
16
.pre-commit-config.yaml
Normal file
@@ -0,0 +1,16 @@
|
||||
repos:
|
||||
- repo: https://github.com/pre-commit/pre-commit-hooks
|
||||
rev: v4.3.0
|
||||
hooks:
|
||||
- id: trailing-whitespace
|
||||
- id: end-of-file-fixer
|
||||
- id: check-case-conflict
|
||||
- id: check-yaml
|
||||
- id: requirements-txt-fixer
|
||||
- id: mixed-line-ending
|
||||
- id: no-commit-to-branch
|
||||
args: [--branch, master]
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 22.6.0
|
||||
hooks:
|
||||
- id: black
|
28
.travis.yml
@@ -1,15 +1,27 @@
|
||||
dist: xenial
|
||||
language: python
|
||||
python:
|
||||
- '3.4'
|
||||
- '3.5'
|
||||
- '3.6'
|
||||
- '3.7'
|
||||
- '3.8'
|
||||
- '3.9'
|
||||
jobs:
|
||||
include:
|
||||
- python: '3.4'
|
||||
env: RUN_PRE_COMMIT=0
|
||||
- python: '3.5'
|
||||
env: RUN_PRE_COMMIT=0
|
||||
- python: '3.6'
|
||||
env: RUN_PRE_COMMIT=0
|
||||
- python: '3.7'
|
||||
env: RUN_PRE_COMMIT=0
|
||||
- python: '3.8'
|
||||
env: RUN_PRE_COMMIT=0
|
||||
- python: '3.9'
|
||||
env: RUN_PRE_COMMIT=1
|
||||
install:
|
||||
- pip install -U setuptools pip -r build-requirements.txt
|
||||
script:
|
||||
- if [[ $RUN_PRE_COMMIT = 1 ]]; then
|
||||
pip install -U pre-commit==2.12.1 &&
|
||||
pre-commit install &&
|
||||
pre-commit run --all;
|
||||
fi
|
||||
- pytest --doctest-modules --cov=anybadge --cov-report html:htmlcov anybadge tests
|
||||
before_deploy:
|
||||
- sed -i "s/^version = .*/version = __version__ = \"$TRAVIS_TAG\"/" anybadge.py
|
||||
@@ -23,4 +35,4 @@ deploy:
|
||||
on:
|
||||
tags: true
|
||||
all_branches: true
|
||||
python: '3.9'
|
||||
python: '3.9'
|
||||
|
@@ -8,7 +8,7 @@ I love your input! I want to make contributing to this project as easy and trans
|
||||
- Becoming a maintainer
|
||||
|
||||
## I use [Github Flow](https://docs.github.com/en/get-started/quickstart/github-flow), so all code changes happen through pull requests
|
||||
Pull requests are the best way to propose changes to the codebase (I use
|
||||
Pull requests are the best way to propose changes to the codebase (I use
|
||||
[Github Flow](https://docs.github.com/en/get-started/quickstart/github-flow)). I actively welcome your pull requests:
|
||||
|
||||
1. Fork the repo and create your branch from `master`
|
||||
@@ -20,7 +20,7 @@ Pull requests are the best way to propose changes to the codebase (I use
|
||||
|
||||
## Any contributions you make will be under the MIT Software License
|
||||
When you submit code changes, your submissions are understood to be under the same
|
||||
[MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers
|
||||
[MIT License](http://choosealicense.com/licenses/mit/) that covers the project. Feel free to contact the maintainers
|
||||
if that's a concern.
|
||||
|
||||
## Report bugs using Github's [issues](https://github.com/jongracecox/anybadge/issues)
|
||||
@@ -48,6 +48,42 @@ By contributing, you agree that your contributions will be licensed under its MI
|
||||
|
||||
# Technical stuff
|
||||
|
||||
## Pre-commit
|
||||
This projects makes use of [pre-commit](https://pre-commit.com) to add some safety checks and create consistency
|
||||
in the project code. When committing changes to this project, please first [install pre-commit](https://pre-commit.com/#install),
|
||||
then activate it for this project:
|
||||
|
||||
```bash
|
||||
pip install pre-commit
|
||||
pre-commit install
|
||||
```
|
||||
|
||||
After installing pre-commit to your project (with `pre-commit install`), committing to the project will trigger a series
|
||||
of checks, and fixers. This process may reject your commit or make changes to your code to bring it into line with the
|
||||
project standards. For example, [Python black](https://github.com/psf/black) will be used to reformat any code. When
|
||||
changes are made by these pre-commit hooks you will need to re-add and commit those changes in order for pre-commit to
|
||||
pass.
|
||||
|
||||
Here is some example output from pre-commit:
|
||||
|
||||
```
|
||||
trim trailing whitespace.................................................Failed
|
||||
- hook id: trailing-whitespace
|
||||
- exit code: 1
|
||||
- files were modified by this hook
|
||||
|
||||
Fixing tests/test_anybadge.py
|
||||
|
||||
fix end of files.........................................................Failed
|
||||
- hook id: end-of-file-fixer
|
||||
- exit code: 1
|
||||
- files were modified by this hook
|
||||
|
||||
Fixing examples/color_teal.svg
|
||||
```
|
||||
|
||||
This shows that two files were updated by hooks, and need to be re-added (with `git add`) before trying to commit again.
|
||||
|
||||
## Documentation
|
||||
The `README.md` file contains a table showing example badges for the different built-in colors. If you modify the
|
||||
appearance of badges, or the available colors please update the table using the following code:
|
||||
|
2
TODO.md
@@ -7,4 +7,4 @@
|
||||
* [ ] Add CI test for Docker image
|
||||
* [ ] Add CI to push server to Docker hub
|
||||
* [ ] Support common badge server URL structure
|
||||
* [ ] Documentation for all docker bits
|
||||
* [ ] Documentation for all docker bits
|
||||
|
@@ -5,7 +5,7 @@ from .styles import Style
|
||||
|
||||
# Package information
|
||||
version = __version__ = "0.0.0"
|
||||
__version_info__ = tuple(re.split('[.-]', __version__))
|
||||
__version_info__ = tuple(re.split("[.-]", __version__))
|
||||
__title__ = "anybadge"
|
||||
__summary__ = "A simple, flexible badge generator."
|
||||
__uri__ = "https://github.com/jongracecox/anybadge"
|
||||
|
@@ -98,12 +98,26 @@ class Badge:
|
||||
'#4c1'
|
||||
"""
|
||||
|
||||
def __init__(self, label, value, font_name=None, font_size=None,
|
||||
num_padding_chars=None, num_label_padding_chars=None,
|
||||
num_value_padding_chars=None, template=None, style=None,
|
||||
value_prefix='', value_suffix='', thresholds=None, default_color=None,
|
||||
use_max_when_value_exceeds=True, value_format=None, text_color=None,
|
||||
semver=False):
|
||||
def __init__(
|
||||
self,
|
||||
label,
|
||||
value,
|
||||
font_name=None,
|
||||
font_size=None,
|
||||
num_padding_chars=None,
|
||||
num_label_padding_chars=None,
|
||||
num_value_padding_chars=None,
|
||||
template=None,
|
||||
style=None,
|
||||
value_prefix="",
|
||||
value_suffix="",
|
||||
thresholds=None,
|
||||
default_color=None,
|
||||
use_max_when_value_exceeds=True,
|
||||
value_format=None,
|
||||
text_color=None,
|
||||
semver=False,
|
||||
):
|
||||
"""Constructor for Badge class."""
|
||||
# Set defaults if values were not passed
|
||||
if not font_name:
|
||||
@@ -121,8 +135,8 @@ class Badge:
|
||||
else:
|
||||
num_value_padding_chars = num_padding_chars
|
||||
if not template:
|
||||
template = get_template('default')
|
||||
if style not in ['gitlab-scoped']:
|
||||
template = get_template("default")
|
||||
if style not in ["gitlab-scoped"]:
|
||||
style = "default"
|
||||
if not default_color:
|
||||
default_color = config.DEFAULT_COLOR
|
||||
@@ -146,7 +160,8 @@ class Badge:
|
||||
if font_name not in config.FONT_WIDTHS:
|
||||
raise ValueError(
|
||||
'Font name "%s" not found. '
|
||||
'Available fonts: %s' % (font_name, ', '.join(config.FONT_WIDTHS.keys()))
|
||||
"Available fonts: %s"
|
||||
% (font_name, ", ".join(config.FONT_WIDTHS.keys()))
|
||||
)
|
||||
self.font_name = font_name
|
||||
self.font_size = font_size
|
||||
@@ -159,7 +174,7 @@ class Badge:
|
||||
|
||||
# text_color can be passed as a single value or a pair of comma delimited values
|
||||
self.text_color = text_color
|
||||
text_colors = text_color.split(',')
|
||||
text_colors = text_color.split(",")
|
||||
self.label_text_color = text_colors[0]
|
||||
self.value_text_color = text_colors[0]
|
||||
if len(text_colors) > 1:
|
||||
@@ -209,26 +224,34 @@ class Badge:
|
||||
optional_args += ", font_size=%s" % repr(self.font_size)
|
||||
if self.num_label_padding_chars == self.num_value_padding_chars:
|
||||
if self.num_label_padding_chars != config.NUM_PADDING_CHARS:
|
||||
optional_args += ", num_padding_chars=%s" % repr(self.num_label_padding_chars)
|
||||
optional_args += ", num_padding_chars=%s" % repr(
|
||||
self.num_label_padding_chars
|
||||
)
|
||||
else:
|
||||
if self.num_label_padding_chars != config.NUM_PADDING_CHARS:
|
||||
optional_args += ", num_label_padding_chars=%s" % repr(self.num_label_padding_chars)
|
||||
optional_args += ", num_label_padding_chars=%s" % repr(
|
||||
self.num_label_padding_chars
|
||||
)
|
||||
if self.num_value_padding_chars != config.NUM_PADDING_CHARS:
|
||||
optional_args += ", num_value_padding_chars=%s" % repr(self.num_value_padding_chars)
|
||||
if self.template != get_template('default'):
|
||||
optional_args += ", num_value_padding_chars=%s" % repr(
|
||||
self.num_value_padding_chars
|
||||
)
|
||||
if self.template != get_template("default"):
|
||||
optional_args += ", template=%s" % repr(self.template)
|
||||
if self.style != 'default':
|
||||
if self.style != "default":
|
||||
optional_args += ", style=%s" % repr(self.style)
|
||||
if self.value_prefix != '':
|
||||
if self.value_prefix != "":
|
||||
optional_args += ", value_prefix=%s" % repr(self.value_prefix)
|
||||
if self.value_suffix != '':
|
||||
if self.value_suffix != "":
|
||||
optional_args += ", value_suffix=%s" % repr(self.value_suffix)
|
||||
if self.thresholds:
|
||||
optional_args += ", thresholds=%s" % repr(self.thresholds)
|
||||
if self.default_color != config.DEFAULT_COLOR:
|
||||
optional_args += ", default_color=%s" % repr(self.default_color)
|
||||
if not self.use_max_when_value_exceeds:
|
||||
optional_args += ", use_max_when_value_exceeds=%s" % repr(self.use_max_when_value_exceeds)
|
||||
optional_args += ", use_max_when_value_exceeds=%s" % repr(
|
||||
self.use_max_when_value_exceeds
|
||||
)
|
||||
if self.value_format:
|
||||
optional_args += ", value_format=%s" % repr(self.value_format)
|
||||
if self.text_color != config.DEFAULT_TEXT_COLOR:
|
||||
@@ -238,7 +261,7 @@ class Badge:
|
||||
self.__class__.__name__,
|
||||
repr(self.label),
|
||||
repr(self.value),
|
||||
optional_args
|
||||
optional_args,
|
||||
)
|
||||
|
||||
def _repr_svg_(self):
|
||||
@@ -255,7 +278,7 @@ class Badge:
|
||||
|
||||
Returns: str
|
||||
"""
|
||||
if not hasattr(cls, 'mask_id'):
|
||||
if not hasattr(cls, "mask_id"):
|
||||
cls.mask_id = 0
|
||||
|
||||
cls.mask_id += 1
|
||||
@@ -269,17 +292,17 @@ class Badge:
|
||||
Returns: str
|
||||
"""
|
||||
if self.style == "gitlab-scoped":
|
||||
return get_template('gitlab_scoped')
|
||||
return get_template("gitlab_scoped")
|
||||
|
||||
# Identify whether template is a file or the actual template text
|
||||
|
||||
if len(self.template.split('\n')) == 1:
|
||||
if len(self.template.split("\n")) == 1:
|
||||
try:
|
||||
return get_template(self.template)
|
||||
except UnknownBadgeTemplate:
|
||||
pass
|
||||
|
||||
with open(self.template, mode='r') as file_handle:
|
||||
with open(self.template, mode="r") as file_handle:
|
||||
return file_handle.read()
|
||||
else:
|
||||
return self.template
|
||||
@@ -360,7 +383,10 @@ class Badge:
|
||||
|
||||
Returns: int
|
||||
"""
|
||||
return int(self.get_text_width(str(self.label)) + (2.0 * self.num_label_padding_chars * self.font_width))
|
||||
return int(
|
||||
self.get_text_width(str(self.label))
|
||||
+ (2.0 * self.num_label_padding_chars * self.font_width)
|
||||
)
|
||||
|
||||
@property
|
||||
def value_width(self):
|
||||
@@ -368,7 +394,10 @@ class Badge:
|
||||
|
||||
Returns: int
|
||||
"""
|
||||
return int(self.get_text_width(str(self.value_text)) + (2.0 * self.num_value_padding_chars * self.font_width))
|
||||
return int(
|
||||
self.get_text_width(str(self.value_text))
|
||||
+ (2.0 * self.num_value_padding_chars * self.font_width)
|
||||
)
|
||||
|
||||
@property
|
||||
def value_box_width(self):
|
||||
@@ -414,7 +443,9 @@ class Badge:
|
||||
|
||||
Returns: float
|
||||
"""
|
||||
return self.color_split_position + ((self.badge_width - self.color_split_position) / 2)
|
||||
return self.color_split_position + (
|
||||
(self.badge_width - self.color_split_position) / 2
|
||||
)
|
||||
|
||||
@property
|
||||
def label_anchor_shadow(self):
|
||||
@@ -469,23 +500,25 @@ class Badge:
|
||||
|
||||
badge_text = self._get_svg_template()
|
||||
|
||||
return badge_text.replace('{{ badge width }}', str(self.badge_width)) \
|
||||
.replace('{{ font name }}', self.font_name) \
|
||||
.replace('{{ font size }}', str(self.font_size)) \
|
||||
.replace('{{ label }}', self.label) \
|
||||
.replace('{{ value }}', self.value_text) \
|
||||
.replace('{{ label anchor }}', str(self.label_anchor)) \
|
||||
.replace('{{ label anchor shadow }}', str(self.label_anchor_shadow)) \
|
||||
.replace('{{ value anchor }}', str(self.value_anchor)) \
|
||||
.replace('{{ value anchor shadow }}', str(self.value_anchor_shadow)) \
|
||||
.replace('{{ color }}', self.badge_color_code) \
|
||||
.replace('{{ label text color }}', self.label_text_color) \
|
||||
.replace('{{ value text color }}', self.value_text_color) \
|
||||
.replace('{{ color split x }}', str(self.color_split_position)) \
|
||||
.replace('{{ value width }}', str(self.value_width)) \
|
||||
.replace('{{ mask id }}', self.mask_id) \
|
||||
.replace('{{ value box width }}', str(self.value_box_width)) \
|
||||
.replace('{{ arc start }}', str(self.arc_start))
|
||||
return (
|
||||
badge_text.replace("{{ badge width }}", str(self.badge_width))
|
||||
.replace("{{ font name }}", self.font_name)
|
||||
.replace("{{ font size }}", str(self.font_size))
|
||||
.replace("{{ label }}", self.label)
|
||||
.replace("{{ value }}", self.value_text)
|
||||
.replace("{{ label anchor }}", str(self.label_anchor))
|
||||
.replace("{{ label anchor shadow }}", str(self.label_anchor_shadow))
|
||||
.replace("{{ value anchor }}", str(self.value_anchor))
|
||||
.replace("{{ value anchor shadow }}", str(self.value_anchor_shadow))
|
||||
.replace("{{ color }}", self.badge_color_code)
|
||||
.replace("{{ label text color }}", self.label_text_color)
|
||||
.replace("{{ value text color }}", self.value_text_color)
|
||||
.replace("{{ color split x }}", str(self.color_split_position))
|
||||
.replace("{{ value width }}", str(self.value_width))
|
||||
.replace("{{ mask id }}", self.mask_id)
|
||||
.replace("{{ value box width }}", str(self.value_box_width))
|
||||
.replace("{{ arc start }}", str(self.arc_start))
|
||||
)
|
||||
|
||||
def __str__(self):
|
||||
"""Return string representation of badge.
|
||||
@@ -573,7 +606,7 @@ class Badge:
|
||||
if isinstance(color, Color):
|
||||
return color.value
|
||||
|
||||
if color[0] == '#':
|
||||
if color[0] == "#":
|
||||
return color
|
||||
|
||||
color = color.upper()
|
||||
@@ -589,32 +622,32 @@ class Badge:
|
||||
# contain underscores) we will try to get the same color.
|
||||
|
||||
for prefix in prefixes:
|
||||
if color.startswith(prefix) and color != prefix and '_' not in color:
|
||||
if color.startswith(prefix) and color != prefix and "_" not in color:
|
||||
try:
|
||||
return Color[color.replace(prefix, prefix + '_')].value
|
||||
return Color[color.replace(prefix, prefix + "_")].value
|
||||
except KeyError:
|
||||
pass
|
||||
|
||||
raise ValueError(
|
||||
'Invalid color code "%s". '
|
||||
'Valid color codes are: %s', (color, ", ".join(list(Color.__members__.keys())))
|
||||
'Invalid color code "%s". ' "Valid color codes are: %s",
|
||||
(color, ", ".join(list(Color.__members__.keys()))),
|
||||
)
|
||||
|
||||
def write_badge(self, file_path, overwrite=False):
|
||||
"""Write badge to file."""
|
||||
|
||||
# Validate path (part 1)
|
||||
if file_path.endswith('/'):
|
||||
raise ValueError('File location may not be a directory.')
|
||||
if file_path.endswith("/"):
|
||||
raise ValueError("File location may not be a directory.")
|
||||
|
||||
# Get absolute filepath
|
||||
path = os.path.abspath(file_path)
|
||||
if not path.lower().endswith('.svg'):
|
||||
path += '.svg'
|
||||
if not path.lower().endswith(".svg"):
|
||||
path += ".svg"
|
||||
|
||||
# Validate path (part 2)
|
||||
if not overwrite and os.path.exists(path):
|
||||
raise RuntimeError('File "{}" already exists.'.format(path))
|
||||
|
||||
with open(path, mode='w') as file_handle:
|
||||
with open(path, mode="w") as file_handle:
|
||||
file_handle.write(self.badge_svg_text)
|
||||
|
200
anybadge/cli.py
@@ -10,8 +10,10 @@ from .badge import Badge
|
||||
|
||||
def parse_args(args):
|
||||
"""Parse the command line arguments."""
|
||||
parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=textwrap.dedent('''\
|
||||
parser = argparse.ArgumentParser(
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||
description=textwrap.dedent(
|
||||
"""\
|
||||
Command line utility to generate .svg badges.
|
||||
|
||||
This utility can be used to generate .svg badge images, using configurable
|
||||
@@ -46,52 +48,121 @@ examples:
|
||||
anybadge.py --label=pipeline --value=passing --file=pipeline.svg \\
|
||||
passing=green failing=red
|
||||
|
||||
'''))
|
||||
parser.add_argument('-l', '--label', type=str, help='The badge label.')
|
||||
parser.add_argument('-v', '--value', type=str, help='The badge value.', required=True)
|
||||
parser.add_argument('-m', '--value-format', type=str, default=None,
|
||||
help='Formatting string for value (e.g. "%%.2f" for 2dp floats)')
|
||||
parser.add_argument('-c', '--color', type=str, help='For fixed color badges use --color '
|
||||
'to specify the badge color.',
|
||||
default=config.DEFAULT_COLOR)
|
||||
parser.add_argument('-p', '--prefix', type=str, help='Optional prefix for value.',
|
||||
default='')
|
||||
parser.add_argument('-s', '--suffix', type=str, help='Optional suffix for value.',
|
||||
default='')
|
||||
parser.add_argument('-d', '--padding', type=int, help='Number of characters to pad on '
|
||||
'either side of the badge text.',
|
||||
default=config.NUM_PADDING_CHARS)
|
||||
parser.add_argument('-lp', '--label-padding', type=int, help='Number of characters to pad on '
|
||||
'either side of the badge label.', default=None)
|
||||
parser.add_argument('-vp', '--value-padding', type=int, help='Number of characters to pad on '
|
||||
'either side of the badge value.', default=None)
|
||||
parser.add_argument('-n', '--font', type=str,
|
||||
help='Font name. Supported fonts: '
|
||||
','.join(['"%s"' % x for x in config.FONT_WIDTHS.keys()]),
|
||||
default=config.DEFAULT_FONT)
|
||||
parser.add_argument('-z', '--font-size', type=int, help='Font size.',
|
||||
default=config.DEFAULT_FONT_SIZE)
|
||||
parser.add_argument('-t', '--template', type=str, help='Location of alternative '
|
||||
'template .svg file.',
|
||||
default=get_template('default'))
|
||||
parser.add_argument('-st', '--style', type=str, help='Alternative style of badge to create. Valid '
|
||||
'values are "gitlab-scoped", "default". This '
|
||||
'overrides any templates passed using --template.')
|
||||
parser.add_argument('-u', '--use-max', action='store_true',
|
||||
help='Use the maximum threshold color when the value exceeds the '
|
||||
'maximum threshold.')
|
||||
parser.add_argument('-f', '--file', type=str, help='Output file location.')
|
||||
parser.add_argument('-o', '--overwrite', action='store_true',
|
||||
help='Overwrite output file if it already exists.')
|
||||
parser.add_argument('-r', '--text-color', type=str, help='Text color. Single value affects both label'
|
||||
'and value colors. A comma separated pair '
|
||||
'affects label and value text respectively.',
|
||||
default=config.DEFAULT_TEXT_COLOR)
|
||||
parser.add_argument('-e', '--semver', action='store_true', default=False,
|
||||
help='Treat value and thresholds as semantic versions.')
|
||||
parser.add_argument('args', nargs=argparse.REMAINDER, help='Pairs of <upper>=<color>. '
|
||||
'For example 2=red 4=orange 6=yellow 8=good. '
|
||||
'Read this as "Less than 2 = red, less than 4 = orange...".')
|
||||
"""
|
||||
),
|
||||
)
|
||||
parser.add_argument("-l", "--label", type=str, help="The badge label.")
|
||||
parser.add_argument(
|
||||
"-v", "--value", type=str, help="The badge value.", required=True
|
||||
)
|
||||
parser.add_argument(
|
||||
"-m",
|
||||
"--value-format",
|
||||
type=str,
|
||||
default=None,
|
||||
help='Formatting string for value (e.g. "%%.2f" for 2dp floats)',
|
||||
)
|
||||
parser.add_argument(
|
||||
"-c",
|
||||
"--color",
|
||||
type=str,
|
||||
help="For fixed color badges use --color to specify the badge color.",
|
||||
default=config.DEFAULT_COLOR,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-p", "--prefix", type=str, help="Optional prefix for value.", default=""
|
||||
)
|
||||
parser.add_argument(
|
||||
"-s", "--suffix", type=str, help="Optional suffix for value.", default=""
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d",
|
||||
"--padding",
|
||||
type=int,
|
||||
help="Number of characters to pad on either side of the badge text.",
|
||||
default=config.NUM_PADDING_CHARS,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-lp",
|
||||
"--label-padding",
|
||||
type=int,
|
||||
help="Number of characters to pad on either side of the badge label.",
|
||||
default=None,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-vp",
|
||||
"--value-padding",
|
||||
type=int,
|
||||
help="Number of characters to pad on either side of the badge value.",
|
||||
default=None,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-n",
|
||||
"--font",
|
||||
type=str,
|
||||
help="Font name. Supported fonts: "
|
||||
",".join(['"%s"' % x for x in config.FONT_WIDTHS.keys()]),
|
||||
default=config.DEFAULT_FONT,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-z",
|
||||
"--font-size",
|
||||
type=int,
|
||||
help="Font size.",
|
||||
default=config.DEFAULT_FONT_SIZE,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-t",
|
||||
"--template",
|
||||
type=str,
|
||||
help="Location of alternative template .svg file.",
|
||||
default=get_template("default"),
|
||||
)
|
||||
parser.add_argument(
|
||||
"-st",
|
||||
"--style",
|
||||
type=str,
|
||||
help="Alternative style of badge to create. Valid "
|
||||
'values are "gitlab-scoped", "default". This '
|
||||
"overrides any templates passed using --template.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-u",
|
||||
"--use-max",
|
||||
action="store_true",
|
||||
help="Use the maximum threshold color when the value exceeds the "
|
||||
"maximum threshold.",
|
||||
)
|
||||
parser.add_argument("-f", "--file", type=str, help="Output file location.")
|
||||
parser.add_argument(
|
||||
"-o",
|
||||
"--overwrite",
|
||||
action="store_true",
|
||||
help="Overwrite output file if it already exists.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"-r",
|
||||
"--text-color",
|
||||
type=str,
|
||||
help="Text color. Single value affects both label"
|
||||
"and value colors. A comma separated pair "
|
||||
"affects label and value text respectively.",
|
||||
default=config.DEFAULT_TEXT_COLOR,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-e",
|
||||
"--semver",
|
||||
action="store_true",
|
||||
default=False,
|
||||
help="Treat value and thresholds as semantic versions.",
|
||||
)
|
||||
parser.add_argument(
|
||||
"args",
|
||||
nargs=argparse.REMAINDER,
|
||||
help="Pairs of <upper>=<color>. "
|
||||
"For example 2=red 4=orange 6=yellow 8=good. "
|
||||
'Read this as "Less than 2 = red, less than 4 = orange...".',
|
||||
)
|
||||
return parser.parse_args(args)
|
||||
|
||||
|
||||
@@ -114,26 +185,39 @@ def main(args=None):
|
||||
if len(args.args) == 1 and Style.exists(args.args[0].upper()):
|
||||
style_name = args.args[0].upper()
|
||||
style = Style[style_name]
|
||||
threshold_text = style.threshold.split(' ')
|
||||
threshold_text = style.threshold.split(" ")
|
||||
if not args.label and style.label:
|
||||
label = style.label
|
||||
if not args.suffix and style.suffix:
|
||||
suffix = style.suffix
|
||||
|
||||
if not label:
|
||||
raise ValueError('Label has not been set. Please use --label argument.')
|
||||
raise ValueError("Label has not been set. Please use --label argument.")
|
||||
|
||||
# Create threshold list from args
|
||||
threshold_list = [x.split('=') for x in threshold_text]
|
||||
threshold_list = [x.split("=") for x in threshold_text]
|
||||
threshold_dict = {x[0]: x[1] for x in threshold_list}
|
||||
|
||||
# Create badge object
|
||||
badge = Badge(label, args.value, value_prefix=args.prefix, value_suffix=suffix,
|
||||
default_color=args.color, num_padding_chars=args.padding,
|
||||
num_label_padding_chars=args.label_padding, num_value_padding_chars=args.value_padding,
|
||||
font_name=args.font, font_size=args.font_size, template=args.template, style=args.style,
|
||||
use_max_when_value_exceeds=args.use_max, thresholds=threshold_dict,
|
||||
value_format=args.value_format, text_color=args.text_color, semver=args.semver)
|
||||
badge = Badge(
|
||||
label,
|
||||
args.value,
|
||||
value_prefix=args.prefix,
|
||||
value_suffix=suffix,
|
||||
default_color=args.color,
|
||||
num_padding_chars=args.padding,
|
||||
num_label_padding_chars=args.label_padding,
|
||||
num_value_padding_chars=args.value_padding,
|
||||
font_name=args.font,
|
||||
font_size=args.font_size,
|
||||
template=args.template,
|
||||
style=args.style,
|
||||
use_max_when_value_exceeds=args.use_max,
|
||||
thresholds=threshold_dict,
|
||||
value_format=args.value_format,
|
||||
text_color=args.text_color,
|
||||
semver=args.semver,
|
||||
)
|
||||
|
||||
if args.file:
|
||||
# Write badge SVG to file
|
||||
@@ -142,5 +226,5 @@ def main(args=None):
|
||||
print(badge.badge_svg_text)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@@ -4,24 +4,24 @@ from enum import Enum
|
||||
|
||||
|
||||
class Color(Enum):
|
||||
WHITE = '#FFFFFF'
|
||||
SILVER = '#C0C0C0'
|
||||
GRAY = '#808080'
|
||||
BLACK = '#000000'
|
||||
RED = '#e05d44'
|
||||
BRIGHT_RED = '#FF0000'
|
||||
MAROON = '#800000'
|
||||
OLIVE = '#808000'
|
||||
LIME = '#00FF00'
|
||||
BRIGHT_YELLOW = '#FFFF00'
|
||||
YELLOW = '#dfb317'
|
||||
GREEN = '#4c1'
|
||||
YELLOW_GREEN = '#a4a61d'
|
||||
AQUA = '#00FFFF'
|
||||
TEAL = '#008080'
|
||||
BLUE = '#0000FF'
|
||||
NAVY = '#000080'
|
||||
FUCHSIA = '#FF00FF'
|
||||
PURPLE = '#800080'
|
||||
ORANGE = '#fe7d37'
|
||||
LIGHT_GREY = '#9f9f9f'
|
||||
WHITE = "#FFFFFF"
|
||||
SILVER = "#C0C0C0"
|
||||
GRAY = "#808080"
|
||||
BLACK = "#000000"
|
||||
RED = "#e05d44"
|
||||
BRIGHT_RED = "#FF0000"
|
||||
MAROON = "#800000"
|
||||
OLIVE = "#808000"
|
||||
LIME = "#00FF00"
|
||||
BRIGHT_YELLOW = "#FFFF00"
|
||||
YELLOW = "#dfb317"
|
||||
GREEN = "#4c1"
|
||||
YELLOW_GREEN = "#a4a61d"
|
||||
AQUA = "#00FFFF"
|
||||
TEAL = "#008080"
|
||||
BLUE = "#0000FF"
|
||||
NAVY = "#000080"
|
||||
FUCHSIA = "#FF00FF"
|
||||
PURPLE = "#800080"
|
||||
ORANGE = "#fe7d37"
|
||||
LIGHT_GREY = "#9f9f9f"
|
||||
|
@@ -1,22 +1,20 @@
|
||||
# Set some defaults
|
||||
DEFAULT_FONT = 'DejaVu Sans,Verdana,Geneva,sans-serif'
|
||||
DEFAULT_FONT = "DejaVu Sans,Verdana,Geneva,sans-serif"
|
||||
DEFAULT_FONT_SIZE = 11
|
||||
NUM_PADDING_CHARS = 0.5
|
||||
DEFAULT_COLOR = '#4c1'
|
||||
DEFAULT_TEXT_COLOR = '#fff'
|
||||
MASK_ID_PREFIX = 'anybadge_'
|
||||
DEFAULT_COLOR = "#4c1"
|
||||
DEFAULT_TEXT_COLOR = "#fff"
|
||||
MASK_ID_PREFIX = "anybadge_"
|
||||
|
||||
# Dictionary for looking up approx pixel widths of
|
||||
# supported fonts and font sizes.
|
||||
FONT_WIDTHS = {
|
||||
'DejaVu Sans,Verdana,Geneva,sans-serif': {
|
||||
"DejaVu Sans,Verdana,Geneva,sans-serif": {
|
||||
10: 9,
|
||||
11: 10,
|
||||
12: 11,
|
||||
},
|
||||
'Arial, Helvetica, sans-serif': {
|
||||
"Arial, Helvetica, sans-serif": {
|
||||
11: 8,
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
|
@@ -1,3 +1,2 @@
|
||||
|
||||
class UnknownBadgeTemplate(Exception):
|
||||
"""The badge template is unknown."""
|
||||
|
@@ -43,12 +43,12 @@ def _get_approx_string_width(text, font_width, fixed_width=False):
|
||||
# These percentages can be calculated using the ``_get_character_percentage_dict`` function.
|
||||
char_width_percentages = {
|
||||
"lij|' ": 40.0,
|
||||
'![]fI.,:;/\\t': 50.0,
|
||||
"![]fI.,:;/\\t": 50.0,
|
||||
'`-(){}r"': 60.0,
|
||||
'*^zcsJkvxy': 70.0,
|
||||
'aebdhnopqug#$L+<>=?_~FZT0123456789': 70.0,
|
||||
'BSPEAKVXY&UwNRCHD': 70.0,
|
||||
'QGOMm%W@': 100.0
|
||||
"*^zcsJkvxy": 70.0,
|
||||
"aebdhnopqug#$L+<>=?_~FZT0123456789": 70.0,
|
||||
"BSPEAKVXY&UwNRCHD": 70.0,
|
||||
"QGOMm%W@": 100.0,
|
||||
}
|
||||
|
||||
for s in text:
|
||||
|
@@ -24,20 +24,32 @@ def run(listen_address: str = None, port: int = None):
|
||||
SERVER_LISTEN_ADDRESS = listen_address
|
||||
|
||||
httpd = HTTPServer(server_address, AnyBadgeHTTPRequestHandler)
|
||||
logger.info('Serving at: http://%s:%s' % server_address)
|
||||
logger.info("Serving at: http://%s:%s" % server_address)
|
||||
httpd.serve_forever()
|
||||
|
||||
|
||||
def parse_args():
|
||||
logger.debug('Parsing command line arguments.')
|
||||
logger.debug("Parsing command line arguments.")
|
||||
parser = argparse.ArgumentParser(description="Run an anybadge server.")
|
||||
parser.add_argument('-p', '--port', type=int, default=DEFAULT_SERVER_PORT,
|
||||
help="Server port number. Default is %s. This can also be set via an environment "
|
||||
"variable called ``ANYBADGE_PORT``." % DEFAULT_SERVER_PORT)
|
||||
parser.add_argument('-l', '--listen-address', type=str, default=DEFAULT_SERVER_LISTEN_ADDRESS,
|
||||
help="Server listen address. Default is %s. This can also be set via an environment "
|
||||
"variable called ``ANYBADGE_LISTEN_ADDRESS``." % DEFAULT_SERVER_LISTEN_ADDRESS)
|
||||
parser.add_argument('-d', '--debug', action='store_true', help='Enable debug logging.')
|
||||
parser.add_argument(
|
||||
"-p",
|
||||
"--port",
|
||||
type=int,
|
||||
default=DEFAULT_SERVER_PORT,
|
||||
help="Server port number. Default is %s. This can also be set via an environment "
|
||||
"variable called ``ANYBADGE_PORT``." % DEFAULT_SERVER_PORT,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-l",
|
||||
"--listen-address",
|
||||
type=str,
|
||||
default=DEFAULT_SERVER_LISTEN_ADDRESS,
|
||||
help="Server listen address. Default is %s. This can also be set via an environment "
|
||||
"variable called ``ANYBADGE_LISTEN_ADDRESS``." % DEFAULT_SERVER_LISTEN_ADDRESS,
|
||||
)
|
||||
parser.add_argument(
|
||||
"-d", "--debug", action="store_true", help="Enable debug logging."
|
||||
)
|
||||
return parser.parse_args()
|
||||
|
||||
|
||||
@@ -47,14 +59,14 @@ def main():
|
||||
global DEFAULT_SERVER_PORT, DEFAULT_SERVER_LISTEN_ADDRESS, DEFAULT_LOGGING_LEVEL
|
||||
|
||||
# Check for environment variables
|
||||
if 'ANYBADGE_PORT' in environ:
|
||||
DEFAULT_SERVER_PORT = environ['ANYBADGE_PORT']
|
||||
if "ANYBADGE_PORT" in environ:
|
||||
DEFAULT_SERVER_PORT = environ["ANYBADGE_PORT"]
|
||||
|
||||
if 'ANYBADGE_LISTEN_ADDRESS' in environ:
|
||||
DEFAULT_SERVER_LISTEN_ADDRESS = environ['ANYBADGE_LISTEN_ADDRESS']
|
||||
if "ANYBADGE_LISTEN_ADDRESS" in environ:
|
||||
DEFAULT_SERVER_LISTEN_ADDRESS = environ["ANYBADGE_LISTEN_ADDRESS"]
|
||||
|
||||
if 'ANYBADGE_LOG_LEVEL' in environ:
|
||||
DEFAULT_LOGGING_LEVEL = logging.getLevelName(environ['ANYBADGE_LOG_LEVEL'])
|
||||
if "ANYBADGE_LOG_LEVEL" in environ:
|
||||
DEFAULT_LOGGING_LEVEL = logging.getLevelName(environ["ANYBADGE_LOG_LEVEL"])
|
||||
|
||||
# Parse command line args
|
||||
args = parse_args()
|
||||
@@ -64,12 +76,14 @@ def main():
|
||||
if args.debug:
|
||||
logging_level = logging.DEBUG
|
||||
|
||||
logging.basicConfig(format='%(asctime)-15s %(levelname)s:%(filename)s(%(lineno)d):%(funcName)s: %(message)s',
|
||||
level=logging_level)
|
||||
logger.info('Starting up anybadge server.')
|
||||
logging.basicConfig(
|
||||
format="%(asctime)-15s %(levelname)s:%(filename)s(%(lineno)d):%(funcName)s: %(message)s",
|
||||
level=logging_level,
|
||||
)
|
||||
logger.info("Starting up anybadge server.")
|
||||
|
||||
run(listen_address=args.listen_address, port=args.port)
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
@@ -2,7 +2,7 @@ import logging
|
||||
|
||||
|
||||
DEFAULT_SERVER_PORT = 8000
|
||||
DEFAULT_SERVER_LISTEN_ADDRESS = 'localhost'
|
||||
DEFAULT_SERVER_LISTEN_ADDRESS = "localhost"
|
||||
DEFAULT_LOGGING_LEVEL = logging.INFO
|
||||
|
||||
SERVER_PORT = DEFAULT_SERVER_PORT
|
||||
|
@@ -12,45 +12,45 @@ class AnyBadgeHTTPRequestHandler(BaseHTTPRequestHandler):
|
||||
"""Request handler for anybadge HTTP server."""
|
||||
|
||||
def do_HEAD(self):
|
||||
logging.debug('Sending head.')
|
||||
logging.debug("Sending head.")
|
||||
self.send_response(200)
|
||||
self.send_header("Content-type", "text/html")
|
||||
self.end_headers()
|
||||
|
||||
def do_GET(self):
|
||||
logging.debug('Handling get request.')
|
||||
logging.debug("Handling get request.")
|
||||
self.do_HEAD()
|
||||
|
||||
# Ignore request for favicon
|
||||
if self.path == '/favicon.ico':
|
||||
logging.debug('Ignoring favicon request.')
|
||||
if self.path == "/favicon.ico":
|
||||
logging.debug("Ignoring favicon request.")
|
||||
return
|
||||
|
||||
# Parse the URL query string
|
||||
parsed = urlparse.urlparse(self.path)
|
||||
url_query = urlparse.parse_qs(parsed.query)
|
||||
|
||||
label = ''
|
||||
value = ''
|
||||
color = 'green'
|
||||
label = ""
|
||||
value = ""
|
||||
color = "green"
|
||||
|
||||
# Extract the label and value portions
|
||||
if 'label' in url_query:
|
||||
label = url_query['label'][0]
|
||||
if "label" in url_query:
|
||||
label = url_query["label"][0]
|
||||
|
||||
if 'value' in url_query:
|
||||
value = url_query['value'][0]
|
||||
if "value" in url_query:
|
||||
value = url_query["value"][0]
|
||||
|
||||
logging.debug('Label: %s Value: %s', label, value)
|
||||
logging.debug("Label: %s Value: %s", label, value)
|
||||
|
||||
if label and value and color:
|
||||
logging.debug('All parameters present.')
|
||||
logging.debug("All parameters present.")
|
||||
badge = Badge(label=label, value=value, default_color=color)
|
||||
for line in badge.badge_svg_text:
|
||||
self.wfile.write(str.encode(line))
|
||||
|
||||
else:
|
||||
logging.debug('Not all parameters present.')
|
||||
logging.debug("Not all parameters present.")
|
||||
|
||||
self.wfile.write(b"<html><head><title>Anybadge Web Server.</title></head>")
|
||||
self.wfile.write(b"<body>")
|
||||
@@ -67,8 +67,10 @@ class AnyBadgeHTTPRequestHandler(BaseHTTPRequestHandler):
|
||||
|
||||
<a href="http://localhost:{port}/?label=Project%20Awesomeness&value=110%">\
|
||||
http://localhost:{port}/?label=Project%20Awesomeness&value=110%</a>
|
||||
""".format(port=config.SERVER_PORT)
|
||||
""".format(
|
||||
port=config.SERVER_PORT
|
||||
)
|
||||
|
||||
for line in help_text.splitlines():
|
||||
self.wfile.write(str.encode('<p>%s</p>' % line))
|
||||
self.wfile.write(b"</body></html>")
|
||||
self.wfile.write(str.encode("<p>%s</p>" % line))
|
||||
self.wfile.write(b"</body></html>")
|
||||
|
@@ -6,8 +6,8 @@ from enum import Enum
|
||||
class Style(Enum):
|
||||
"""A style that can be used for common badge types."""
|
||||
|
||||
PYLINT = ('default.svg', '2=red 4=orange 8=yellow 10=green', 'pylint')
|
||||
COVERAGE = ('default.svg', '50=red 60=orange 80=yellow 100=green', 'coverage', '%')
|
||||
PYLINT = ("default.svg", "2=red 4=orange 8=yellow 10=green", "pylint")
|
||||
COVERAGE = ("default.svg", "50=red 60=orange 80=yellow 100=green", "coverage", "%")
|
||||
|
||||
def __init__(self, template, threshold, label, suffix=None):
|
||||
self.template = template
|
||||
|
@@ -20,4 +20,4 @@
|
||||
<text x="{{ value anchor shadow }}" y="15" fill="#010101" fill-opacity=".3">{{ value }}</text>
|
||||
<text x="{{ value anchor }}" y="14">{{ value }}</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -19,4 +19,4 @@
|
||||
<g fill="{{ value text color }}" text-anchor="middle" font-family="{{ font name }}" font-size="{{ font size }}">
|
||||
<text x="{{ value anchor }}" y="14">{{ value }}</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -1,3 +1,3 @@
|
||||
pygments
|
||||
pytest
|
||||
pytest-cov
|
||||
pytest-cov
|
||||
|
@@ -1,15 +1,23 @@
|
||||
import anybadge
|
||||
|
||||
if __name__ == '__main__':
|
||||
if __name__ == "__main__":
|
||||
|
||||
print("""| Color Name | Hex Code | Example |
|
||||
| ---------- | -------- | ------- |""")
|
||||
print(
|
||||
"""| Color Name | Hex Code | Example |
|
||||
| ---------- | -------- | ------- |"""
|
||||
)
|
||||
for color, hex in sorted(anybadge.COLORS.items()):
|
||||
|
||||
file = 'examples/color_' + color + '.svg'
|
||||
file = "examples/color_" + color + ".svg"
|
||||
|
||||
url = 'https://cdn.rawgit.com/jongracecox/anybadge/master/' + file
|
||||
url = "https://cdn.rawgit.com/jongracecox/anybadge/master/" + file
|
||||
|
||||
anybadge.Badge(label='Color', value=color, default_color=color).write_badge(file, overwrite=True)
|
||||
anybadge.Badge(label="Color", value=color, default_color=color).write_badge(
|
||||
file, overwrite=True
|
||||
)
|
||||
|
||||
print("| {color} | {hex} |  |".format(color=color, hex=hex.upper(), url=url))
|
||||
print(
|
||||
"| {color} | {hex} |  |".format(
|
||||
color=color, hex=hex.upper(), url=url
|
||||
)
|
||||
)
|
||||
|
@@ -20,4 +20,4 @@
|
||||
<text x="111" y="15" fill="#010101" fill-opacity=".3">110%</text>
|
||||
<text x="110" y="14">110%</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="80.5" y="15" fill="#010101" fill-opacity=".3">Color.AQUA</text>
|
||||
<text x="79.5" y="14">Color.AQUA</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="82.5" y="15" fill="#010101" fill-opacity=".3">Color.BLACK</text>
|
||||
<text x="81.5" y="14">Color.BLACK</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="79.0" y="15" fill="#010101" fill-opacity=".3">Color.BLUE</text>
|
||||
<text x="78.0" y="14">Color.BLUE</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="100.5" y="15" fill="#010101" fill-opacity=".3">Color.BRIGHT_RED</text>
|
||||
<text x="99.5" y="14">Color.BRIGHT_RED</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="114.0" y="15" fill="#010101" fill-opacity=".3">Color.BRIGHT_YELLOW</text>
|
||||
<text x="113.0" y="14">Color.BRIGHT_YELLOW</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.1 KiB After Width: | Height: | Size: 1.1 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="75.0" y="15" fill="#010101" fill-opacity=".3">brightred</text>
|
||||
<text x="74.0" y="14">brightred</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="83.0" y="15" fill="#010101" fill-opacity=".3">brightyellow</text>
|
||||
<text x="82.0" y="14">brightyellow</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="88.5" y="15" fill="#010101" fill-opacity=".3">Color.FUCHSIA</text>
|
||||
<text x="87.5" y="14">Color.FUCHSIA</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="80.5" y="15" fill="#010101" fill-opacity=".3">Color.GRAY</text>
|
||||
<text x="79.5" y="14">Color.GRAY</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="84.0" y="15" fill="#010101" fill-opacity=".3">Color.GREEN</text>
|
||||
<text x="83.0" y="14">Color.GREEN</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="102.0" y="15" fill="#010101" fill-opacity=".3">Color.LIGHT_GREY</text>
|
||||
<text x="101.0" y="14">Color.LIGHT_GREY</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="74.0" y="15" fill="#010101" fill-opacity=".3">lightgrey</text>
|
||||
<text x="73.0" y="14">lightgrey</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="79.5" y="15" fill="#010101" fill-opacity=".3">Color.LIME</text>
|
||||
<text x="78.5" y="14">Color.LIME</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="90.5" y="15" fill="#010101" fill-opacity=".3">Color.MAROON</text>
|
||||
<text x="89.5" y="14">Color.MAROON</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="79.0" y="15" fill="#010101" fill-opacity=".3">Color.NAVY</text>
|
||||
<text x="78.0" y="14">Color.NAVY</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="83.0" y="15" fill="#010101" fill-opacity=".3">Color.OLIVE</text>
|
||||
<text x="82.0" y="14">Color.OLIVE</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="89.0" y="15" fill="#010101" fill-opacity=".3">Color.ORANGE</text>
|
||||
<text x="88.0" y="14">Color.ORANGE</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="86.0" y="15" fill="#010101" fill-opacity=".3">Color.PURPLE</text>
|
||||
<text x="85.0" y="14">Color.PURPLE</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="75.5" y="15" fill="#010101" fill-opacity=".3">Color.RED</text>
|
||||
<text x="74.5" y="14">Color.RED</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="85.0" y="15" fill="#010101" fill-opacity=".3">Color.SILVER</text>
|
||||
<text x="84.0" y="14">Color.SILVER</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="79.0" y="15" fill="#010101" fill-opacity=".3">Color.TEAL</text>
|
||||
<text x="78.0" y="14">Color.TEAL</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="83.0" y="15" fill="#010101" fill-opacity=".3">Color.WHITE</text>
|
||||
<text x="82.0" y="14">Color.WHITE</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="89.0" y="15" fill="#010101" fill-opacity=".3">Color.YELLOW</text>
|
||||
<text x="88.0" y="14">Color.YELLOW</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="111.5" y="15" fill="#010101" fill-opacity=".3">Color.YELLOW_GREEN</text>
|
||||
<text x="110.5" y="14">Color.YELLOW_GREEN</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="82.0" y="15" fill="#010101" fill-opacity=".3">yellowgreen</text>
|
||||
<text x="81.0" y="14">yellowgreen</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="93" y="15" fill="#010101" fill-opacity=".3">65.0%</text>
|
||||
<text x="92" y="14">65.0%</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1023 B After Width: | Height: | Size: 1.0 KiB |
@@ -19,4 +19,4 @@
|
||||
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
||||
<text x="91.5" y="14">Archimedes</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 963 B After Width: | Height: | Size: 964 B |
@@ -20,4 +20,4 @@
|
||||
<text x="100" y="15" fill="#010101" fill-opacity=".3">passing</text>
|
||||
<text x="99" y="14">passing</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
@@ -20,4 +20,4 @@
|
||||
<text x="76" y="15" fill="#010101" fill-opacity=".3">2.22</text>
|
||||
<text x="75" y="14">2.22</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1014 B After Width: | Height: | Size: 1015 B |
44
setup.py
@@ -3,39 +3,37 @@ import os
|
||||
import re
|
||||
from setuptools import setup
|
||||
|
||||
with open('README.md', encoding='utf-8') as f:
|
||||
with open("README.md", encoding="utf-8") as f:
|
||||
long_description = f.read()
|
||||
|
||||
# Attempt to get version number from TravisCI environment variable
|
||||
version = os.environ.get('TRAVIS_TAG', default='0.0.0')
|
||||
version = os.environ.get("TRAVIS_TAG", default="0.0.0")
|
||||
|
||||
# Remove leading 'v'
|
||||
version = re.sub('^v', '', version)
|
||||
version = re.sub("^v", "", version)
|
||||
|
||||
setup(
|
||||
name='anybadge',
|
||||
description='Simple, flexible badge generator for project badges.',
|
||||
name="anybadge",
|
||||
description="Simple, flexible badge generator for project badges.",
|
||||
long_description=long_description,
|
||||
long_description_content_type='text/markdown',
|
||||
long_description_content_type="text/markdown",
|
||||
version=version,
|
||||
author='Jon Grace-Cox',
|
||||
author_email='jongracecox@gmail.com',
|
||||
packages=['anybadge'],
|
||||
py_modules=['anybadge_server'],
|
||||
setup_requires=['setuptools', 'wheel'],
|
||||
author="Jon Grace-Cox",
|
||||
author_email="jongracecox@gmail.com",
|
||||
packages=["anybadge"],
|
||||
py_modules=["anybadge_server"],
|
||||
setup_requires=["setuptools", "wheel"],
|
||||
tests_require=[],
|
||||
install_requires=['packaging'],
|
||||
package_data={'anybadge': ['templates/*.svg']},
|
||||
options={
|
||||
'bdist_wheel': {'universal': False}
|
||||
},
|
||||
python_requires='>=3.4',
|
||||
url='https://github.com/jongracecox/anybadge',
|
||||
install_requires=["packaging"],
|
||||
package_data={"anybadge": ["templates/*.svg"]},
|
||||
options={"bdist_wheel": {"universal": False}},
|
||||
python_requires=">=3.4",
|
||||
url="https://github.com/jongracecox/anybadge",
|
||||
entry_points={
|
||||
'console_scripts': ['anybadge=anybadge.cli:main',
|
||||
'anybadge-server=anybadge.server.cli:main'],
|
||||
"console_scripts": [
|
||||
"anybadge=anybadge.cli:main",
|
||||
"anybadge-server=anybadge.server.cli:main",
|
||||
],
|
||||
},
|
||||
classifiers=[
|
||||
'License :: OSI Approved :: MIT License'
|
||||
]
|
||||
classifiers=["License :: OSI Approved :: MIT License"],
|
||||
)
|
||||
|
@@ -20,4 +20,4 @@
|
||||
<text x="{{ value anchor shadow }}" y="15" fill="#010101" fill-opacity=".3">{{ value }}</text>
|
||||
<text x="{{ value anchor }}" y="14">{{ value }}</text>
|
||||
</g>
|
||||
</svg>
|
||||
</svg>
|
||||
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 1.2 KiB |
@@ -7,319 +7,389 @@ class TestAnybadge(TestCase):
|
||||
"""Test case class for anybadge package."""
|
||||
|
||||
def setUp(self):
|
||||
if not hasattr(self, 'assertRaisesRegex'):
|
||||
if not hasattr(self, "assertRaisesRegex"):
|
||||
self.assertRaisesRegex = self.assertRaisesRegexp
|
||||
|
||||
|
||||
def test_badge_equal_label_value_width(self):
|
||||
"""Test that label and value widths are equal when text is the same."""
|
||||
badge = Badge(label='a', value='a', num_padding_chars=0)
|
||||
badge = Badge(label="a", value="a", num_padding_chars=0)
|
||||
|
||||
self.assertEqual(badge.label_width, badge.value_width)
|
||||
|
||||
def test_badge_equal_split(self):
|
||||
"""Test that the color split is in the middle when label and value are equal width."""
|
||||
badge = Badge(label='a', value='a')
|
||||
badge = Badge(label="a", value="a")
|
||||
|
||||
self.assertEqual(int(badge.badge_width / 2), badge.color_split_position)
|
||||
|
||||
def test_badge_equal_split_no_padding(self):
|
||||
"""Test that the color split is in the middle when label and value are equal width."""
|
||||
badge = Badge(label='a', value='a', num_padding_chars=0)
|
||||
badge = Badge(label="a", value="a", num_padding_chars=0)
|
||||
|
||||
self.assertEqual(int(badge.badge_width / 2), badge.color_split_position)
|
||||
|
||||
def test_badge_width_with_long_value_text(self):
|
||||
"""Test the width of a badge generated with a long text value."""
|
||||
|
||||
badge = Badge(label='CppCheck',
|
||||
value='err: 2 | warn: 9 | info: 99 | style: 365',
|
||||
default_color='red')
|
||||
badge = Badge(
|
||||
label="CppCheck",
|
||||
value="err: 2 | warn: 9 | info: 99 | style: 365",
|
||||
default_color="red",
|
||||
)
|
||||
|
||||
badge.write_badge('test_badge_1.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_1.svg", overwrite=True)
|
||||
|
||||
self.assertLessEqual(badge.badge_width, 326)
|
||||
|
||||
def test_badge_width_with_long_value_text_zero_padding(self):
|
||||
"""Test the width of a badge generated with a long text value."""
|
||||
|
||||
badge = Badge(label='CppCheck',
|
||||
value='err: 2 | warn: 9 | info: 99 | style: 365',
|
||||
default_color='red',
|
||||
num_padding_chars=0)
|
||||
badge = Badge(
|
||||
label="CppCheck",
|
||||
value="err: 2 | warn: 9 | info: 99 | style: 365",
|
||||
default_color="red",
|
||||
num_padding_chars=0,
|
||||
)
|
||||
|
||||
badge.write_badge('test_badge_2.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_2.svg", overwrite=True)
|
||||
|
||||
self.assertLessEqual(badge.badge_width, 306)
|
||||
|
||||
def test_badge_width_with_medium_value_text(self):
|
||||
"""Test the width of a badge generated with a medium text value."""
|
||||
|
||||
badge = Badge(label='medium',
|
||||
value='89.67%',
|
||||
default_color='green')
|
||||
badge = Badge(label="medium", value="89.67%", default_color="green")
|
||||
|
||||
badge.write_badge('test_badge_medium.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_medium.svg", overwrite=True)
|
||||
|
||||
self.assertLessEqual(badge.badge_width, 138)
|
||||
|
||||
def test_badge_width_with_medium_value_text_zero_pad(self):
|
||||
"""Test the width of a badge generated with a medium text value."""
|
||||
|
||||
badge = Badge(label='medium no padding',
|
||||
value='89.67%',
|
||||
default_color='green',
|
||||
num_padding_chars=0)
|
||||
badge = Badge(
|
||||
label="medium no padding",
|
||||
value="89.67%",
|
||||
default_color="green",
|
||||
num_padding_chars=0,
|
||||
)
|
||||
|
||||
badge.write_badge('test_badge_medium_no_padding.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_medium_no_padding.svg", overwrite=True)
|
||||
|
||||
self.assertLessEqual(badge.badge_width, 156)
|
||||
|
||||
def test_badge_width_with_short_value_text(self):
|
||||
"""Test the width of a badge generated with a short text value."""
|
||||
|
||||
badge = Badge(label='short',
|
||||
value='1',
|
||||
default_color='green')
|
||||
badge = Badge(label="short", value="1", default_color="green")
|
||||
|
||||
badge.write_badge('test_badge_short.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_short.svg", overwrite=True)
|
||||
|
||||
self.assertLessEqual(badge.badge_width, 101)
|
||||
|
||||
def test_badge_width_with_short_value_text_zero_pad(self):
|
||||
"""Test the width of a badge generated with a short text value."""
|
||||
|
||||
badge = Badge(label='short value no padding',
|
||||
value='1',
|
||||
default_color='green',
|
||||
num_padding_chars=0)
|
||||
badge = Badge(
|
||||
label="short value no padding",
|
||||
value="1",
|
||||
default_color="green",
|
||||
num_padding_chars=0,
|
||||
)
|
||||
|
||||
badge.write_badge('test_badge_short_no_padding.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_short_no_padding.svg", overwrite=True)
|
||||
|
||||
self.assertLessEqual(badge.badge_width, 143)
|
||||
|
||||
def test_badge_width_with_tiny_value_text(self):
|
||||
"""Test the width of a badge generated with a short text value."""
|
||||
|
||||
badge = Badge(label='a',
|
||||
value='1',
|
||||
default_color='green')
|
||||
badge = Badge(label="a", value="1", default_color="green")
|
||||
|
||||
badge.write_badge('test_badge_tiny_text_value.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_tiny_text_value.svg", overwrite=True)
|
||||
|
||||
self.assertLessEqual(badge.badge_width, 76)
|
||||
|
||||
def test_badge_width_with_tiny_value_text_no_padding(self):
|
||||
"""Test the width of a badge generated with a short text value."""
|
||||
|
||||
badge = Badge(label='a',
|
||||
value='1',
|
||||
default_color='green',
|
||||
num_padding_chars=0)
|
||||
badge = Badge(label="a", value="1", default_color="green", num_padding_chars=0)
|
||||
|
||||
badge.write_badge('test_badge_tiny_text_value_no_padding.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_tiny_text_value_no_padding.svg", overwrite=True)
|
||||
|
||||
self.assertLessEqual(badge.badge_width, 76)
|
||||
|
||||
def test_badge_with_thresholds(self):
|
||||
"""Test generating a badge using thresholds."""
|
||||
thresholds = {
|
||||
2: 'red', 4: 'orange', 6: 'green', 8: 'brightgreen'
|
||||
}
|
||||
thresholds = {2: "red", 4: "orange", 6: "green", 8: "brightgreen"}
|
||||
|
||||
badge = Badge('thresholds', '2.22', value_suffix='%',
|
||||
thresholds=thresholds)
|
||||
badge = Badge("thresholds", "2.22", value_suffix="%", thresholds=thresholds)
|
||||
|
||||
badge.write_badge('test_badge_thresholds.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_thresholds.svg", overwrite=True)
|
||||
|
||||
def test_badge_with_text_color(self):
|
||||
"""Test generating a badge with alternate text_color."""
|
||||
|
||||
badge = Badge('text color', '2.22', value_suffix='%',
|
||||
text_color='#010101,#101010')
|
||||
badge = Badge(
|
||||
"text color", "2.22", value_suffix="%", text_color="#010101,#101010"
|
||||
)
|
||||
|
||||
badge.write_badge('test_badge_text_color.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_text_color.svg", overwrite=True)
|
||||
|
||||
def test_multiple_badges_in_one_session(self):
|
||||
|
||||
badges = [
|
||||
Badge('multiple 1', value='100', value_suffix='%', num_padding_chars=0),
|
||||
Badge('multiple 2', value='1234567890'),
|
||||
Badge("multiple 1", value="100", value_suffix="%", num_padding_chars=0),
|
||||
Badge("multiple 2", value="1234567890"),
|
||||
]
|
||||
|
||||
self.assertNotEqual(badges[0].badge_width, badges[1].badge_width)
|
||||
|
||||
def test_multiple_badges_get_different_mask_id(self):
|
||||
badges = [
|
||||
Badge('multiple 1', value='100', value_suffix='%', num_padding_chars=0),
|
||||
Badge('multiple 2', value='1234567890'),
|
||||
Badge("multiple 1", value="100", value_suffix="%", num_padding_chars=0),
|
||||
Badge("multiple 2", value="1234567890"),
|
||||
]
|
||||
|
||||
self.assertNotEqual(badges[0].mask_id, badges[1].mask_id)
|
||||
|
||||
def test_integer_str_value_is_handled_as_integer(self):
|
||||
badge = Badge('integer', value='1234')
|
||||
badge = Badge("integer", value="1234")
|
||||
|
||||
self.assertTrue(badge.value_is_int)
|
||||
self.assertFalse(badge.value_is_float)
|
||||
badge.write_badge('test_badge_int_str.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_int_str.svg", overwrite=True)
|
||||
|
||||
def test_integer_int_value_is_handled_as_integer(self):
|
||||
badge = Badge('integer', value=1234)
|
||||
badge = Badge("integer", value=1234)
|
||||
|
||||
self.assertTrue(badge.value_is_int)
|
||||
self.assertFalse(badge.value_is_float)
|
||||
badge.write_badge('test_badge_int.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_int.svg", overwrite=True)
|
||||
|
||||
def test_float_str_value_is_handled_as_float(self):
|
||||
badge = Badge('float str', value='1234.1')
|
||||
badge = Badge("float str", value="1234.1")
|
||||
|
||||
self.assertFalse(badge.value_is_int)
|
||||
self.assertTrue(badge.value_is_float)
|
||||
badge.write_badge('test_badge_float_str.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_float_str.svg", overwrite=True)
|
||||
|
||||
def test_float_value_is_handled_as_float(self):
|
||||
badge = Badge('float int', value=1234.1)
|
||||
badge = Badge("float int", value=1234.1)
|
||||
|
||||
self.assertFalse(badge.value_is_int)
|
||||
self.assertTrue(badge.value_is_float)
|
||||
badge.write_badge('test_badge_float.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_float.svg", overwrite=True)
|
||||
|
||||
def test_float_value_with_zero_decimal(self):
|
||||
badge = Badge('float with zeros', value='10.00')
|
||||
badge = Badge("float with zeros", value="10.00")
|
||||
|
||||
self.assertFalse(badge.value_is_int)
|
||||
self.assertTrue(badge.value_is_float)
|
||||
badge.write_badge('test_badge_float_zeros.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_float_zeros.svg", overwrite=True)
|
||||
|
||||
def test_float_value_with_non_zero_decimal(self):
|
||||
badge = Badge('float str no decimal', value='10.01')
|
||||
badge = Badge("float str no decimal", value="10.01")
|
||||
|
||||
self.assertFalse(badge.value_is_int)
|
||||
self.assertTrue(badge.value_is_float)
|
||||
badge.write_badge('test_badge_float-str-no-decimal.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_float-str-no-decimal.svg", overwrite=True)
|
||||
|
||||
def test_padding_label(self):
|
||||
badge = Badge('label padding', value='10.01', num_label_padding_chars=2)
|
||||
badge = Badge("label padding", value="10.01", num_label_padding_chars=2)
|
||||
|
||||
badge.write_badge('test_badge_padding_label.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_padding_label.svg", overwrite=True)
|
||||
|
||||
def test_padding_value(self):
|
||||
badge = Badge('value padding', value='10.01', num_value_padding_chars=2)
|
||||
badge = Badge("value padding", value="10.01", num_value_padding_chars=2)
|
||||
|
||||
badge.write_badge('test_badge_padding_value.svg', overwrite=True)
|
||||
badge.write_badge("test_badge_padding_value.svg", overwrite=True)
|
||||
|
||||
def test_value_formatting(self):
|
||||
badge = Badge('value formatting', value="10", value_format="%s hits/sec")
|
||||
badge = Badge("value formatting", value="10", value_format="%s hits/sec")
|
||||
|
||||
self.assertEqual("10 hits/sec", badge.value_text)
|
||||
|
||||
def test_font_name(self):
|
||||
font = 'Arial, Helvetica, sans-serif'
|
||||
badge = Badge('font', value=font, font_name=font)
|
||||
badge.write_badge('test_badge_font.svg', overwrite=True)
|
||||
font = "Arial, Helvetica, sans-serif"
|
||||
badge = Badge("font", value=font, font_name=font)
|
||||
badge.write_badge("test_badge_font.svg", overwrite=True)
|
||||
|
||||
badge_repr = repr(badge)
|
||||
self.assertTrue("font_name='Arial, Helvetica, sans-serif'" in badge_repr)
|
||||
|
||||
def test_invalid_font_name(self):
|
||||
font = 'Invalid font'
|
||||
font = "Invalid font"
|
||||
with self.assertRaises(ValueError):
|
||||
_ = Badge('font', value=font, font_name=font)
|
||||
_ = Badge("font", value=font, font_name=font)
|
||||
|
||||
def test_font_size(self):
|
||||
for size in [10, 11, 12]:
|
||||
badge = Badge('font size', value=size, font_size=size)
|
||||
badge.write_badge('test_badge_font_size_%s.svg' % size, overwrite=True)
|
||||
badge = Badge("font size", value=size, font_size=size)
|
||||
badge.write_badge("test_badge_font_size_%s.svg" % size, overwrite=True)
|
||||
|
||||
def test_font_size_repr(self):
|
||||
badge = Badge('font size', value=10, font_size=10)
|
||||
badge = Badge("font size", value=10, font_size=10)
|
||||
badge_repr = repr(badge)
|
||||
self.assertTrue("font_size=10" in badge_repr)
|
||||
|
||||
def test_template_from_file(self):
|
||||
file = "tests/template.svg"
|
||||
badge = Badge('template from file', value=file, template=file)
|
||||
badge = Badge("template from file", value=file, template=file)
|
||||
_ = badge.badge_svg_text
|
||||
|
||||
def test_repr_svg(self):
|
||||
badge = Badge('label', 'value')
|
||||
badge = Badge("label", "value")
|
||||
self.assertEqual(badge.badge_svg_text, badge._repr_svg_())
|
||||
|
||||
def test_str_value_with_threshold_and_default(self):
|
||||
badge = Badge('label', value='fred', thresholds={'pass': 'green', 'fail': 'red'}, default_color='orange')
|
||||
self.assertEqual('orange', badge.badge_color)
|
||||
badge = Badge(
|
||||
"label",
|
||||
value="fred",
|
||||
thresholds={"pass": "green", "fail": "red"},
|
||||
default_color="orange",
|
||||
)
|
||||
self.assertEqual("orange", badge.badge_color)
|
||||
|
||||
def test_invalid_color(self):
|
||||
with self.assertRaises(ValueError):
|
||||
badge = Badge('label', value='fred', default_color='floberry')
|
||||
badge = Badge("label", value="fred", default_color="floberry")
|
||||
_ = badge.badge_color_code
|
||||
|
||||
def test_invalid_write_path(self):
|
||||
badge = Badge('label', 'value')
|
||||
with self.assertRaisesRegex(ValueError, r'File location may not be a directory\.'):
|
||||
badge.write_badge('tests/')
|
||||
badge = Badge("label", "value")
|
||||
with self.assertRaisesRegex(
|
||||
ValueError, r"File location may not be a directory\."
|
||||
):
|
||||
badge.write_badge("tests/")
|
||||
|
||||
with self.assertRaisesRegex(RuntimeError, r'File ".*tests\/exists\.svg" already exists\.'):
|
||||
badge.write_badge('tests/exists')
|
||||
badge.write_badge('tests/exists')
|
||||
with self.assertRaisesRegex(
|
||||
RuntimeError, r'File ".*tests\/exists\.svg" already exists\.'
|
||||
):
|
||||
badge.write_badge("tests/exists")
|
||||
badge.write_badge("tests/exists")
|
||||
|
||||
def test_arg_parsing(self):
|
||||
args = parse_args(['-l', 'label', '-v', 'value'])
|
||||
self.assertEqual('label', args.label)
|
||||
self.assertEqual('value', args.value)
|
||||
args = parse_args(["-l", "label", "-v", "value"])
|
||||
self.assertEqual("label", args.label)
|
||||
self.assertEqual("value", args.value)
|
||||
|
||||
def test_main_print(self):
|
||||
main(['--label', 'label', '--value', 'value'])
|
||||
main(["--label", "label", "--value", "value"])
|
||||
|
||||
def test_main_write_to_file(self):
|
||||
main(['--label', 'label', '--value', 'value', '--file', 'test_badge_main.svg', '--overwrite'])
|
||||
main(
|
||||
[
|
||||
"--label",
|
||||
"label",
|
||||
"--value",
|
||||
"value",
|
||||
"--file",
|
||||
"test_badge_main.svg",
|
||||
"--overwrite",
|
||||
]
|
||||
)
|
||||
|
||||
def test_main_thresholds(self):
|
||||
main([
|
||||
'--label', 'label',
|
||||
'--value', 'value',
|
||||
'--file', 'test_badge_main_threshold.svg',
|
||||
'--overwrite',
|
||||
'2=red', '4=orange'])
|
||||
main(
|
||||
[
|
||||
"--label",
|
||||
"label",
|
||||
"--value",
|
||||
"value",
|
||||
"--file",
|
||||
"test_badge_main_threshold.svg",
|
||||
"--overwrite",
|
||||
"2=red",
|
||||
"4=orange",
|
||||
]
|
||||
)
|
||||
|
||||
def test_named_threshold(self):
|
||||
main([
|
||||
'--value', 'value',
|
||||
'--file', 'test_badge_main_named_threshold.svg',
|
||||
'--overwrite',
|
||||
'coverage'])
|
||||
main(
|
||||
[
|
||||
"--value",
|
||||
"value",
|
||||
"--file",
|
||||
"test_badge_main_named_threshold.svg",
|
||||
"--overwrite",
|
||||
"coverage",
|
||||
]
|
||||
)
|
||||
|
||||
def test_main_missing_value(self):
|
||||
with self.assertRaisesRegex(ValueError, r'Label has not been set\. Please use --label argument\.'):
|
||||
main(['--value', '123', '--file', 'test_badge_main.svg', '--overwrite'])
|
||||
with self.assertRaisesRegex(
|
||||
ValueError, r"Label has not been set\. Please use --label argument\."
|
||||
):
|
||||
main(["--value", "123", "--file", "test_badge_main.svg", "--overwrite"])
|
||||
|
||||
def test_version_comparison(self):
|
||||
# Define thresholds: <3.0.0=red, <3.2.0=orange <999.0.0=green
|
||||
badge = Badge('Version', value='1.0.0', thresholds={'3.0.0': 'red', '3.2.0': 'orange', '999.0.0': 'green'}, semver=True)
|
||||
self.assertEqual('red', badge.badge_color)
|
||||
badge = Badge(
|
||||
"Version",
|
||||
value="1.0.0",
|
||||
thresholds={"3.0.0": "red", "3.2.0": "orange", "999.0.0": "green"},
|
||||
semver=True,
|
||||
)
|
||||
self.assertEqual("red", badge.badge_color)
|
||||
|
||||
# Define thresholds: <3.0.0=red, <3.2.0=orange <999.0.0=green
|
||||
badge = Badge('Version', value='3.0.0', thresholds={'3.0.0': 'red', '3.2.0': 'orange', '999.0.0': 'green'}, semver=True)
|
||||
self.assertEqual('orange', badge.badge_color)
|
||||
badge = Badge(
|
||||
"Version",
|
||||
value="3.0.0",
|
||||
thresholds={"3.0.0": "red", "3.2.0": "orange", "999.0.0": "green"},
|
||||
semver=True,
|
||||
)
|
||||
self.assertEqual("orange", badge.badge_color)
|
||||
|
||||
# Define thresholds: <3.0.0=red, <3.2.0=orange <999.0.0=green
|
||||
badge = Badge('Version', value='3.1.0', thresholds={'3.0.0': 'red', '3.2.0': 'orange', '999.0.0': 'green'}, semver=True)
|
||||
self.assertEqual('orange', badge.badge_color)
|
||||
badge = Badge(
|
||||
"Version",
|
||||
value="3.1.0",
|
||||
thresholds={"3.0.0": "red", "3.2.0": "orange", "999.0.0": "green"},
|
||||
semver=True,
|
||||
)
|
||||
self.assertEqual("orange", badge.badge_color)
|
||||
|
||||
# Define thresholds: <3.0.0=red, <3.2.0=orange <999.0.0=green
|
||||
badge = Badge('Version', value='3.2.0', thresholds={'3.0.0': 'red', '3.2.0': 'orange', '999.0.0': 'green'}, semver=True)
|
||||
self.assertEqual('green', badge.badge_color)
|
||||
badge = Badge(
|
||||
"Version",
|
||||
value="3.2.0",
|
||||
thresholds={"3.0.0": "red", "3.2.0": "orange", "999.0.0": "green"},
|
||||
semver=True,
|
||||
)
|
||||
self.assertEqual("green", badge.badge_color)
|
||||
|
||||
badge = Badge('Version', value='3.2.1', thresholds={'3.0.0': 'red', '3.2.0': 'orange', '999.0.0': 'green'}, semver=True)
|
||||
self.assertEqual('green', badge.badge_color)
|
||||
badge = Badge(
|
||||
"Version",
|
||||
value="3.2.1",
|
||||
thresholds={"3.0.0": "red", "3.2.0": "orange", "999.0.0": "green"},
|
||||
semver=True,
|
||||
)
|
||||
self.assertEqual("green", badge.badge_color)
|
||||
|
||||
# Define thresholds: <3.0.0=red, <3.2.0=orange <999.0.0=green
|
||||
badge = Badge('Version', value='10.20.30', thresholds={'3.0.0': 'red', '3.2.0': 'orange', '999.0.0': 'green'}, semver=True)
|
||||
self.assertEqual('green', badge.badge_color)
|
||||
badge = Badge(
|
||||
"Version",
|
||||
value="10.20.30",
|
||||
thresholds={"3.0.0": "red", "3.2.0": "orange", "999.0.0": "green"},
|
||||
semver=True,
|
||||
)
|
||||
self.assertEqual("green", badge.badge_color)
|
||||
|
||||
# Define thresholds: <3.0.0=red, <13.2.0=orange <999.0.0=green
|
||||
badge = Badge('Version', value='14.0.0', thresholds={'3.0.0': 'red', '13.2.0': 'orange', '999.0.0': 'green'}, semver=True)
|
||||
self.assertEqual('green', badge.badge_color)
|
||||
badge = Badge(
|
||||
"Version",
|
||||
value="14.0.0",
|
||||
thresholds={"3.0.0": "red", "13.2.0": "orange", "999.0.0": "green"},
|
||||
semver=True,
|
||||
)
|
||||
self.assertEqual("green", badge.badge_color)
|
||||
|
||||
badge = Badge('Version', value='12.0.0', thresholds={'3.0.0': 'red', '13.2.0': 'orange', '999.0.0': 'green'}, semver=True)
|
||||
self.assertEqual('orange', badge.badge_color)
|
||||
badge = Badge(
|
||||
"Version",
|
||||
value="12.0.0",
|
||||
thresholds={"3.0.0": "red", "13.2.0": "orange", "999.0.0": "green"},
|
||||
semver=True,
|
||||
)
|
||||
self.assertEqual("orange", badge.badge_color)
|
||||
|