Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add --name option to change badge left side text #25

Merged
merged 11 commits into from
Jun 29, 2022
Merged
2 changes: 1 addition & 1 deletion ci_tools/flake8-requirements.txt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
setuptools_scm>=3,<4
flake8>=3.6,<4
flake8-html>=0.4,<1
flake8-html>=0.4,<=0.4.1
smarie marked this conversation as resolved.
Show resolved Hide resolved
flake8-bandit>=2.1.1,<3
flake8-bugbear>=20.1.0,<21.0.0
flake8-docstrings>=1.5,<2
Expand Down
6 changes: 6 additions & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ By default it assumes that

- `-` can be used to denote `<stdout>`: e.g. `genbadge tests -o - > badge.svg`.

- the badge name (left-hand side text) is **tests**. You can change it with the `-n/--name` flag or clear it with `-n ""` (but keep the empty space). Alternatively if you want to completely remove the left-hand side of the badge you can use `--noname`.

- the badge should be generated using `shields.io` (requires an internet connection). If you prefer you can use `-l/--local` to use the included SVG file template (less mature but seems to work)

In addition to generating the badge, executing the command will also display some details about the parsed file is you use the verbose `-v` flag:
Expand Down Expand Up @@ -204,6 +206,8 @@ By default it assumes that

- `-` can be used to denote `<stdout>`: e.g. `genbadge coverage -o - > badge.svg`.

- the badge name (left-hand side text) is **coverage**. You can change it with the `-n/--name` flag or clear it with `-n ""` (but keep the empty space). Alternatively if you want to completely remove the left-hand side of the badge you can use `--noname`.

- the badge should be generated using `shields.io` (requires an internet connection). If you prefer you can use `-l/--local` to use the included SVG file template (less mature but seems to work)

In addition to generating the badge, executing the command will also display some details about the parsed file is you use the verbose `-v` flag:
Expand Down Expand Up @@ -281,6 +285,8 @@ By default it assumes that

- `-` can be used to denote `<stdout>`: e.g. `genbadge flake8 -o - > badge.svg`.

- the badge name (left-hand side text) is **flake8**. You can change it with the `-n/--name` flag or clear it with `-n ""` (but keep the empty space). Alternatively if you want to completely remove the left-hand side of the badge you can use `--noname`.

- the badge should be generated using `shields.io` (requires an internet connection). If you prefer you can use `-l/--local` to use the included SVG file template (less mature but seems to work)

