Drop <3.7 support and add type hints (#59)

- Drop support for Python <3.7
- Bump the pre-commit version used in CI
- Add type hinting and docstrings
- Add mypy to pre-commit config
- Fix typing issues
- Update colors module
  - Update colors module to use uppercase hex codes
  - Add `__lt__` to allow sorting colors by name
- Fix `build_examples.py` to work with color Enum
- Update example badges in `README.md`
- Fix typing issues in server
- Update travis links in `README.md`
- Fix PyPi deployment bug (#60)
This commit is contained in:
Jon Grace-Cox
2022-08-08 23:19:50 -04:00
committed by GitHub
parent f16867114a
commit 8a434d95b5
36 changed files with 430 additions and 313 deletions

View File

@@ -13,4 +13,8 @@ repos:
- repo: https://github.com/psf/black
rev: 22.6.0
hooks:
- id: black
- id: black
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.971
hooks:
- id: mypy

View File

@@ -2,12 +2,6 @@ dist: xenial
language: python
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'
@@ -18,13 +12,13 @@ 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 &&
pip install -U pre-commit==2.20.0 &&
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
- sed -i "s/^version = .*/version = __version__ = \"$TRAVIS_TAG\"/" anybadge/__init__.py
deploy:
- provider: pypi
skip_cleanup: true

View File

@@ -3,7 +3,7 @@
Python project for generating badges for your projects
[![pypi package](https://badge.fury.io/py/anybadge.svg)](https://pypi.org/project/anybadge)
[![build status](https://api.travis-ci.org/jongracecox/anybadge.svg?branch=master)](https://travis-ci.org/jongracecox/anybadge)
[![build status](https://api.travis-ci.com/jongracecox/anybadge.svg?branch=master)](https://app.travis-ci.com/github/jongracecox/anybadge)
[![downloads](https://img.shields.io/pypi/dm/anybadge.svg)](https://pypistats.org/packages/anybadge)
[![GitHub last commit](https://img.shields.io/github/last-commit/jongracecox/anybadge.svg)](https://github.com/jongracecox/anybadge/commits/master)
[![GitHub](https://img.shields.io/github/license/jongracecox/anybadge.svg)](https://github.com/jongracecox/anybadge/blob/master/LICENSE)
@@ -137,29 +137,29 @@ badge = anybadge.Badge(label='custom color', value='teal', default_color='#00808
Available named colors are:
| Color Name | Hex Code | Example |
| ---------- | -------- | ------- |
| aqua | #00FFFF | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_aqua.svg) |
| black | #000000 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_black.svg) |
| blue | #0000FF | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_blue.svg) |
| bright_red | #FF0000 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_bright_red.svg) |
| bright_yellow | #FFFF00 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_bright_yellow.svg) |
| fuchsia | #FF00FF | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_fuchsia.svg) |
| gray | #808080 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_gray.svg) |
| green | #4C1 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_green.svg) |
| light_grey | #9F9F9F | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_light_grey.svg) |
| lime | #00FF00 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_lime.svg) |
| maroon | #800000 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_maroon.svg) |
| navy | #000080 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_navy.svg) |
| olive | #808000 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_olive.svg) |
| orange | #FE7D37 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_orange.svg) |
| purple | #800080 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_purple.svg) |
| red | #E05D44 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_red.svg) |
| silver | #C0C0C0 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_silver.svg) |
| teal | #008080 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_teal.svg) |
| white | #FFFFFF | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_white.svg) |
| yellow | #DFB317 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_yellow.svg) |
| yellow_green | #A4A61D | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_yellow_green.svg) |
| Color Name | Hex | Example |
| ------------- | ------- | ------- |
| aqua | #00FFFF | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_aqua.svg) |
| black | #000000 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_black.svg) |
| blue | #0000FF | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_blue.svg) |
| bright_red | #FF0000 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_bright_red.svg) |
| bright_yellow | #FFFF00 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_bright_yellow.svg)|
| fuchsia | #FF00FF | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_fuchsia.svg) |
| gray | #808080 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_gray.svg) |
| green | #4C1 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_green.svg) |
| light_grey | #9F9F9F | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_light_grey.svg) |
| lime | #00FF00 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_lime.svg) |
| maroon | #800000 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_maroon.svg) |
| navy | #000080 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_navy.svg) |
| olive | #808000 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_olive.svg) |
| orange | #FE7D37 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_orange.svg) |
| purple | #800080 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_purple.svg) |
| red | #E05D44 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_red.svg) |
| silver | #C0C0C0 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_silver.svg) |
| teal | #008080 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_teal.svg) |
| white | #FFFFFF | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_white.svg) |
| yellow | #DFB317 | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_yellow.svg) |
| yellow_green | #A4A61D | ![](https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_yellow_green.svg) |
### Semantic version support

View File

@@ -1,5 +1,6 @@
import os
from collections import OrderedDict
from typing import Dict, Type, Optional, Union
from . import config
from .colors import Color
@@ -98,25 +99,28 @@ class Badge:
'#4c1'
"""
#: Singleton variable to track current max mask_id. This is used by _get_next_mask_str class method.
mask_id: int
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,
font_name: str = None,
font_size: int = None,
num_padding_chars: int = None,
num_label_padding_chars: float = None,
num_value_padding_chars: float = None,
template: str = None,
style: str = None,
value_prefix: str = "",
value_suffix: str = "",
thresholds: Optional[Dict[float, str]] = None,
default_color: str = None,
use_max_when_value_exceeds: bool = True,
value_format: str = None,
text_color: str = None,
semver: bool = False,
):
"""Constructor for Badge class."""
# Set defaults if values were not passed
@@ -181,9 +185,9 @@ class Badge:
self.value_text_color = text_colors[1]
self.use_max_when_value_exceeds = use_max_when_value_exceeds
self.mask_id = self.__class__._get_next_mask_id()
self.mask_str = self.__class__._get_next_mask_str()
def __repr__(self):
def __repr__(self) -> str:
"""Return a representation of the Badge object instance.
The output of the __repr__ function could be used to recreate the current object.
@@ -264,7 +268,7 @@ class Badge:
optional_args,
)
def _repr_svg_(self):
def _repr_svg_(self) -> str:
"""Return SVG representation when used inside Jupyter notebook cells.
This will render the SVG immediately inside a notebook cell when creating
@@ -273,7 +277,7 @@ class Badge:
return self.badge_svg_text
@classmethod
def _get_next_mask_id(cls):
def _get_next_mask_str(cls) -> str:
"""Return a new mask ID from a singleton sequence maintained on the class.
Returns: str
@@ -285,7 +289,7 @@ class Badge:
return config.MASK_ID_PREFIX + str(cls.mask_id)
def _get_svg_template(self):
def _get_svg_template(self) -> str:
"""Return the correct SVG template to render, based on the style and template
that have been set
@@ -308,7 +312,7 @@ class Badge:
return self.template
@property
def semver_version(self):
def semver_version(self) -> Version:
"""The semantic version represented by the value string.
Returns: Version
@@ -316,20 +320,25 @@ class Badge:
return Version(self.value)
@property
def semver_thresholds(self):
def semver_thresholds(self) -> Optional[OrderedDict]:
"""Thresholds as a dict using Version as keys."""
# Version is not a hashable type, so can't be used to create an
# ordered dict directly. First we need to create an ordered list of keys
if not self.thresholds:
return None
ordered_keys = sorted(self.thresholds.keys(), key=Version)
return OrderedDict((key, self.thresholds[key]) for key in ordered_keys)
@property
def float_thresholds(self):
def float_thresholds(self) -> Optional[Dict[float, str]]:
"""Thresholds as a dict using floats as keys."""
if not self.thresholds:
return None
return {float(k): v for k, v in self.thresholds.items()}
@property
def value_is_float(self):
def value_is_float(self) -> bool:
"""Identify whether the value text is a float.
Returns: bool
@@ -349,7 +358,7 @@ class Badge:
return True
@property
def value_is_int(self):
def value_is_int(self) -> bool:
"""Identify whether the value text is an int.
Returns: bool
@@ -363,7 +372,7 @@ class Badge:
return a == b
@property
def value_type(self):
def value_type(self) -> Type:
"""The Python type associated with the value.
Returns: type
@@ -378,9 +387,17 @@ class Badge:
return str
@property
def label_width(self):
def label_width(self) -> int:
"""The SVG width of the label text.
┌───────────────────────────┬────────────────────────────────┐
│ │ │
│ Label text │ Value │
│ │ │
└───────────────────────────┴────────────────────────────────┘
◀────────▶
label_width
Returns: int
"""
return int(
@@ -389,9 +406,17 @@ class Badge:
)
@property
def value_width(self):
def value_width(self) -> int:
"""The SVG width of the value text.
┌───────────────────────────┬────────────────────────────────┐
│ │ │
│ Label text │ Value text │
│ │ │
└───────────────────────────┴────────────────────────────────┘
◀────────▶
value_width
Returns: int
"""
return int(
@@ -400,15 +425,23 @@ class Badge:
)
@property
def value_box_width(self):
def value_box_width(self) -> int:
"""The SVG width of the value text box.
┌───────────────────────────┬────────────────────────────────┐
│ │ │
│ Label text │ Value text │
│ │ │
└───────────────────────────┴────────────────────────────────┘
◀────────────────────────────────▶
value_box_width
Returns: int
"""
return self.value_width - 9
@property
def font_width(self):
def font_width(self) -> int:
"""Return the width multiplier for a font.
Returns:
@@ -422,25 +455,61 @@ class Badge:
return config.FONT_WIDTHS[self.font_name][self.font_size]
@property
def color_split_position(self):
def color_split_position(self) -> int:
"""The SVG x position where the color split should occur.
Split
┌──┘
┌───────────────────────────┬────────────────────────────────┐
│ │ │
│ Label text │ Value text │
│ │ │
└───────────────────────────┴────────────────────────────────┘
◀───────────────────────────▶
color_split_pos
Returns: int
"""
return self.badge_width - self.value_width
@property
def label_anchor(self):
def label_anchor(self) -> float:
"""The SVG x position of the middle anchor for the label text.
Middle of
label
┌──┘
┌───────────────────────────┬────────────────────────────────┐
│ │ │
│ Label text │ Value text │
│ │ │
└───────────────────────────┴────────────────────────────────┘
◀───────────▶
label_anchor
Returns: float
"""
return self.color_split_position / 2
@property
def value_anchor(self):
def value_anchor(self) -> float:
"""The SVG x position of the middle anchor for the value text.
Middle of
value
┌──┘
┌───────────────────────────┬────────────────────────────────┐
│ │ │
│ Label text │ Value text │
│ │ │
└───────────────────────────┴────────────────────────────────┘
◀──────────────────────────────────────────▶
value_anchor
Returns: float
"""
return self.color_split_position + (
@@ -448,25 +517,62 @@ class Badge:
)
@property
def label_anchor_shadow(self):
def label_anchor_shadow(self) -> float:
"""The SVG x position of the label shadow anchor.
The shadow for the label will appear behind the label.
┌ Text ──────────────────┐
│ │
│ ├────┐
│ │ │
└────┬───────────────────┘ │
│ │
└───────────── Shadow ───┘
The label_anchor_shadow is the distance from left to center of shadow:
┌─────────────────────────────┬─────────────────────────────────┐
│ ┌────────────┐ │ │
│ │ ├─┐ │ Value text │
│ └─┬──────────┘ │ │ │
│ └────────────┘ │ │
└─────────────────────────────┴─────────────────────────────────┘
◀─────────────▶
label_anchor_shadow
Returns: float
"""
return self.label_anchor + 1
@property
def value_anchor_shadow(self):
def value_anchor_shadow(self) -> float:
"""The SVG x position of the value shadow anchor.
┌─────────────────────────────┬─────────────────────────────────┐
│ │ ┌────────────┐ │
│ Label text │ │ ├─┐ │
│ │ └─┬──────────┘ │ │
│ │ └────────────┘ │
└─────────────────────────────┴─────────────────────────────────┘
◀───────────────────────────────────────────────▶
value_anchor_shadow
Returns: float
"""
return self.value_anchor + 1
@property
def badge_width(self):
def badge_width(self) -> int:
"""The total width of badge.
┌───────────────────────────┬────────────────────────────────┐
│ │ │
│ Label text │ Value text │
│ │ │
└───────────────────────────┴────────────────────────────────┘
◀───────────────────────────────────────────────────────────▶
badge_width
Returns: int
Examples:
@@ -478,8 +584,8 @@ class Badge:
return self.label_width + self.value_width
@property
def arc_start(self):
"""The position where the arc on the gitlab-scoped should start.
def arc_start(self) -> int:
"""The position where the arc on the arc should start.
Returns: int
@@ -492,7 +598,7 @@ class Badge:
return self.badge_width - 10
@property
def badge_svg_text(self):
def badge_svg_text(self) -> str:
"""The badge SVG text.
Returns: str
@@ -515,12 +621,12 @@ class Badge:
.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("{{ mask id }}", self.mask_str)
.replace("{{ value box width }}", str(self.value_box_width))
.replace("{{ arc start }}", str(self.arc_start))
)
def __str__(self):
def __str__(self) -> str:
"""Return string representation of badge.
This will return the badge SVG text.
@@ -535,7 +641,7 @@ class Badge:
"""
return self.badge_svg_text
def get_text_width(self, text):
def get_text_width(self, text) -> int:
"""Return the width of text.
Args:
@@ -554,7 +660,7 @@ class Badge:
return _get_approx_string_width(text, self.font_width)
@property
def badge_color(self):
def badge_color(self) -> str:
"""Badge color based on the configured thresholds.
Returns: str"""
@@ -568,6 +674,8 @@ class Badge:
else:
return self.default_color
thresholds: Optional[Union[Dict[float, str], OrderedDict[float, str]]]
# Set value and thresholds based on the value type. This will result in either
# value and thresholds as floats or value and thresholds as semantic versions.
if self.value_type == Version:
@@ -577,15 +685,17 @@ class Badge:
value = float(self.value)
thresholds = self.float_thresholds
# Convert the threshold dictionary into a sorted list of lists
threshold_list = [[self.value_type(i[0]), i[1]] for i in thresholds.items()]
threshold_list.sort(key=lambda x: x[0])
color = None
for threshold, color in threshold_list:
if value < threshold:
return color
if thresholds:
# Convert the threshold dictionary into a sorted list of lists
threshold_list = [[self.value_type(i[0]), i[1]] for i in thresholds.items()]
threshold_list.sort(key=lambda x: x[0])
for threshold, color in threshold_list:
if value < threshold:
return color
# If we drop out the top of the range then return the last max color
if color and self.use_max_when_value_exceeds:
@@ -633,7 +743,7 @@ class Badge:
(color, ", ".join(list(Color.__members__.keys()))),
)
def write_badge(self, file_path, overwrite=False):
def write_badge(self, file_path, overwrite=False) -> None:
"""Write badge to file."""
# Validate path (part 1)

View File

@@ -8,20 +8,23 @@ class Color(Enum):
SILVER = "#C0C0C0"
GRAY = "#808080"
BLACK = "#000000"
RED = "#e05d44"
RED = "#E05D44"
BRIGHT_RED = "#FF0000"
MAROON = "#800000"
OLIVE = "#808000"
LIME = "#00FF00"
BRIGHT_YELLOW = "#FFFF00"
YELLOW = "#dfb317"
GREEN = "#4c1"
YELLOW_GREEN = "#a4a61d"
YELLOW = "#DFB317"
GREEN = "#4C1"
YELLOW_GREEN = "#A4A61D"
AQUA = "#00FFFF"
TEAL = "#008080"
BLUE = "#0000FF"
NAVY = "#000080"
FUCHSIA = "#FF00FF"
PURPLE = "#800080"
ORANGE = "#fe7d37"
LIGHT_GREY = "#9f9f9f"
ORANGE = "#FE7D37"
LIGHT_GREY = "#9F9F9F"
def __lt__(self, other):
return self.name < other.name

View File

@@ -1,14 +1,16 @@
# Set some defaults
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_"
from typing import Dict
DEFAULT_FONT: str = "DejaVu Sans,Verdana,Geneva,sans-serif"
DEFAULT_FONT_SIZE: int = 11
NUM_PADDING_CHARS: float = 0.5
DEFAULT_COLOR: str = "#4c1"
DEFAULT_TEXT_COLOR: str = "#fff"
MASK_ID_PREFIX: str = "anybadge_"
# Dictionary for looking up approx pixel widths of
# supported fonts and font sizes.
FONT_WIDTHS = {
FONT_WIDTHS: Dict[str, Dict[int, int]] = {
"DejaVu Sans,Verdana,Geneva,sans-serif": {
10: 9,
11: 10,

View File

@@ -1,5 +1,5 @@
# Based on the following SO answer: https://stackoverflow.com/a/16008023/6252525
def _get_approx_string_width(text, font_width, fixed_width=False):
def _get_approx_string_width(text, font_width, fixed_width=False) -> int:
"""
Get the approximate width of a string using a specific average font width.

View File

@@ -10,42 +10,43 @@ logger = logging.getLogger(__name__)
def run(listen_address: str = None, port: int = None):
"""Run a persistent webserver."""
if not listen_address:
listen_address = config.DEFAULT_SERVER_LISTEN_ADDRESS
if not port:
port = config.DEFAULT_SERVER_PORT
server_address = (listen_address, port)
global SERVER_PORT, SERVER_LISTEN_ADDRESS
SERVER_PORT = port
SERVER_LISTEN_ADDRESS = listen_address
server_address: Tuple[str, int] = (listen_address, port) # type: ignore
httpd = HTTPServer(server_address, AnyBadgeHTTPRequestHandler)
logger.info("Serving at: http://%s:%s" % server_address)
httpd.serve_forever()
try:
httpd.serve_forever()
except KeyboardInterrupt:
logger.info("Received keyboard interrupt. Shutting down...")
def parse_args():
def parse_args() -> argparse.Namespace:
"""Parse 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,
default=config.DEFAULT_SERVER_PORT,
help=f"Server port number. Default is {config.DEFAULT_SERVER_PORT}. This can also be set via an environment "
"variable called ``ANYBADGE_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,
default=config.DEFAULT_SERVER_LISTEN_ADDRESS,
help=f"Server listen address. Default is {config.DEFAULT_SERVER_LISTEN_ADDRESS}. This can also be set via an "
f"environment variable called ``ANYBADGE_LISTEN_ADDRESS``.",
)
parser.add_argument(
"-d", "--debug", action="store_true", help="Enable debug logging."
@@ -56,23 +57,23 @@ def parse_args():
def main():
"""Run server."""
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"]
config.DEFAULT_SERVER_PORT = environ["ANYBADGE_PORT"]
if "ANYBADGE_LISTEN_ADDRESS" in environ:
DEFAULT_SERVER_LISTEN_ADDRESS = environ["ANYBADGE_LISTEN_ADDRESS"]
config.DEFAULT_SERVER_LISTEN_ADDRESS = environ["ANYBADGE_LISTEN_ADDRESS"]
if "ANYBADGE_LOG_LEVEL" in environ:
DEFAULT_LOGGING_LEVEL = logging.getLevelName(environ["ANYBADGE_LOG_LEVEL"])
config.DEFAULT_LOGGING_LEVEL = logging.getLevelName(
environ["ANYBADGE_LOG_LEVEL"]
)
# Parse command line args
args = parse_args()
args: argparse.Namespace = parse_args()
# Set logging level
logging_level = DEFAULT_LOGGING_LEVEL
logging_level = config.DEFAULT_LOGGING_LEVEL
if args.debug:
logging_level = logging.DEBUG

View File

@@ -1,9 +1,9 @@
import logging
DEFAULT_SERVER_PORT = 8000
DEFAULT_SERVER_LISTEN_ADDRESS = "localhost"
DEFAULT_SERVER_PORT: int = 8000
DEFAULT_SERVER_LISTEN_ADDRESS: str = "localhost"
DEFAULT_LOGGING_LEVEL = logging.INFO
SERVER_PORT = DEFAULT_SERVER_PORT
SERVER_LISTEN_ADDRESS = DEFAULT_SERVER_LISTEN_ADDRESS
SERVER_PORT: int = DEFAULT_SERVER_PORT
SERVER_LISTEN_ADDRESS: str = DEFAULT_SERVER_LISTEN_ADDRESS

View File

@@ -3,7 +3,6 @@ import urllib.parse as urlparse
from http.server import BaseHTTPRequestHandler
from anybadge import Badge
from anybadge.server import config
logger = logging.getLogger(__name__)
@@ -55,7 +54,9 @@ class AnyBadgeHTTPRequestHandler(BaseHTTPRequestHandler):
self.wfile.write(b"<html><head><title>Anybadge Web Server.</title></head>")
self.wfile.write(b"<body>")
help_text = """
listen_host, listen_port = self.server.server_address
help_text = f"""
<h1>Welcome to the Anybadge Web Server.</h1>
You are seeing this message because you haven't passed all the query parameters
@@ -65,11 +66,9 @@ class AnyBadgeHTTPRequestHandler(BaseHTTPRequestHandler):
Here is an example:
<a href="http://localhost:{port}/?label=Project%20Awesomeness&value=110%">\
http://localhost:{port}/?label=Project%20Awesomeness&value=110%</a>
""".format(
port=config.SERVER_PORT
)
<a href="http://{listen_host}:{listen_port}/?label=Project%20Awesomeness&value=110%">\
http://{listen_host}:{listen_port}/?label=Project%20Awesomeness&value=110%</a>
"""
for line in help_text.splitlines():
self.wfile.write(str.encode("<p>%s</p>" % line))

View File

@@ -16,7 +16,7 @@ class Style(Enum):
self.suffix = suffix
@classmethod
def exists(cls, name: str):
def exists(cls, name: str) -> bool:
"""Test whether a style exists."""
try:
_ = cls[name]

View File

@@ -14,6 +14,11 @@ def get_template(name: str) -> str:
"""
try:
return pkgutil.get_data(__name__, name + ".svg").decode("utf-8")
data = pkgutil.get_data(__name__, name + ".svg")
except FileNotFoundError as e:
raise UnknownBadgeTemplate from e
if not data:
raise UnknownBadgeTemplate
return data.decode("utf-8")

View File

@@ -3,21 +3,20 @@ import anybadge
if __name__ == "__main__":
print(
"""| Color Name | Hex Code | Example |
| ---------- | -------- | ------- |"""
"""
| Color Name | Hex | Example |
| ------------- | ------- | ------- |"""
)
for color, hex in sorted(anybadge.COLORS.items()):
for color in sorted(anybadge.colors.Color):
file = "examples/color_" + color + ".svg"
file = "examples/color_" + color.name.lower() + ".svg"
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.name.lower(), default_color=color.value
).write_badge(file, overwrite=True)
print(
"| {color} | {hex} | ![]({url}) |".format(
color=color, hex=hex.upper(), url=url
)
f"| {color.name.lower():<13} | {color.value.upper():<7} | ![]({f'{url})':<84}|"
)

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="118" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="79" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_43">
<rect width="118" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_1">
<rect width="79" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_43)">
<g mask="url(#anybadge_1)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#00FFFF" d="M41 0h77v20H41z"/>
<path fill="url(#b)" d="M0 0h118v20H0z"/>
<path fill="#00FFFF" d="M41 0h38v20H41z"/>
<path fill="url(#b)" d="M0 0h79v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="80.5" y="15" fill="#010101" fill-opacity=".3">Color.AQUA</text>
<text x="79.5" y="14">Color.AQUA</text>
<text x="61.0" y="15" fill="#010101" fill-opacity=".3">aqua</text>
<text x="60.0" y="14">aqua</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="122" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="83" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_44">
<rect width="122" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_2">
<rect width="83" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_44)">
<g mask="url(#anybadge_2)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#000000" d="M41 0h81v20H41z"/>
<path fill="url(#b)" d="M0 0h122v20H0z"/>
<path fill="#000000" d="M41 0h42v20H41z"/>
<path fill="url(#b)" d="M0 0h83v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="82.5" y="15" fill="#010101" fill-opacity=".3">Color.BLACK</text>
<text x="81.5" y="14">Color.BLACK</text>
<text x="63.0" y="15" fill="#010101" fill-opacity=".3">black</text>
<text x="62.0" y="14">black</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="115" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="76" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_45">
<rect width="115" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_3">
<rect width="76" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_45)">
<g mask="url(#anybadge_3)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#0000FF" d="M41 0h74v20H41z"/>
<path fill="url(#b)" d="M0 0h115v20H0z"/>
<path fill="#0000FF" d="M41 0h35v20H41z"/>
<path fill="url(#b)" d="M0 0h76v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="79.0" y="15" fill="#010101" fill-opacity=".3">Color.BLUE</text>
<text x="78.0" y="14">Color.BLUE</text>
<text x="59.5" y="15" fill="#010101" fill-opacity=".3">blue</text>
<text x="58.5" y="14">blue</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="158" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="114" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_46">
<rect width="158" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_4">
<rect width="114" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_46)">
<g mask="url(#anybadge_4)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#FF0000" d="M41 0h117v20H41z"/>
<path fill="url(#b)" d="M0 0h158v20H0z"/>
<path fill="#FF0000" d="M41 0h73v20H41z"/>
<path fill="url(#b)" d="M0 0h114v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<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>
<text x="78.5" y="15" fill="#010101" fill-opacity=".3">bright_red</text>
<text x="77.5" y="14">bright_red</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="185" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="130" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_47">
<rect width="185" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_5">
<rect width="130" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_47)">
<g mask="url(#anybadge_5)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#FFFF00" d="M41 0h144v20H41z"/>
<path fill="url(#b)" d="M0 0h185v20H0z"/>
<path fill="#FFFF00" d="M41 0h89v20H41z"/>
<path fill="url(#b)" d="M0 0h130v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<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>
<text x="86.5" y="15" fill="#010101" fill-opacity=".3">bright_yellow</text>
<text x="85.5" y="14">bright_yellow</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.1 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="134" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="95" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_48">
<rect width="134" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_6">
<rect width="95" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_48)">
<g mask="url(#anybadge_6)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#FF00FF" d="M41 0h93v20H41z"/>
<path fill="url(#b)" d="M0 0h134v20H0z"/>
<path fill="#FF00FF" d="M41 0h54v20H41z"/>
<path fill="url(#b)" d="M0 0h95v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="88.5" y="15" fill="#010101" fill-opacity=".3">Color.FUCHSIA</text>
<text x="87.5" y="14">Color.FUCHSIA</text>
<text x="69.0" y="15" fill="#010101" fill-opacity=".3">fuchsia</text>
<text x="68.0" y="14">fuchsia</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="118" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="78" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_49">
<rect width="118" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_7">
<rect width="78" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_49)">
<g mask="url(#anybadge_7)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#808080" d="M41 0h77v20H41z"/>
<path fill="url(#b)" d="M0 0h118v20H0z"/>
<path fill="#808080" d="M41 0h37v20H41z"/>
<path fill="url(#b)" d="M0 0h78v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="80.5" y="15" fill="#010101" fill-opacity=".3">Color.GRAY</text>
<text x="79.5" y="14">Color.GRAY</text>
<text x="60.5" y="15" fill="#010101" fill-opacity=".3">gray</text>
<text x="59.5" y="14">gray</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="125" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="85" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_50">
<rect width="125" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_8">
<rect width="85" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_50)">
<g mask="url(#anybadge_8)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#4c1" d="M41 0h84v20H41z"/>
<path fill="url(#b)" d="M0 0h125v20H0z"/>
<path fill="#4C1" d="M41 0h44v20H41z"/>
<path fill="url(#b)" d="M0 0h85v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="84.0" y="15" fill="#010101" fill-opacity=".3">Color.GREEN</text>
<text x="83.0" y="14">Color.GREEN</text>
<text x="64.0" y="15" fill="#010101" fill-opacity=".3">green</text>
<text x="63.0" y="14">green</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="161" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="112" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_51">
<rect width="161" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_9">
<rect width="112" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_51)">
<g mask="url(#anybadge_9)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#9f9f9f" d="M41 0h120v20H41z"/>
<path fill="url(#b)" d="M0 0h161v20H0z"/>
<path fill="#9F9F9F" d="M41 0h71v20H41z"/>
<path fill="url(#b)" d="M0 0h112v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<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>
<text x="77.5" y="15" fill="#010101" fill-opacity=".3">light_grey</text>
<text x="76.5" y="14">light_grey</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="116" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="76" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_52">
<rect width="116" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_10">
<rect width="76" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_52)">
<g mask="url(#anybadge_10)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#00FF00" d="M41 0h75v20H41z"/>
<path fill="url(#b)" d="M0 0h116v20H0z"/>
<path fill="#00FF00" d="M41 0h35v20H41z"/>
<path fill="url(#b)" d="M0 0h76v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="79.5" y="15" fill="#010101" fill-opacity=".3">Color.LIME</text>
<text x="78.5" y="14">Color.LIME</text>
<text x="59.5" y="15" fill="#010101" fill-opacity=".3">lime</text>
<text x="58.5" y="14">lime</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="138" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="95" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_53">
<rect width="138" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_11">
<rect width="95" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_53)">
<g mask="url(#anybadge_11)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#800000" d="M41 0h97v20H41z"/>
<path fill="url(#b)" d="M0 0h138v20H0z"/>
<path fill="#800000" d="M41 0h54v20H41z"/>
<path fill="url(#b)" d="M0 0h95v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="90.5" y="15" fill="#010101" fill-opacity=".3">Color.MAROON</text>
<text x="89.5" y="14">Color.MAROON</text>
<text x="69.0" y="15" fill="#010101" fill-opacity=".3">maroon</text>
<text x="68.0" y="14">maroon</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="115" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="79" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_54">
<rect width="115" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_12">
<rect width="79" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_54)">
<g mask="url(#anybadge_12)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#000080" d="M41 0h74v20H41z"/>
<path fill="url(#b)" d="M0 0h115v20H0z"/>
<path fill="#000080" d="M41 0h38v20H41z"/>
<path fill="url(#b)" d="M0 0h79v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="79.0" y="15" fill="#010101" fill-opacity=".3">Color.NAVY</text>
<text x="78.0" y="14">Color.NAVY</text>
<text x="61.0" y="15" fill="#010101" fill-opacity=".3">navy</text>
<text x="60.0" y="14">navy</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="123" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="80" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_55">
<rect width="123" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_13">
<rect width="80" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_55)">
<g mask="url(#anybadge_13)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#808000" d="M41 0h82v20H41z"/>
<path fill="url(#b)" d="M0 0h123v20H0z"/>
<path fill="#808000" d="M41 0h39v20H41z"/>
<path fill="url(#b)" d="M0 0h80v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="83.0" y="15" fill="#010101" fill-opacity=".3">Color.OLIVE</text>
<text x="82.0" y="14">Color.OLIVE</text>
<text x="61.5" y="15" fill="#010101" fill-opacity=".3">olive</text>
<text x="60.5" y="14">olive</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="135" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="92" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_56">
<rect width="135" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_14">
<rect width="92" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_56)">
<g mask="url(#anybadge_14)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#fe7d37" d="M41 0h94v20H41z"/>
<path fill="url(#b)" d="M0 0h135v20H0z"/>
<path fill="#FE7D37" d="M41 0h51v20H41z"/>
<path fill="url(#b)" d="M0 0h92v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="89.0" y="15" fill="#010101" fill-opacity=".3">Color.ORANGE</text>
<text x="88.0" y="14">Color.ORANGE</text>
<text x="67.5" y="15" fill="#010101" fill-opacity=".3">orange</text>
<text x="66.5" y="14">orange</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="129" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="89" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_57">
<rect width="129" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_15">
<rect width="89" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_57)">
<g mask="url(#anybadge_15)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#800080" d="M41 0h88v20H41z"/>
<path fill="url(#b)" d="M0 0h129v20H0z"/>
<path fill="#800080" d="M41 0h48v20H41z"/>
<path fill="url(#b)" d="M0 0h89v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="86.0" y="15" fill="#010101" fill-opacity=".3">Color.PURPLE</text>
<text x="85.0" y="14">Color.PURPLE</text>
<text x="66.0" y="15" fill="#010101" fill-opacity=".3">purple</text>
<text x="65.0" y="14">purple</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="108" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="71" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_58">
<rect width="108" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_16">
<rect width="71" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_58)">
<g mask="url(#anybadge_16)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#e05d44" d="M41 0h67v20H41z"/>
<path fill="url(#b)" d="M0 0h108v20H0z"/>
<path fill="#E05D44" d="M41 0h30v20H41z"/>
<path fill="url(#b)" d="M0 0h71v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="75.5" y="15" fill="#010101" fill-opacity=".3">Color.RED</text>
<text x="74.5" y="14">Color.RED</text>
<text x="57.0" y="15" fill="#010101" fill-opacity=".3">red</text>
<text x="56.0" y="14">red</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="127" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="86" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_59">
<rect width="127" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_17">
<rect width="86" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_59)">
<g mask="url(#anybadge_17)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#C0C0C0" d="M41 0h86v20H41z"/>
<path fill="url(#b)" d="M0 0h127v20H0z"/>
<path fill="#C0C0C0" d="M41 0h45v20H41z"/>
<path fill="url(#b)" d="M0 0h86v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="85.0" y="15" fill="#010101" fill-opacity=".3">Color.SILVER</text>
<text x="84.0" y="14">Color.SILVER</text>
<text x="64.5" y="15" fill="#010101" fill-opacity=".3">silver</text>
<text x="63.5" y="14">silver</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="115" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="74" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_60">
<rect width="115" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_18">
<rect width="74" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_60)">
<g mask="url(#anybadge_18)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#008080" d="M41 0h74v20H41z"/>
<path fill="url(#b)" d="M0 0h115v20H0z"/>
<path fill="#008080" d="M41 0h33v20H41z"/>
<path fill="url(#b)" d="M0 0h74v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="79.0" y="15" fill="#010101" fill-opacity=".3">Color.TEAL</text>
<text x="78.0" y="14">Color.TEAL</text>
<text x="58.5" y="15" fill="#010101" fill-opacity=".3">teal</text>
<text x="57.5" y="14">teal</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="123" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="81" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_61">
<rect width="123" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_19">
<rect width="81" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_61)">
<g mask="url(#anybadge_19)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#FFFFFF" d="M41 0h82v20H41z"/>
<path fill="url(#b)" d="M0 0h123v20H0z"/>
<path fill="#FFFFFF" d="M41 0h40v20H41z"/>
<path fill="url(#b)" d="M0 0h81v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="83.0" y="15" fill="#010101" fill-opacity=".3">Color.WHITE</text>
<text x="82.0" y="14">Color.WHITE</text>
<text x="62.0" y="15" fill="#010101" fill-opacity=".3">white</text>
<text x="61.0" y="14">white</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="135" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="87" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_62">
<rect width="135" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_20">
<rect width="87" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_62)">
<g mask="url(#anybadge_20)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#dfb317" d="M41 0h94v20H41z"/>
<path fill="url(#b)" d="M0 0h135v20H0z"/>
<path fill="#DFB317" d="M41 0h46v20H41z"/>
<path fill="url(#b)" d="M0 0h87v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="89.0" y="15" fill="#010101" fill-opacity=".3">Color.YELLOW</text>
<text x="88.0" y="14">Color.YELLOW</text>
<text x="65.0" y="15" fill="#010101" fill-opacity=".3">yellow</text>
<text x="64.0" y="14">yellow</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -1,23 +1,23 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="180" height="20">
<svg xmlns="http://www.w3.org/2000/svg" width="128" height="20">
<linearGradient id="b" x2="0" y2="100%">
<stop offset="0" stop-color="#bbb" stop-opacity=".1"/>
<stop offset="1" stop-opacity=".1"/>
</linearGradient>
<mask id="anybadge_63">
<rect width="180" height="20" rx="3" fill="#fff"/>
<mask id="anybadge_21">
<rect width="128" height="20" rx="3" fill="#fff"/>
</mask>
<g mask="url(#anybadge_63)">
<g mask="url(#anybadge_21)">
<path fill="#555" d="M0 0h41v20H0z"/>
<path fill="#a4a61d" d="M41 0h139v20H41z"/>
<path fill="url(#b)" d="M0 0h180v20H0z"/>
<path fill="#A4A61D" d="M41 0h87v20H41z"/>
<path fill="url(#b)" d="M0 0h128v20H0z"/>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<text x="21.5" y="15" fill="#010101" fill-opacity=".3">Color</text>
<text x="20.5" y="14">Color</text>
</g>
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
<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>
<text x="85.5" y="15" fill="#010101" fill-opacity=".3">yellow_green</text>
<text x="84.5" y="14">yellow_green</text>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.0 KiB

After

Width:  |  Height:  |  Size: 1.0 KiB

View File

@@ -27,7 +27,7 @@ setup(
install_requires=["packaging"],
package_data={"anybadge": ["templates/*.svg"]},
options={"bdist_wheel": {"universal": False}},
python_requires=">=3.4",
python_requires=">=3.7",
url="https://github.com/jongracecox/anybadge",
entry_points={
"console_scripts": [

View File

@@ -145,13 +145,13 @@ class TestAnybadge(TestCase):
self.assertNotEqual(badges[0].badge_width, badges[1].badge_width)
def test_multiple_badges_get_different_mask_id(self):
def test_multiple_badges_get_different_mask(self):
badges = [
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)
self.assertNotEqual(badges[0].mask_str, badges[1].mask_str)
def test_integer_str_value_is_handled_as_integer(self):
badge = Badge("integer", value="1234")