diff --git a/.gitignore b/.gitignore index 4d8e167..9bce014 100644 --- a/.gitignore +++ b/.gitignore @@ -105,3 +105,12 @@ ENV/ .DS_Store demo.svg + +# py.test +.pytest_cache + +# SVG files generated by the unittests +test_badge_*.svg + +# html coverage report +htmlcov/ diff --git a/.travis.yml b/.travis.yml index fae333d..32bbb14 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,12 +1,16 @@ +dist: xenial language: python python: - '2.7' - '3.5' - '3.6' +- '3.7' install: - pip install -U setuptools pip -r build-requirements.txt script: -- python ./test.py +- pytest --doctest-modules --cov=anybadge anybadge.py tests +before_deploy: +- sed -i "s/^version = .*/version = __version__ = \"$TRAVIS_TAG\"/" anybadge.py deploy: - provider: pypi user: jongracecox @@ -16,12 +20,4 @@ deploy: on: tags: true all_branches: true - python: '3.6' -- provider: pypi - user: jongracecox - password: - secure: "TwKVv2wGesF3zHMtSzC/whgtBfHOG03wYS8bUOeeH4x8g5wQIu9SVyrYSffYE3FxapHbMCzmx7A3IgP4Ma6v4Ik6HqJY7a5DY/na0bcuI40IyCM2J0S0Hbq4E7WXaCCe6t7C5KE7NO3QzIcZboSZBWb78mcKLB2XbuIWMPCXqayGhqh8hynQmhwQ4C5b+jpBXlLtm6+AFH7eJOSdl8iO39RU5TL6FrOjgmks/KvTO0yHaXxmBoRcVudZsv9sAGsUx/UtRA65FPViIgu/dEV8cNtz7HOtL4v9x1mkvsiHF7OJiB1KCzSdUSCI83JSjdh44jjlNx0x2SnPbbwmCR7hi53xszMLbAHqY27hK1O4ntR1Iaui8HhBx8inxwS5z271xEQ9HZ8W9veRaxXxGkzj3LKGzjYflK1UN/ZK2syy5+cF4AEUpqEuQYi2waGhMxxWRo5KA05RLXetvsJYFEHUlATq9aXjMv29yH77KzySgpZe/Emd+Hb7r/7TKDeWXRaWDtUa+lc7G5oHLn6Kmm0iM1lerFKalEO9eoZwO2m1+O47CJ5yTKw1mNsC5Dj6EhG1QeonJWPS5z32vjNvnzRm2psbInt00SE2ClPxY5ASQOdcCMkq4ELGUHVssOGlniVYILs+tiwzrDTaXcckf8lvVvx6CiXfmFY+JYK9q3HYEuE=" - distributions: sdist bdist_wheel - on: - branch: master - python: '3.6' + python: '3.7' \ No newline at end of file diff --git a/README.md b/README.md index aa82d38..67cd9aa 100644 --- a/README.md +++ b/README.md @@ -208,185 +208,218 @@ Here is the output of ``help(anybadge)``:: Help on module anybadge: NAME - anybadge - anybadge - -FILE - /home/jon/Git/anybadge/anybadge.py + anybadge - anybadge DESCRIPTION - A Python module for generating badges for your projects, with a focus on - simplicity and flexibility. + A Python module for generating badges for your projects, with a focus on + simplicity and flexibility. CLASSES - __builtin__.object - Badge - - class Badge(__builtin__.object) - | Badge class used to generate badges. - | - | Examples: - | - | Create a simple green badge: - | - | >>> badge = Badge('label', 123, default_color='green') - | - | Write a badge to file, overwriting any existing file: - | - | >>> badge = Badge('label', 123, default_color='green') - | >>> badge.write_badge('demo.svg', overwrite=True) - | - | Here are a number of examples showing thresholds, since there - | are certain situations that may not be obvious: - | - | >>> badge = Badge('pipeline', 'passing', thresholds={'passing': 'green', 'failing': 'red'}) - | >>> badge.badge_color - | 'green' - | - | 2.32 is not <2 - | 2.32 is < 4, so 2.32 yields orange - | >>> badge = Badge('pylint', 2.32, thresholds={2: 'red', - | ... 4: 'orange', - | ... 8: 'yellow', - | ... 10: 'green'}) - | >>> badge.badge_color - | 'orange' - | - | 8 is not <8 - | 8 is <4, so 8 yields orange - | >>> badge = Badge('pylint', 6, thresholds={2: 'red', - | ... 4: 'orange', - | ... 8: 'yellow', - | ... 10: 'green'}) - | >>> badge.badge_color - | 'green' - | - | 10 is not <8, but use_max_when_value_exceeds defaults to - | True, so 10 yields green - | >>> badge = Badge('pylint', 11, thresholds={2: 'red', - | ... 4: 'orange', - | ... 8: 'yellow', - | ... 10: 'green'}) - | >>> badge.badge_color - | 'green' - | - | 11 is not <10, and use_max_when_value_exceeds is set to - | False, so 11 yields the default color '#a4a61d' - | >>> badge = Badge('pylint', 11, use_max_when_value_exceeds=False, - | ... thresholds={2: 'red', 4: 'orange', 8: 'yellow', - | ... 10: 'green'}) - | >>> badge.badge_color - | '#a4a61d' - | - | Methods defined here: - | - | __init__(self, label, value, font_name='DejaVu Sans,Verdana,Geneva,sans-serif', font_size=11, num_padding_chars=0.5, template='\n{{ value }}\n \n', value_prefix='', value_suffix='', thresholds=None, default_color='#a4a61d', use_max_when_value_exceeds=True, value_format=None, text_color='#fff') - | Constructor for Badge class. - | - | get_text_width(self, text) - | Return the width of text. - | - | This implementation assumes a fixed font of: - | - | font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11" - | >>> badge = Badge('x', 1, font_name='DejaVu Sans,Verdana,Geneva,sans-serif', font_size=11) - | >>> badge.get_text_width('pylint') - | 42 - | - | write_badge(self, file_path, overwrite=False) - | Write badge to file. - | - | ---------------------------------------------------------------------- - | Static methods defined here: - | - | get_font_width(font_name, font_size) - | Return the width multiplier for a font. - | - | >>> Badge.get_font_width('DejaVu Sans,Verdana,Geneva,sans-serif', 11) - | 7 - | - | ---------------------------------------------------------------------- - | Data descriptors defined here: - | - | __dict__ - | dictionary for instance variables (if defined) - | - | __weakref__ - | list of weak references to the object (if defined) - | - | badge_color - | Find the badge color based on the thresholds. - | - | badge_color_code - | Return the color code for the badge. - | - | badge_svg_text - | The badge SVG text. - | - | badge_width - | The total width of badge. - | - | >>> badge = Badge('pylint', '5', font_name='DejaVu Sans,Verdana,Geneva,sans-serif', - | ... font_size=11) - | >>> badge.badge_width - | 91 - | - | color_split_position - | The SVG x position where the color split should occur. - | - | font_width - | Return the badge font width. - | - | label_anchor - | The SVG x position of the middle anchor for the label text. - | - | label_anchor_shadow - | The SVG x position of the label shadow anchor. - | - | label_width - | The SVG width of the label text. - | - | value_anchor - | The SVG x position of the middle anchor for the value text. - | - | value_anchor_shadow - | The SVG x position of the value shadow anchor. - | - | value_is_float - | Identify whether the value text is a float. - | - | value_is_int - | Identify whether the value text is an int. - | - | value_type - | The Python type associated with the value. - | - | value_width - | The SVG width of the value text. + builtins.object + Badge + + class Badge(builtins.object) + | Badge(label, value, font_name='DejaVu Sans,Verdana,Geneva,sans-serif', font_size=11, num_padding_chars=0.5, template='\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n {{ label }}\n {{ label }}\n \n \n {{ value }}\n {{ value }}\n \n', value_prefix='', value_suffix='', thresholds=None, default_color='#4c1', use_max_when_value_exceeds=True, value_format=None, text_color='#fff') + | + | Badge class used to generate badges. + | + | Examples: + | + | Create a simple green badge: + | + | >>> badge = Badge('label', 123, default_color='green') + | + | Write a badge to file, overwriting any existing file: + | + | >>> badge = Badge('label', 123, default_color='green') + | >>> badge.write_badge('demo.svg', overwrite=True) + | + | Here are a number of examples showing thresholds, since there + | are certain situations that may not be obvious: + | + | >>> badge = Badge('pipeline', 'passing', thresholds={'passing': 'green', 'failing': 'red'}) + | >>> badge.badge_color + | 'green' + | + | 2.32 is not <2 + | 2.32 is < 4, so 2.32 yields orange + | >>> badge = Badge('pylint', 2.32, thresholds={2: 'red', + | ... 4: 'orange', + | ... 8: 'yellow', + | ... 10: 'green'}) + | >>> badge.badge_color + | 'orange' + | + | 8 is not <8 + | 8 is <4, so 8 yields orange + | >>> badge = Badge('pylint', 8, thresholds={2: 'red', + | ... 4: 'orange', + | ... 8: 'yellow', + | ... 10: 'green'}) + | >>> badge.badge_color + | 'green' + | + | 10 is not <8, but use_max_when_value_exceeds defaults to + | True, so 10 yields green + | >>> badge = Badge('pylint', 11, thresholds={2: 'red', + | ... 4: 'orange', + | ... 8: 'yellow', + | ... 10: 'green'}) + | >>> badge.badge_color + | 'green' + | + | 11 is not <10, and use_max_when_value_exceeds is set to + | False, so 11 yields the default color '#4c1' + | >>> badge = Badge('pylint', 11, use_max_when_value_exceeds=False, + | ... thresholds={2: 'red', 4: 'orange', 8: 'yellow', + | ... 10: 'green'}) + | >>> badge.badge_color + | '#4c1' + | + | Methods defined here: + | + | __init__(self, label, value, font_name='DejaVu Sans,Verdana,Geneva,sans-serif', font_size=11, num_padding_chars=0.5, template='\n\n \n \n \n \n \n \n \n \n \n \n \n \n \n {{ label }}\n {{ label }}\n \n \n {{ value }}\n {{ value }}\n \n', value_prefix='', value_suffix='', thresholds=None, default_color='#4c1', use_max_when_value_exceeds=True, value_format=None, text_color='#fff') + | Constructor for Badge class. + | + | get_text_width(self, text) + | Return the width of text. + | + | Args: + | text(str): Text to get the pixel width of. + | + | Returns: + | int: Pixel width of the given text based on the badges selected font. + | + | This implementation assumes a fixed font of: + | + | font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11" + | >>> badge = Badge('x', 1, font_name='DejaVu Sans,Verdana,Geneva,sans-serif', font_size=11) + | >>> badge.get_text_width('pylint') + | 34 + | + | write_badge(self, file_path, overwrite=False) + | Write badge to file. + | + | ---------------------------------------------------------------------- + | Data descriptors defined here: + | + | __dict__ + | dictionary for instance variables (if defined) + | + | __weakref__ + | list of weak references to the object (if defined) + | + | badge_color + | Badge color based on the configured thresholds. + | + | Returns: str + | + | badge_color_code + | Return the color code for the badge. + | + | Returns: str + | + | badge_svg_text + | The badge SVG text. + | + | Returns: str + | + | badge_width + | The total width of badge. + | + | Returns: int + | + | Examples: + | + | >>> badge = Badge('pylint', '5') + | >>> badge.badge_width + | 103 + | + | color_split_position + | The SVG x position where the color split should occur. + | + | Returns: int + | + | font_width + | Return the width multiplier for a font. + | + | Returns: + | int: Maximum pixel width of badges selected font. + | + | Example: + | + | >>> Badge(label='x', value='1').font_width + | 10 + | + | label_anchor + | The SVG x position of the middle anchor for the label text. + | + | Returns: float + | + | label_anchor_shadow + | The SVG x position of the label shadow anchor. + | + | Returns: float + | + | label_width + | The SVG width of the label text. + | + | Returns: int + | + | value_anchor + | The SVG x position of the middle anchor for the value text. + | + | Returns: float + | + | value_anchor_shadow + | The SVG x position of the value shadow anchor. + | + | Returns: float + | + | value_is_float + | Identify whether the value text is a float. + | + | Returns: bool + | + | value_is_int + | Identify whether the value text is an int. + | + | Returns: bool + | + | value_type + | The Python type associated with the value. + | + | Returns: type + | + | value_width + | The SVG width of the value text. + | + | Returns: int FUNCTIONS - main() - Generate a badge based on command line arguments. - - parse_args() - Parse the command line arguments. + main() + Generate a badge based on command line arguments. + + parse_args() + Parse the command line arguments. DATA - BADGE_TEMPLATES = {'coverage': {'label': 'coverage', 'suffix': '%', 't... - COLORS = {'green': '#97CA00', 'lightgrey': '#9f9f9f', 'orange': '#fe7d... - DEFAULT_COLOR = '#a4a61d' - DEFAULT_FONT = 'DejaVu Sans,Verdana,Geneva,sans-serif' - DEFAULT_FONT_SIZE = 11 - DEFAULT_TEXT_COLOR = '#fff' - FONT_WIDTHS = {'DejaVu Sans,Verdana,Geneva,sans-serif': {11: 7}} - NUM_PADDING_CHARS = 0.5 - TEMPLATE_SVG = '\n>> Badge(label='x', value='1').font_width + 10 + """ + return FONT_WIDTHS[self.font_name][self.font_size] @property def color_split_position(self): - """The SVG x position where the color split should occur.""" - return self.get_text_width(' ') + self.label_width + \ - int(float(self.font_width) * float(self.num_padding_chars)) + """The SVG x position where the color split should occur. + + Returns: int + """ + return int(self.font_width + self.label_width + + float(self.font_width) * float(self.num_padding_chars)) @property def label_anchor(self): - """The SVG x position of the middle anchor for the label text.""" + """The SVG x position of the middle anchor for the label text. + + Returns: float + """ return self.color_split_position / 2 @property def value_anchor(self): - """The SVG x position of the middle anchor for the value text.""" + """The SVG x position of the middle anchor for the value text. + + Returns: float + """ return self.color_split_position + ((self.badge_width - self.color_split_position) / 2) @property def label_anchor_shadow(self): - """The SVG x position of the label shadow anchor.""" + """The SVG x position of the label shadow anchor. + + Returns: float + """ return self.label_anchor + 1 @property def value_anchor_shadow(self): - """The SVG x position of the value shadow anchor.""" + """The SVG x position of the value shadow anchor. + + Returns: float + """ return self.value_anchor + 1 @property def badge_width(self): """The total width of badge. - >>> badge = Badge('pylint', '5', font_name='DejaVu Sans,Verdana,Geneva,sans-serif', - ... font_size=11) - >>> badge.badge_width - 91 + Returns: int + + Examples: + + >>> badge = Badge('pylint', '5') + >>> badge.badge_width + 103 """ - return self.get_text_width(' ' + ' ' * int(float(self.num_padding_chars) * 2.0)) \ - + self.label_width + self.value_width + padding = int(self.font_width * (self.num_padding_chars + 3)) + return padding + self.label_width + self.value_width @property def badge_svg_text(self): - """The badge SVG text.""" + """The badge SVG text. + + Returns: str + """ # Identify whether template is a file or the actual template text if len(self.template.split('\n')) == 1: @@ -279,30 +325,29 @@ class Badge(object): .replace('{{ color split x }}', str(self.color_split_position)) \ .replace('{{ value width }}', str(self.badge_width - self.color_split_position)) - @staticmethod - def get_font_width(font_name, font_size): - """Return the width multiplier for a font. - - >>> Badge.get_font_width('DejaVu Sans,Verdana,Geneva,sans-serif', 11) - 7 - """ - return FONT_WIDTHS[font_name][font_size] - def get_text_width(self, text): """Return the width of text. + Args: + text(str): Text to get the pixel width of. + + Returns: + int: Pixel width of the given text based on the badges selected font. + This implementation assumes a fixed font of: font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11" >>> badge = Badge('x', 1, font_name='DejaVu Sans,Verdana,Geneva,sans-serif', font_size=11) >>> badge.get_text_width('pylint') - 42 + 34 """ - return len(text) * self.get_font_width(self.font_name, self.font_size) + return _get_approx_string_width(text, self.font_width) @property def badge_color(self): - """Find the badge color based on the thresholds.""" + """Badge color based on the configured thresholds. + + Returns: str""" # If no thresholds were passed then return the default color if not self.thresholds: return self.default_color @@ -331,7 +376,10 @@ class Badge(object): @property def badge_color_code(self): - """Return the color code for the badge.""" + """Return the color code for the badge. + + Returns: str + """ color = self.badge_color if color[0] == '#': return color @@ -357,6 +405,113 @@ class Badge(object): file_handle.write(self.badge_svg_text) +# Based on the following SO answer: https://stackoverflow.com/a/16008023/6252525 +def _get_approx_string_width(text, font_width, fixed_width=False): + """ + Get the approximate width of a string using a specific average font width. + + Args: + text(str): Text string to calculate width of. + font_width(int): Average width of font characters. + fixed_width(bool): Indicates that the font is fixed width. + + Returns: + int: Width of string in pixels. + + Examples: + + Call the function with a string and the maximum character width of the font you are using: + + >>> int(_get_approx_string_width('hello', 10)) + 29 + + This example shows the comparison of simplistic calculation based on a fixed width. + Given a test string and a fixed font width of 10, we can calculate the width + by multiplying the length and the font character with: + + >>> test_string = 'GOOGLE|ijkl' + >>> _get_approx_string_width(test_string, 10, fixed_width=True) + 110 + + Since some characters in the string are thinner than others we expect that the + apporximate text width will be narrower than the fixed width calculation: + + >>> _get_approx_string_width(test_string, 10) + 77 + + """ + if fixed_width: + return len(text) * font_width + + size = 0.0 + + # A dictionary containing percentages that relate to how wide + # each character will be represented in a variable width font. + # These percentages can be calculated using the ``_get_character_percentage_dict`` function. + char_width_percentages = { + "lij|' ": 40.0, + '![]fI.,:;/\\t': 50.0, + '`-(){}r"': 60.0, + '*^zcsJkvxy': 70.0, + 'aebdhnopqug#$L+<>=?_~FZT0123456789': 70.0, + 'BSPEAKVXY&UwNRCHD': 70.0, + 'QGOMm%W@': 100.0 + } + + for s in text: + percentage = 100.0 + for k in char_width_percentages.keys(): + if s in k: + percentage = char_width_percentages[k] + break + size += (percentage / 100.0) * float(font_width) + + return int(size) + +# This is a helper function that can be used to generate alternate dictionaries +# for the _get_approx_string_width function. The function is not needed for +# normal operation of this package, and since it depends on the PIL package, +# which is not included in the dependencies the function will remain commented out. +# +# def _get_character_percentage_dict(font_path, font_size): +# """Get the dictionary used to estimate variable width font text lengths. +# +# Args: +# font_path(str): Path to valid font file. +# font_size(int): Font size to use. +# +# Returns: dict +# +# This function can be used to calculate the dictionary used in the +# ``get_approx_string_width`` function. +# +# Examples: +# >>> _get_character_percentage_dict('/Library/Fonts/Verdana.ttf', 9) # doctest: +ELLIPSIS +# {"lij|' ": 40, '![]fI.,:;/\\\\t': 50, '`-(){}r"': 60, '*^zcsJkvxy': 70, ... +# """ +# from PIL import ImageFont +# +# # List of groups in size order, smallest to largest +# char_width_groups = [ +# "lij|' ", +# '![]fI.,:;/\\t', +# '`-(){}r"', +# '*^zcsJkvxy', +# 'aebdhnopqug#$L+<>=?_~FZT' + digits, +# 'BSPEAKVXY&UwNRCHD', +# 'QGOMm%W@', +# ] +# +# def get_largest_in_group(group): +# """Get the widest character from the group.""" +# return max([ImageFont.truetype(font_path, font_size).getsize(c)[0] for c in group]) +# +# largest = char_width_groups[-1] +# font_width = get_largest_in_group(largest) +# return {group: int((get_largest_in_group(group) / font_width) * 100) +# for group in char_width_groups} + + def parse_args(): """Parse the command line arguments.""" import argparse @@ -477,5 +632,6 @@ def main(): else: print(badge.badge_svg_text) + if __name__ == '__main__': main() diff --git a/build-requirements.txt b/build-requirements.txt index 1572f5f..046b26f 100644 --- a/build-requirements.txt +++ b/build-requirements.txt @@ -1,4 +1,5 @@ -mister-bump>=1.0.0 m2r restructuredtext_lint pygments +pytest +pytest-cov \ No newline at end of file diff --git a/setup.py b/setup.py index a179ce0..c250076 100644 --- a/setup.py +++ b/setup.py @@ -1,6 +1,7 @@ #!/usr/bin/python +import os +import re from setuptools import setup -from mister_bump import bump from m2r import parse_from_file import restructuredtext_lint @@ -16,16 +17,22 @@ if errors: raise ValueError('README.md contains errors: ', ', '.join([e.message for e in errors])) +# Attempt to get version number from TravisCI environment variable +version = os.environ.get('TRAVIS_TAG', default='0.0.0') + +# Remove leading 'v' +version = re.sub('^v', '', version) + setup( name='anybadge', description='Simple, flexible badge generator for project badges.', long_description=rst_readme, - version=bump(), + version=version, author='Jon Grace-Cox', author_email='jongracecox@gmail.com', py_modules=['anybadge', 'anybadge_server'], setup_requires=['setuptools', 'wheel'], - tests_require=[], + tests_require=['unittest'], install_requires=[], data_files=[], options={ diff --git a/test.py b/test.py deleted file mode 100755 index 2869a0d..0000000 --- a/test.py +++ /dev/null @@ -1,15 +0,0 @@ -#!/usr/bin/python -""" -anybadge test module. -""" - -import anybadge - -if __name__ == '__main__': - - thresholds={2: 'red', 4: 'orange', 6: 'green', 8: 'brightgreen'} - - badge = anybadge.Badge('test', '2.22', value_suffix='%', - thresholds=thresholds, text_color='#010101,#101010') - - print(badge.badge_svg_text) diff --git a/tests/__init__.py b/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/test_anybadge.py b/tests/test_anybadge.py new file mode 100644 index 0000000..9c6ce89 --- /dev/null +++ b/tests/test_anybadge.py @@ -0,0 +1,105 @@ +from unittest import TestCase +from anybadge import Badge + + +class TestAnybadge(TestCase): + """Test case class for anybadge package.""" + + 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.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.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.write_badge('test_badge_3.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', + value='89.67%', + default_color='green', + num_padding_chars=0) + + badge.write_badge('test_badge_4.svg', overwrite=True) + + self.assertLessEqual(badge.badge_width, 118) + + 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.write_badge('test_badge_5.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='1', + default_color='green', + num_padding_chars=0) + + badge.write_badge('test_badge_6.svg', overwrite=True) + + self.assertLessEqual(badge.badge_width, 81) + + 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.write_badge('test_badge_7.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' + } + + badge = Badge('test', '2.22', value_suffix='%', + thresholds=thresholds) + + badge.write_badge('test_badge_8.svg') + + def test_badge_with_text_color(self): + """Test generating a badge with alternate text_color.""" + + badge = Badge('test', '2.22', value_suffix='%', + text_color='#010101,#101010') + + badge.write_badge('test_badge_9.svg')