In addition to generating the badge, executing the command will also display some details about the parsed file is you use the verbose `-v` flag:
Expand Down
77 changes: 71 additions & 6 deletions genbadge/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@
OUTFILE_BADGE_HELP = ("An alternate SVG badge file to write to. '-' is supported and means <stdout>. Note that in this "
"case no other message will be printed to <stdout>. In particular the verbose flag will have no "
"effect.")
NAME_HELP = ("An alternate SVG badge text name to display on the left-hand side of the badge.")
WITH_NAME_HELP = ("Indicates if a badge should be generated with or without the left-hand side of the badge.")
SHIELDS_HELP = ("Indicates if badges should be generated using the shields.io HTTP API (default) or the local SVG file "
"template included.")
VERBOSE_HELP = ("Use this flag to print details to stdout during the badge generation process. Note that this flag has "
Expand All @@ -49,16 +51,20 @@ def genbadge():
short_help="Generate a badge for the test results (e.g. from a junit.xml).")
@click.option('-i', '--input-file', type=click.File('rt'), help=INFILE_HELP_TMP % "test results XML")
@click.option('-o', '--output-file', type=click.File('wt'), help=OUTFILE_BADGE_HELP)
@click.option('-n', '--name', type=str, default="tests", help=NAME_HELP)
@click.option('-t', '--threshold', type=float,
help="An optional success percentage threshold to use. The command will fail with exit code 1 if the"
"actual success percentage is strictly less than the provided value.")
@click.option('--withname/--noname', type=bool, default=True, help=WITH_NAME_HELP)
@click.option('-w/-l', '--webshields/--local', type=bool, default=True, help=SHIELDS_HELP)
@click.option('-v', '--verbose', type=bool, default=False, is_flag=True, help=VERBOSE_HELP)
@click.option('-s', '--silent', type=bool, default=False, is_flag=True, help=SILENT_HELP)
def gen_tests_badge(
input_file=None,
output_file=None,
name=None,
threshold=None,
withname=None,
webshields=None,
verbose=None,
silent=None
Expand All @@ -72,6 +78,11 @@ def gen_tests_badge(
the output file is `./tests-badge.svg`. You can change these settings with
the `-i/--input_file` and `-o/--output-file` options.

By default the badge will have the name "tests" as the left-hand side text.
You can change these settings with the `-n/--name` option. The left-hand side
text can be left blank with `-n ""` or have the left-hand side of the badge
completely removed by passing `--noname`.

You can use the verbose flag `-v/--verbose` to display information on the
input file contents, for verification.

Expand Down Expand Up @@ -117,10 +128,22 @@ def gen_tests_badge(
"Success percentage %s%% is strictly lower than required threshold %s%%"
% (float(test_stats.success_percentage), threshold)
)

# Set badge name
clear_left_txt = False
if not withname:
name = "" # removes left side of badge
elif not name.strip():
name = "###" # blank text to replace
clear_left_txt = True # keep left side of badge but remove text

# Generate the badge
badge = get_tests_badge(test_stats)
badge.write_to(output_file if is_stdout else output_file_path, use_shields=webshields)
badge = get_tests_badge(test_stats, name)
badge.write_to(
output_file if is_stdout else output_file_path,
use_shields=webshields,
clear_left_txt=clear_left_txt
)

if not silent and not is_stdout:
click.echo("SUCCESS - Tests badge created: %r" % str(output_file_path))
Expand All @@ -130,12 +153,16 @@ def gen_tests_badge(
short_help="Generate a badge for the coverage results (e.g. from a coverage.xml).")
@click.option('-i', '--input-file', type=click.File('rt'), help=INFILE_HELP_TMP % "coverage results XML")
@click.option('-o', '--output-file', type=click.File('wt'), help=OUTFILE_BADGE_HELP)
@click.option('-n', '--name', type=str, default="coverage", help=NAME_HELP)
@click.option('--withname/--noname', type=bool, default=True, help=WITH_NAME_HELP)
@click.option('-w/-l', '--webshields/--local', type=bool, default=True, help=SHIELDS_HELP)
@click.option('-v', '--verbose', type=bool, default=False, is_flag=True, help=VERBOSE_HELP)
@click.option('-s', '--silent', type=bool, default=False, is_flag=True, help=SILENT_HELP)
def gen_coverage_badge(
input_file=None,
output_file=None,
name=None,
withname=None,
webshields=None,
verbose=None,
silent=None
Expand All @@ -148,6 +175,11 @@ def gen_coverage_badge(
By default the input file is the relative `./reports/coverage/coverage.xml`
and the output file is `./coverage-badge.svg`. You can change these settings
with the `-i/--input_file` and `-o/--output-file` options.

By default the badge will have the name "coverage" as the left-hand side text.
You can change these settings with the `-n/--name` option. The left-hand side
text can be left blank with `-n ""` or have the left-hand side of the badge
completely removed by passing `--noname`.

You can use the verbose flag `-v/--verbose` to display information on the
input file contents, for verification.
Expand Down Expand Up @@ -179,9 +211,21 @@ def gen_coverage_badge(
bcp=cov_stats.branch_coverage, bc=cov_stats.branches_covered, bv=cov_stats.branches_valid,
lcp=cov_stats.line_coverage, lc=cov_stats.lines_covered, lv=cov_stats.lines_valid))

# Set badge name
clear_left_txt = False
if not withname:
name = "" # removes left side of badge
elif not name.strip():
name = "###" # blank text to replace
clear_left_txt = True # keep left side of badge but remove text

# Generate the badge
badge = get_coverage_badge(cov_stats)
badge.write_to(output_file if is_stdout else output_file_path, use_shields=webshields)
badge = get_coverage_badge(cov_stats, name)
badge.write_to(
output_file if is_stdout else output_file_path,
use_shields=webshields,
clear_left_txt=clear_left_txt
)

if not silent and not is_stdout:
click.echo("SUCCESS - Coverage badge created: %r" % str(output_file_path))
Expand All @@ -191,12 +235,16 @@ def gen_coverage_badge(
short_help="Generate a badge for the flake8 results (e.g. from a flake8stats.txt file).")
@click.option('-i', '--input-file', type=click.File('rt'), help=INFILE_HELP_TMP % "flake8 results TXT")
@click.option('-o', '--output-file', type=click.File('wt'), help=OUTFILE_BADGE_HELP)
@click.option('-n', '--name', type=str, default="flake8", help=NAME_HELP)
@click.option('--withname/--noname', type=bool, default=True, help=WITH_NAME_HELP)
@click.option('-w/-l', '--webshields/--local', type=bool, default=True, help=SHIELDS_HELP)
@click.option('-v', '--verbose', type=bool, default=False, is_flag=True, help=VERBOSE_HELP)
@click.option('-s', '--silent', type=bool, default=False, is_flag=True, help=SILENT_HELP)
def gen_flake8_badge(
input_file=None,
output_file=None,
name=None,
withname=None,
webshields=None,
verbose=None,
silent=None
Expand All @@ -210,6 +258,11 @@ def gen_flake8_badge(
and the output file is `./flake8-badge.svg`. You can change these settings
with the `-i/--input_file` and `-o/--output-file` options.

By default the badge will have the name "flake8" as the left-hand side text.
You can change these settings with the `-n/--name` option. The left-hand side
text can be left blank with `-n ""` or have the left-hand side of the badge
completely removed by passing `--noname`.

You can use the verbose flag `-v/--verbose` to display information on the
input file contents, for verification.

Expand All @@ -235,9 +288,21 @@ def gen_flake8_badge(
- Total (%s) = Critical (%s) + Warning (%s) + Info (%s)
""" % (input_file_path, flake8_stats.nb_total, flake8_stats.nb_critical, flake8_stats.nb_warning, flake8_stats.nb_info))

# Set badge name
clear_left_txt = False
if not withname:
name = "" # removes left side of badge
elif not name.strip():
name = "###" # blank text to replace
clear_left_txt = True # keep left side of badge but remove text

# Generate the badge
badge = get_flake8_badge(flake8_stats)
badge.write_to(output_file if is_stdout else output_file_path, use_shields=webshields)
badge = get_flake8_badge(flake8_stats, name)
badge.write_to(
output_file if is_stdout else output_file_path,
use_shields=webshields,
clear_left_txt=clear_left_txt
)

if not silent and not is_stdout:
click.echo("SUCCESS - Flake8 badge created: %r" % str(output_file_path))
Expand Down
27 changes: 27 additions & 0 deletions genbadge/tests/test_readme_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,11 @@ def __str__(self):
output file is `./tests-badge.svg`. You can change these settings with the
`-i/--input_file` and `-o/--output-file` options.

By default the badge will have the name "tests" as the left-hand side text.
You can change these settings with the `-n/--name` option. The left-hand side
text can be left blank with `-n ""` or have the left-hand side of the badge
completely removed by passing `--noname`.

You can use the verbose flag `-v/--verbose` to display information on the
input file contents, for verification.

Expand All @@ -82,10 +87,14 @@ def __str__(self):
this case no other message will be printed to
<stdout>. In particular the verbose flag will
have no effect.
-n, --name TEXT An alternate SVG badge text name to display on
the left-hand side of the badge.
-t, --threshold FLOAT An optional success percentage threshold to
use. The command will fail with exit code 1 if
theactual success percentage is strictly less
than the provided value.
--withname / --noname Indicates if a badge should be generated with
or without the left-hand side of the badge.
-w, --webshields / -l, --local Indicates if badges should be generated using
the shields.io HTTP API (default) or the local
SVG file template included.
Expand Down Expand Up @@ -125,6 +134,11 @@ def __str__(self):
and the output file is `./coverage-badge.svg`. You can change these settings
with the `-i/--input_file` and `-o/--output-file` options.

By default the badge will have the name "coverage" as the left-hand side text.
You can change these settings with the `-n/--name` option. The left-hand side
text can be left blank with `-n ""` or have the left-hand side of the badge
completely removed by passing `--noname`.

You can use the verbose flag `-v/--verbose` to display information on the
input file contents, for verification.

Expand All @@ -144,6 +158,10 @@ def __str__(self):
this case no other message will be printed to
<stdout>. In particular the verbose flag will
have no effect.
-n, --name TEXT An alternate SVG badge text name to display on
the left-hand side of the badge.
--withname / --noname Indicates if a badge should be generated with
or without the left-hand side of the badge.
-w, --webshields / -l, --local Indicates if badges should be generated using
the shields.io HTTP API (default) or the local
SVG file template included.
Expand Down Expand Up @@ -181,6 +199,11 @@ def __str__(self):
and the output file is `./flake8-badge.svg`. You can change these settings
with the `-i/--input_file` and `-o/--output-file` options.

By default the badge will have the name "flake8" as the left-hand side text.
You can change these settings with the `-n/--name` option. The left-hand side
text can be left blank with `-n ""` or have the left-hand side of the badge
completely removed by passing `--noname`.

You can use the verbose flag `-v/--verbose` to display information on the
input file contents, for verification.

Expand All @@ -198,6 +221,10 @@ def __str__(self):
this case no other message will be printed to
<stdout>. In particular the verbose flag will
have no effect.
-n, --name TEXT An alternate SVG badge text name to display on
the left-hand side of the badge.
--withname / --noname Indicates if a badge should be generated with
or without the left-hand side of the badge.
-w, --webshields / -l, --local Indicates if badges should be generated using
the shields.io HTTP API (default) or the local
SVG file template included.
Expand Down
18 changes: 14 additions & 4 deletions genbadge/utils_badge.py
Original file line number Diff line number Diff line change
Expand Up @@ -61,33 +61,43 @@ def as_svg(self,
else:
# download from requests
import requests
url = 'https://img.shields.io/badge/%s-%s-%s.svg' % (self.left_txt, self.right_txt, self.color)
# url encode test
safe_left_txt = requests.utils.quote(self.left_txt, safe='')
safe_right_txt = requests.utils.quote(self.right_txt, safe='')
safe_color_txt = requests.utils.quote(self.color, safe='')
url = 'https://img.shields.io/badge/%s-%s-%s.svg' % (safe_left_txt, safe_right_txt, safe_color_txt)
response = requests.get(url, stream=True)
return response.text

def write_to(self,
path_or_stream, # type: Union[TextIO, str, Path]
use_shields=False # type: bool
use_shields=False, # type: bool
clear_left_txt=False # type: bool
):
"""Write the SVG representation of this badge to the given file

:param path_or_stream:
:param use_shields:
:param clear_left_txt:
:return:
"""
# convert to a Path
if isinstance(path_or_stream, str):
path_or_stream = Path(path_or_stream)

svg = self.as_svg(use_shields=use_shields)
if clear_left_txt:
svg = svg.replace(">" + self.left_txt + "<", "><")
Comment on lines +88 to +90
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a little messy. In the case where we keep the left side of the badge but have no text it would be great to pass a tab character. However shields escapes label input so this doesn't work well. Instead we're looking for a strict match of the left txt inside html tags and replacing it with nothing afterwards. A placeholder ### is used to create the svg space (so removing text doesn't remove the left side) in this case. Thoughts on improving this welcome.


# create parent dirs if needed
if isinstance(path_or_stream, Path):
path_or_stream.parent.mkdir(parents=True, exist_ok=True)

# finally write to
with open(str(path_or_stream), mode="wb") as f:
f.write(self.as_svg(use_shields=use_shields).encode("utf-8"))
f.write(svg.encode("utf-8"))
else:
path_or_stream.write(self.as_svg(use_shields=use_shields))
path_or_stream.write(svg)


def get_svg_badge(
Expand Down
5 changes: 3 additions & 2 deletions genbadge/utils_coverage.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,8 @@ def get_color(


def get_coverage_badge(
cov_stats # type: CoverageStats
cov_stats, # type: CoverageStats
left_txt= "coverage" # type: str
):
# type: (...) -> Badge
"""Return the badge from coverage results """
Expand All @@ -129,7 +130,7 @@ def get_coverage_badge(

right_txt = "%.2f%%" % (cov_stats.total_coverage,)

return Badge(left_txt="coverage", right_txt=right_txt, color=color)
return Badge(left_txt=left_txt, right_txt=right_txt, color=color)


def parse_cov(source):
Expand Down
5 changes: 3 additions & 2 deletions genbadge/utils_flake8.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,8 @@ def get_color(


def get_flake8_badge(
flake8_stats # type: Flake8Stats
flake8_stats, # type: Flake8Stats
left_txt = "flake8" # type: str
):
# type: (...) -> Badge
"""Return the badge from coverage results """
Expand All @@ -85,7 +86,7 @@ def get_flake8_badge(

right_txt = "%s C, %s W, %s I" % (flake8_stats.nb_critical, flake8_stats.nb_warning, flake8_stats.nb_info)

return Badge(left_txt="flake8", right_txt=right_txt, color=color)
return Badge(left_txt=left_txt, right_txt=right_txt, color=color)


def get_flake8_stats(flake8_stats_file):
Expand Down
5 changes: 3 additions & 2 deletions genbadge/utils_junit.py
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ def get_color(


def get_tests_badge(
test_stats # type: TestStats
test_stats, # type: TestStats
left_txt = "tests" # type: str
):
# type: (...) -> Badge
"""Return the badge from test statistics """
Expand All @@ -106,4 +107,4 @@ def get_tests_badge(
# simplified badge showing the number of tests
right_txt = "%s" % (test_stats.total_without_skipped,)

return Badge(left_txt="tests", right_txt=right_txt, color=color)
return Badge(left_txt=left_txt, right_txt=right_txt, color=color)
2 changes: 1 addition & 1 deletion noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ def tests(session: PowerSession, coverage, pkg_specs):

# install all requirements
# session.install_reqs(phase="pip", phase_reqs=("pip",), versions_dct=pkg_specs)
session.install_reqs(setup=True, install=True, tests=True, extras=("all",), versions_dct=pkg_specs)
session.install_reqs(setup=True, install=True, tests=True, extras=("tests","coverage",), versions_dct=pkg_specs)
smarie marked this conversation as resolved.
Show resolved Hide resolved

# install CI-only dependencies
# if install_ci_deps:
Expand Down