diff --git a/.travis.yml b/.travis.yml index 83aa2c8..3c43788 100644 --- a/.travis.yml +++ b/.travis.yml @@ -8,7 +8,7 @@ python: install: - pip install -U setuptools pip -r build-requirements.txt script: -- pytest --doctest-modules --cov=anybadge anybadge.py tests +- pytest --doctest-modules --cov=anybadge --cov-report html:htmlcov anybadge.py tests before_deploy: - sed -i "s/^version = .*/version = __version__ = \"$TRAVIS_TAG\"/" anybadge.py deploy: diff --git a/README.md b/README.md index 247570f..3822acf 100644 --- a/README.md +++ b/README.md @@ -163,10 +163,10 @@ This table was generated with the following code: print("""| Color Name | Hex Code | Example | | ---------- | -------- | ------- |""") for color, hex in sorted(anybadge.COLORS.items()): - file = 'https://cdn.rawgit.com/jongracecox/anybadge/master/examples/color_' + color + '.svg' + file = 'examples/color_' + color + '.svg' + url = 'https://cdn.rawgit.com/jongracecox/anybadge/master/' + file anybadge.Badge(label='Color', value=color, default_color=color).write_badge(file, overwrite=True) - print("| {color} | {hex} | ![]({file}) |".format(color=color, hex=hex.upper(), file=file)) - + print("| {color} | {hex} | ![]({url}) |".format(color=color, hex=hex.upper(), url=url)) ``` ### Examples diff --git a/anybadge.py b/anybadge.py index 29ef9fc..f62d3d5 100755 --- a/anybadge.py +++ b/anybadge.py @@ -5,9 +5,11 @@ anybadge A Python module for generating badges for your projects, with a focus on simplicity and flexibility. """ +import sys import os import re - +import argparse +import textwrap # Package information version = __version__ = "0.0.0" @@ -20,7 +22,7 @@ __uri__ = "https://github.com/jongracecox/anybadge" # Set some defaults DEFAULT_FONT = 'DejaVu Sans,Verdana,Geneva,sans-serif' DEFAULT_FONT_SIZE = 11 -NUM_PADDING_CHARS = 0 +NUM_PADDING_CHARS = 0.5 DEFAULT_COLOR = '#4c1' DEFAULT_TEXT_COLOR = '#fff' MASK_ID_PREFIX = 'anybadge_' @@ -29,8 +31,13 @@ MASK_ID_PREFIX = 'anybadge_' # supported fonts and font sizes. FONT_WIDTHS = { 'DejaVu Sans,Verdana,Geneva,sans-serif': { - 11: 10 - } + 10: 9, + 11: 10, + 12: 11, + }, + 'Arial, Helvetica, sans-serif': { + 11: 8, + }, } # Create a dictionary of colors to make selections @@ -111,6 +118,10 @@ class Badge(object): font_size(int, optional): Font size. num_padding_chars(float, optional): Number of padding characters to use to give extra space around text. + num_label_padding_chars(float, optional): Number of padding characters to use to give extra + space around label text. + num_value_padding_chars(float, optional): Number of padding characters to use to give extra + space around value text. template(str, optional): String containing the SVG template. This should be valid SVG file content with place holders for variables to be populated during rendering. value_prefix(str, optional): Prefix to be placed before value. @@ -178,18 +189,26 @@ class Badge(object): """ def __init__(self, label, value, font_name=None, font_size=None, - num_padding_chars=None, template=None, + num_padding_chars=None, num_label_padding_chars=None, + num_value_padding_chars=None, template=None, value_prefix='', value_suffix='', thresholds=None, default_color=None, use_max_when_value_exceeds=True, value_format=None, text_color=None): """Constructor for Badge class.""" - # Set defaults if values were not passed if not font_name: font_name = DEFAULT_FONT if not font_size: font_size = DEFAULT_FONT_SIZE - if num_padding_chars is None: - num_padding_chars = NUM_PADDING_CHARS + if num_label_padding_chars is None: + if num_padding_chars is None: + num_label_padding_chars = NUM_PADDING_CHARS + else: + num_label_padding_chars = num_padding_chars + if num_value_padding_chars is None: + if num_padding_chars is None: + num_value_padding_chars = NUM_PADDING_CHARS + else: + num_value_padding_chars = num_padding_chars if not template: template = TEMPLATE_SVG if not default_color: @@ -207,9 +226,13 @@ class Badge(object): self.value_prefix = value_prefix self.value_suffix = value_suffix self.value_text = value_prefix + value_text + value_suffix + + if font_name not in FONT_WIDTHS: + raise ValueError('Font name "%s" not found. Available fonts: %s' % (font_name, ', '.join(FONT_WIDTHS.keys()))) self.font_name = font_name self.font_size = font_size - self.num_padding_chars = num_padding_chars + self.num_label_padding_chars = num_label_padding_chars + self.num_value_padding_chars = num_value_padding_chars self.template = template self.thresholds = thresholds self.default_color = default_color @@ -244,14 +267,34 @@ class Badge(object): >>> repr(badge) "Badge('example', '123.456', value_suffix='TB', text_color='#111111')" + >>> badge = Badge('example', '123', num_padding_chars=5) + >>> repr(badge) + "Badge('example', '123', num_padding_chars=5)" + + >>> badge = Badge('example', '123', num_label_padding_chars=5) + >>> repr(badge) + "Badge('example', '123', num_label_padding_chars=5)" + + >>> badge = Badge('example', '123', num_label_padding_chars=5, num_value_padding_chars=6, + ... template='template.svg', value_prefix='$', thresholds={10: 'green', 30: 'red'}, + ... default_color='red', use_max_when_value_exceeds=False, value_format="%s m/s") + >>> repr(badge) + "Badge('example', '123', num_label_padding_chars=5, num_value_padding_chars=6, template='template.svg', value_prefix='$', thresholds={10: 'green', 30: 'red'}, default_color='red', use_max_when_value_exceeds=False, value_format='%s m/s')" + """ optional_args = "" if self.font_name != DEFAULT_FONT: optional_args += ", font_name=%s" % repr(self.font_name) if self.font_size != DEFAULT_FONT_SIZE: optional_args += ", font_size=%s" % repr(self.font_size) - if self.num_padding_chars != NUM_PADDING_CHARS: - optional_args += ", num_padding_chars=%s" % repr(self.num_padding_chars) + if self.num_label_padding_chars == self.num_value_padding_chars: + if self.num_label_padding_chars != NUM_PADDING_CHARS: + optional_args += ", num_padding_chars=%s" % repr(self.num_label_padding_chars) + else: + if self.num_label_padding_chars != NUM_PADDING_CHARS: + optional_args += ", num_label_padding_chars=%s" % repr(self.num_label_padding_chars) + if self.num_value_padding_chars != NUM_PADDING_CHARS: + optional_args += ", num_value_padding_chars=%s" % repr(self.num_value_padding_chars) if self.template != TEMPLATE_SVG: optional_args += ", template=%s" % repr(self.template) if self.value_prefix != '': @@ -351,7 +394,7 @@ class Badge(object): Returns: int """ - return int(self.get_text_width(self.label) + (2.0 * self.num_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): @@ -359,7 +402,7 @@ class Badge(object): Returns: int """ - return int(self.get_text_width(str(self.value_text)) + (self.num_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 font_width(self): @@ -381,8 +424,7 @@ class Badge(object): Returns: int """ - return int(self.font_width + self.label_width + - float(self.font_width) * float(self.num_padding_chars)) + return self.badge_width - self.value_width @property def label_anchor(self): @@ -426,11 +468,9 @@ class Badge(object): >>> badge = Badge('pylint', '5') >>> badge.badge_width - 53 + 61 """ - padding_char_width = self.get_text_width(' ') - padding = int(padding_char_width * (self.num_padding_chars + 3)) - return padding + self.label_width + self.value_width + return self.label_width + self.value_width @property def badge_svg_text(self): @@ -459,7 +499,7 @@ class Badge(object): .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.badge_width - self.color_split_position))\ + .replace('{{ value width }}', str(self.value_width))\ .replace('{{ mask id }}', self.mask_id) def __str__(self): @@ -531,18 +571,24 @@ class Badge(object): """Return the color code for the badge. Returns: str + + Raises: ValueError when an invalid badge color is set. """ color = self.badge_color if color[0] == '#': return color - return COLORS[color] + + try: + return COLORS[color] + except KeyError: + raise ValueError('Invalid color code "%s". Valid color codes are: %s', (color, ", ".join(COLORS.keys()))) def write_badge(self, file_path, overwrite=False): """Write badge to file.""" # Validate path (part 1) if file_path.endswith('/'): - raise Exception('File location may not be a directory.') + raise ValueError('File location may not be a directory.') # Get absolute filepath path = os.path.abspath(file_path) @@ -551,7 +597,7 @@ class Badge(object): # Validate path (part 2) if not overwrite and os.path.exists(path): - raise Exception('File "{}" already exists.'.format(path)) + raise RuntimeError('File "{}" already exists.'.format(path)) with open(path, mode='w') as file_handle: file_handle.write(self.badge_svg_text) @@ -664,10 +710,8 @@ def _get_approx_string_width(text, font_width, fixed_width=False): # for group in char_width_groups} -def parse_args(): +def parse_args(args): """Parse the command line arguments.""" - import argparse - import textwrap parser = argparse.ArgumentParser(formatter_class=argparse.RawDescriptionHelpFormatter, description=textwrap.dedent('''\ Command line utility to generate .svg badges. @@ -741,13 +785,13 @@ examples: parser.add_argument('args', nargs=argparse.REMAINDER, help='Pairs of =. ' '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() + return parser.parse_args(args) -def main(): +def main(args): """Generate a badge based on command line arguments.""" # Parse command line arguments - args = parse_args() + args = parse_args(args) label = args.label threshold_text = args.args @@ -786,4 +830,4 @@ def main(): if __name__ == '__main__': - main() + main(sys.argv[1:]) diff --git a/build_examples.py b/build_examples.py new file mode 100644 index 0000000..4ffbaab --- /dev/null +++ b/build_examples.py @@ -0,0 +1,15 @@ +import anybadge + +if __name__ == '__main__': + + print("""| Color Name | Hex Code | Example | + | ---------- | -------- | ------- |""") + for color, hex in sorted(anybadge.COLORS.items()): + + file = 'examples/color_' + color + '.svg' + + url = 'https://cdn.rawgit.com/jongracecox/anybadge/master/' + file + + anybadge.Badge(label='Color', value=color, default_color=color).write_badge(file, overwrite=True) + + print("| {color} | {hex} | ![]({url}) |".format(color=color, hex=hex.upper(), url=url)) diff --git a/examples/color_aqua.svg b/examples/color_aqua.svg index 9293cd7..8f94e9d 100644 --- a/examples/color_aqua.svg +++ b/examples/color_aqua.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - aqua - aqua + aqua + aqua \ No newline at end of file diff --git a/examples/color_black.svg b/examples/color_black.svg index 21d92e6..50b40e1 100644 --- a/examples/color_black.svg +++ b/examples/color_black.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - black - black + black + black \ No newline at end of file diff --git a/examples/color_blue.svg b/examples/color_blue.svg index 8a7e734..2fb3b62 100644 --- a/examples/color_blue.svg +++ b/examples/color_blue.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - blue - blue + blue + blue \ No newline at end of file diff --git a/examples/color_brightred.svg b/examples/color_brightred.svg index 0a34830..7e5e873 100644 --- a/examples/color_brightred.svg +++ b/examples/color_brightred.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - brightred - brightred + brightred + brightred \ No newline at end of file diff --git a/examples/color_brightyellow.svg b/examples/color_brightyellow.svg index a3508c5..d0dd1ba 100644 --- a/examples/color_brightyellow.svg +++ b/examples/color_brightyellow.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - brightyellow - brightyellow + brightyellow + brightyellow \ No newline at end of file diff --git a/examples/color_fuchsia.svg b/examples/color_fuchsia.svg index cc5e346..4e0d9c7 100644 --- a/examples/color_fuchsia.svg +++ b/examples/color_fuchsia.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - fuchsia - fuchsia + fuchsia + fuchsia \ No newline at end of file diff --git a/examples/color_gray.svg b/examples/color_gray.svg index 5e309a1..e99fe36 100644 --- a/examples/color_gray.svg +++ b/examples/color_gray.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - gray - gray + gray + gray \ No newline at end of file diff --git a/examples/color_green.svg b/examples/color_green.svg index fd379ae..b99a269 100644 --- a/examples/color_green.svg +++ b/examples/color_green.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - green - green + green + green \ No newline at end of file diff --git a/examples/color_lightgrey.svg b/examples/color_lightgrey.svg index 3da03cd..74e1abc 100644 --- a/examples/color_lightgrey.svg +++ b/examples/color_lightgrey.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - lightgrey - lightgrey + lightgrey + lightgrey \ No newline at end of file diff --git a/examples/color_lime.svg b/examples/color_lime.svg index 959b7b9..167150c 100644 --- a/examples/color_lime.svg +++ b/examples/color_lime.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - lime - lime + lime + lime \ No newline at end of file diff --git a/examples/color_maroon.svg b/examples/color_maroon.svg index 73cd8c9..cb96180 100644 --- a/examples/color_maroon.svg +++ b/examples/color_maroon.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - maroon - maroon + maroon + maroon \ No newline at end of file diff --git a/examples/color_navy.svg b/examples/color_navy.svg index 1751f54..7a16fda 100644 --- a/examples/color_navy.svg +++ b/examples/color_navy.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - navy - navy + navy + navy \ No newline at end of file diff --git a/examples/color_olive.svg b/examples/color_olive.svg index 4b0c810..e0e0c64 100644 --- a/examples/color_olive.svg +++ b/examples/color_olive.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - olive - olive + olive + olive \ No newline at end of file diff --git a/examples/color_orange.svg b/examples/color_orange.svg index 17015c4..fc43cf7 100644 --- a/examples/color_orange.svg +++ b/examples/color_orange.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - orange - orange + orange + orange \ No newline at end of file diff --git a/examples/color_purple.svg b/examples/color_purple.svg index a1f98c8..c02bb54 100644 --- a/examples/color_purple.svg +++ b/examples/color_purple.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - purple - purple + purple + purple \ No newline at end of file diff --git a/examples/color_red.svg b/examples/color_red.svg index 30b2b32..570aa56 100644 --- a/examples/color_red.svg +++ b/examples/color_red.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - red - red + red + red \ No newline at end of file diff --git a/examples/color_silver.svg b/examples/color_silver.svg index e25bf7d..bdffeea 100644 --- a/examples/color_silver.svg +++ b/examples/color_silver.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - silver - silver + silver + silver \ No newline at end of file diff --git a/examples/color_teal.svg b/examples/color_teal.svg index 095ebed..6b81930 100644 --- a/examples/color_teal.svg +++ b/examples/color_teal.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - teal - teal + teal + teal \ No newline at end of file diff --git a/examples/color_white.svg b/examples/color_white.svg index 6a79aef..3c64231 100644 --- a/examples/color_white.svg +++ b/examples/color_white.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - white - white + white + white \ No newline at end of file diff --git a/examples/color_yellow.svg b/examples/color_yellow.svg index 899c2c5..a0a248a 100644 --- a/examples/color_yellow.svg +++ b/examples/color_yellow.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - yellow - yellow + yellow + yellow \ No newline at end of file diff --git a/examples/color_yellowgreen.svg b/examples/color_yellowgreen.svg index f60ce56..266f20a 100644 --- a/examples/color_yellowgreen.svg +++ b/examples/color_yellowgreen.svg @@ -1,23 +1,23 @@ - + - + - - + + - Color - Color + Color + Color - yellowgreen - yellowgreen + yellowgreen + yellowgreen \ No newline at end of file diff --git a/measurements.png b/measurements.png new file mode 100644 index 0000000..b74aea2 Binary files /dev/null and b/measurements.png differ diff --git a/tests/template.svg b/tests/template.svg new file mode 100644 index 0000000..e81e92a --- /dev/null +++ b/tests/template.svg @@ -0,0 +1,23 @@ + + + + + + + + + + + + + + + + {{ label }} + {{ label }} + + + {{ value }} + {{ value }} + + \ No newline at end of file diff --git a/tests/test_anybadge.py b/tests/test_anybadge.py index 82b3ec0..d4bb4f6 100644 --- a/tests/test_anybadge.py +++ b/tests/test_anybadge.py @@ -1,10 +1,28 @@ from unittest import TestCase -from anybadge import Badge +from anybadge import Badge, parse_args, main class TestAnybadge(TestCase): """Test case class for anybadge package.""" + 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) + + 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') + + 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) + + 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.""" @@ -35,21 +53,21 @@ class TestAnybadge(TestCase): value='89.67%', default_color='green') - badge.write_badge('test_badge_3.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', + badge = Badge(label='medium no padding', value='89.67%', default_color='green', num_padding_chars=0) - badge.write_badge('test_badge_4.svg', overwrite=True) + badge.write_badge('test_badge_medium_no_padding.svg', overwrite=True) - self.assertLessEqual(badge.badge_width, 118) + 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.""" @@ -58,21 +76,21 @@ class TestAnybadge(TestCase): value='1', default_color='green') - badge.write_badge('test_badge_5.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', + badge = Badge(label='short value no padding', value='1', default_color='green', num_padding_chars=0) - badge.write_badge('test_badge_6.svg', overwrite=True) + badge.write_badge('test_badge_short_no_padding.svg', overwrite=True) - self.assertLessEqual(badge.badge_width, 81) + 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.""" @@ -81,7 +99,19 @@ class TestAnybadge(TestCase): value='1', default_color='green') - badge.write_badge('test_badge_7.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.write_badge('test_badge_tiny_text_value_no_padding.svg', overwrite=True) self.assertLessEqual(badge.badge_width, 76) @@ -91,58 +121,169 @@ class TestAnybadge(TestCase): 2: 'red', 4: 'orange', 6: 'green', 8: 'brightgreen' } - badge = Badge('test', '2.22', value_suffix='%', + badge = Badge('thresholds', '2.22', value_suffix='%', thresholds=thresholds) - badge.write_badge('test_badge_8.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('test', '2.22', value_suffix='%', + badge = Badge('text color', '2.22', value_suffix='%', text_color='#010101,#101010') - badge.write_badge('test_badge_9.svg', overwrite=True) + badge.write_badge('test_badge_text_color.svg', overwrite=True) def test_multiple_badges_in_one_session(self): badges = [ - Badge('something', value='100', value_suffix='%', num_padding_chars=0), - Badge('coverage', 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('something', value='100', value_suffix='%', num_padding_chars=0), - Badge('coverage', 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_value_is_handled_as_integer(self): - badge = Badge('test', value='1234') + def test_integer_str_value_is_handled_as_integer(self): + 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) + + def test_integer_int_value_is_handled_as_integer(self): + 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) + + def test_float_str_value_is_handled_as_float(self): + 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) def test_float_value_is_handled_as_float(self): - badge = Badge('test', 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) def test_float_value_with_zero_decimal(self): - badge = Badge('test', 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_10.svg', overwrite=True) + badge.write_badge('test_badge_float_zeros.svg', overwrite=True) def test_float_value_with_non_zero_decimal(self): - badge = Badge('test', 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_11.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.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.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") + + 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) + + badge_repr = repr(badge) + self.assertTrue("font_name='Arial, Helvetica, sans-serif'" in badge_repr) + + def test_invalid_font_name(self): + font = 'Invalid font' + with self.assertRaises(ValueError): + _ = 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) + + def test_font_size_repr(self): + 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_svg_text + + def test_repr_svg(self): + 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.assertTrue('orange', badge.badge_color) + + def test_invalid_color(self): + with self.assertRaises(ValueError): + badge = Badge('label', value='fred', default_color='floberry') + _ = badge.badge_color_code + + def test_invalid_write_path(self): + badge = Badge('label', 'value') + with self.assertRaisesRegexp(ValueError, r'File location may not be a directory\.'): + badge.write_badge('tests/') + + with self.assertRaisesRegexp(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) + + def test_main_print(self): + main(['--label', 'label', '--value', 'value']) + + def test_main_write_to_file(self): + 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']) + + def test_named_threshold(self): + main([ + '--value', 'value', + '--file', 'test_badge_main_named_threshold.svg', + '--overwrite', + 'coverage']) + + def test_main_missing_value(self): + with self.assertRaisesRegexp(ValueError, r'Label has not been set\. Please use --label argument\.'): + main(['--value', '123', '--file', 'test_badge_main.svg', '--overwrite'])