mirror of
https://github.com/jongracecox/anybadge.git
synced 2025-07-21 12:21:03 +02:00
Allow badges with no value or no label (#89)
This commit allows badges to be generated with only a label or only a value. Badges must provide at least a label or a value, so it is not valid to create a badge with no label and no value. This will result in a `ValueError` being raised.
This commit is contained in:
committed by
Jon Grace-Cox
parent
a076a4867a
commit
9d4470a1a0
10
README.md
10
README.md
@@ -317,6 +317,16 @@ Here are some examples to show how to use padding to fix layout:
|
|||||||
|  | `anybadge.Badge("Pipeline status", "😄")` |
|
|  | `anybadge.Badge("Pipeline status", "😄")` |
|
||||||
|  | `anybadge.Badge("Pipeline status", "😄", num_value_padding_chars=1)` |
|
|  | `anybadge.Badge("Pipeline status", "😄", num_value_padding_chars=1)` |
|
||||||
|
|
||||||
|
### Value or label only
|
||||||
|
|
||||||
|
It is possible to create badges with only a label or only a value. This can be done by passing
|
||||||
|
an empty string to the appropriate field. Note that either a label or value must be provided.
|
||||||
|
|
||||||
|
| Badge | Code |
|
||||||
|
|---------------------------------------------------------------------------------|--------------------------------------|
|
||||||
|
|  | `anybadge.Badge(label="Label only")` |
|
||||||
|
|  | `anybadge.Badge(value="Value only")` |
|
||||||
|
|
||||||
### Semantic version support
|
### Semantic version support
|
||||||
|
|
||||||
Anybadge supports semantic versions for value and threshold keys. This supports color-coded
|
Anybadge supports semantic versions for value and threshold keys. This supports color-coded
|
||||||
|
@@ -153,6 +153,14 @@ class Badge:
|
|||||||
self.label = label
|
self.label = label
|
||||||
self.value = value
|
self.value = value
|
||||||
|
|
||||||
|
if self.label is None:
|
||||||
|
self.label = ""
|
||||||
|
if self.value is None:
|
||||||
|
self.value = ""
|
||||||
|
|
||||||
|
if len(str(self.label)) == 0 and len(str(self.value)) == 0:
|
||||||
|
raise ValueError("Either a label or a value must be provided for a badge.")
|
||||||
|
|
||||||
self.value_is_version = semver
|
self.value_is_version = semver
|
||||||
|
|
||||||
self.value_format = value_format
|
self.value_format = value_format
|
||||||
@@ -414,6 +422,9 @@ class Badge:
|
|||||||
|
|
||||||
Returns: int
|
Returns: int
|
||||||
"""
|
"""
|
||||||
|
if len(str(self.label)) == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
return int(
|
return int(
|
||||||
self.get_text_width(str(self.label))
|
self.get_text_width(str(self.label))
|
||||||
+ (2.0 * self.num_label_padding_chars * self.font_width)
|
+ (2.0 * self.num_label_padding_chars * self.font_width)
|
||||||
@@ -433,6 +444,9 @@ class Badge:
|
|||||||
|
|
||||||
Returns: int
|
Returns: int
|
||||||
"""
|
"""
|
||||||
|
if len(str(self.value_text)) == 0:
|
||||||
|
return 0
|
||||||
|
|
||||||
return int(
|
return int(
|
||||||
self.get_text_width(str(self.value_text))
|
self.get_text_width(str(self.value_text))
|
||||||
+ (2.0 * self.num_value_padding_chars * self.font_width)
|
+ (2.0 * self.num_value_padding_chars * self.font_width)
|
||||||
|
@@ -52,10 +52,8 @@ examples:
|
|||||||
"""
|
"""
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
parser.add_argument("-l", "--label", type=str, help="The badge label.")
|
parser.add_argument("-l", "--label", type=str, help="The badge label.", default="")
|
||||||
parser.add_argument(
|
parser.add_argument("-v", "--value", type=str, help="The badge value.", default="")
|
||||||
"-v", "--value", type=str, help="The badge value.", required=True
|
|
||||||
)
|
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"-m",
|
"-m",
|
||||||
"--value-format",
|
"--value-format",
|
||||||
@@ -196,9 +194,6 @@ def main(args=None):
|
|||||||
if not args.suffix and style.suffix:
|
if not args.suffix and style.suffix:
|
||||||
suffix = style.suffix
|
suffix = style.suffix
|
||||||
|
|
||||||
if not label:
|
|
||||||
raise ValueError("Label has not been set. Please use --label argument.")
|
|
||||||
|
|
||||||
# Create threshold list from args
|
# Create threshold list from args
|
||||||
threshold_list = [x.split("=") for x in threshold_text]
|
threshold_list = [x.split("=") for x in threshold_text]
|
||||||
threshold_dict = {x[0]: x[1] for x in threshold_list}
|
threshold_dict = {x[0]: x[1] for x in threshold_list}
|
||||||
|
@@ -24,7 +24,7 @@ def color_examples_table():
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
def emoji_examples():
|
def other_examples():
|
||||||
"""Generate emoji example badges used in documentation."""
|
"""Generate emoji example badges used in documentation."""
|
||||||
examples_dir = Path(__file__).parent / Path("examples")
|
examples_dir = Path(__file__).parent / Path("examples")
|
||||||
for label, value, file, kwargs in [
|
for label, value, file, kwargs in [
|
||||||
@@ -38,6 +38,8 @@ def emoji_examples():
|
|||||||
("Pipeline status", "😟", "pipeline_frown.svg", {"default_color": "Red"}),
|
("Pipeline status", "😟", "pipeline_frown.svg", {"default_color": "Red"}),
|
||||||
("🔗", "Documentation", "documentation_link.svg", {}),
|
("🔗", "Documentation", "documentation_link.svg", {}),
|
||||||
("🔗", "PyPi", "pypi_link.svg", {}),
|
("🔗", "PyPi", "pypi_link.svg", {}),
|
||||||
|
("", "Value only", "value_only.svg", {}),
|
||||||
|
("Label only", "", "label_only.svg", {}),
|
||||||
]:
|
]:
|
||||||
anybadge.Badge(label=label, value=value, **kwargs).write_badge(
|
anybadge.Badge(label=label, value=value, **kwargs).write_badge(
|
||||||
examples_dir / Path(file), overwrite=True
|
examples_dir / Path(file), overwrite=True
|
||||||
@@ -46,7 +48,7 @@ def emoji_examples():
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
color_examples_table()
|
color_examples_table()
|
||||||
emoji_examples()
|
other_examples()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
@@ -34,6 +34,16 @@ anybadge --label="Label" --value="Value" --file "${TEST_FILES}/test_command_line
|
|||||||
check_rc
|
check_rc
|
||||||
echo "OK"
|
echo "OK"
|
||||||
|
|
||||||
|
echo -n "Testing with no label..."
|
||||||
|
anybadge --value="Value" --file "${TEST_FILES}/test_command_line_no_label.svg"
|
||||||
|
check_rc
|
||||||
|
echo "OK"
|
||||||
|
|
||||||
|
echo -n "Testing with no value..."
|
||||||
|
anybadge --label="Label" --file "${TEST_FILES}/test_command_line_no_value.svg"
|
||||||
|
check_rc
|
||||||
|
echo "OK"
|
||||||
|
|
||||||
echo -n "Testing python -m call... "
|
echo -n "Testing python -m call... "
|
||||||
python -m anybadge --label="Label" --value="Value" --file "${TEST_FILES}/test_m_command_line.svg"
|
python -m anybadge --label="Label" --value="Value" --file "${TEST_FILES}/test_m_command_line.svg"
|
||||||
check_rc
|
check_rc
|
||||||
|
23
examples/label_only.svg
Normal file
23
examples/label_only.svg
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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_152">
|
||||||
|
<rect width="71" height="20" rx="3" fill="#fff"/>
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#anybadge_152)">
|
||||||
|
<path fill="#555" d="M0 0h71v20H0z"/>
|
||||||
|
<path fill="#4c1" d="M71 0h0v20H71z"/>
|
||||||
|
<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="36.5" y="15" fill="#010101" fill-opacity=".3">Label only</text>
|
||||||
|
<text x="35.5" y="14">Label only</text>
|
||||||
|
</g>
|
||||||
|
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
||||||
|
<text x="72.0" y="15" fill="#010101" fill-opacity=".3"></text>
|
||||||
|
<text x="71.0" y="14"></text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
23
examples/value_only.svg
Normal file
23
examples/value_only.svg
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<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_151">
|
||||||
|
<rect width="71" height="20" rx="3" fill="#fff"/>
|
||||||
|
</mask>
|
||||||
|
<g mask="url(#anybadge_151)">
|
||||||
|
<path fill="#555" d="M0 0h0v20H0z"/>
|
||||||
|
<path fill="#4c1" d="M0 0h71v20H0z"/>
|
||||||
|
<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="1.0" y="15" fill="#010101" fill-opacity=".3"></text>
|
||||||
|
<text x="0.0" y="14"></text>
|
||||||
|
</g>
|
||||||
|
<g fill="#fff" text-anchor="middle" font-family="DejaVu Sans,Verdana,Geneva,sans-serif" font-size="11">
|
||||||
|
<text x="36.5" y="15" fill="#010101" fill-opacity=".3">Value only</text>
|
||||||
|
<text x="35.5" y="14">Value only</text>
|
||||||
|
</g>
|
||||||
|
</svg>
|
After Width: | Height: | Size: 1.0 KiB |
@@ -328,12 +328,6 @@ class TestAnybadge(TestCase):
|
|||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
def test_main_missing_value(self):
|
|
||||||
with self.assertRaisesRegex(
|
|
||||||
ValueError, r"Label has not been set\. Please use --label argument\."
|
|
||||||
):
|
|
||||||
main(["--value", "123", "--file", "test_badge_main.svg", "--overwrite"])
|
|
||||||
|
|
||||||
def test_version_comparison(self):
|
def test_version_comparison(self):
|
||||||
# Define thresholds: <3.0.0=red, <3.2.0=orange <999.0.0=green
|
# Define thresholds: <3.0.0=red, <3.2.0=orange <999.0.0=green
|
||||||
badge = Badge(
|
badge = Badge(
|
||||||
@@ -410,3 +404,45 @@ class TestAnybadge(TestCase):
|
|||||||
output_module = subprocess.check_output(["python", "-m", "anybadge", "--help"])
|
output_module = subprocess.check_output(["python", "-m", "anybadge", "--help"])
|
||||||
output_script = subprocess.check_output(["anybadge", "--help"])
|
output_script = subprocess.check_output(["anybadge", "--help"])
|
||||||
self.assertEqual(output_module, output_script)
|
self.assertEqual(output_module, output_script)
|
||||||
|
|
||||||
|
def test_badge_with_no_label(self):
|
||||||
|
"""Test the dimensions for a badge with no label."""
|
||||||
|
badge = Badge(
|
||||||
|
label="",
|
||||||
|
value="Value",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
badge.label_width,
|
||||||
|
0,
|
||||||
|
"Expected label width to be 0 for badge with no label.",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_badge_with_no_value(self):
|
||||||
|
"""Test the dimensions for a badge with no value."""
|
||||||
|
badge = Badge(
|
||||||
|
label="Label",
|
||||||
|
value="",
|
||||||
|
)
|
||||||
|
self.assertEqual(
|
||||||
|
badge.value_width,
|
||||||
|
0,
|
||||||
|
"Expected value width to be 0 for badge with no value.",
|
||||||
|
)
|
||||||
|
|
||||||
|
def test_badge_with_no_label_and_no_value(self):
|
||||||
|
"""Test that an exception is raised when trying to create a badge with no label or value."""
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
ValueError, r"Either a label or a value must be provided for a badge\."
|
||||||
|
):
|
||||||
|
_ = Badge(
|
||||||
|
label="",
|
||||||
|
value="",
|
||||||
|
)
|
||||||
|
|
||||||
|
with self.assertRaisesRegex(
|
||||||
|
ValueError, r"Either a label or a value must be provided for a badge\."
|
||||||
|
):
|
||||||
|
_ = Badge(
|
||||||
|
label=None,
|
||||||
|
value=None,
|
||||||
|
)
|
||||||
|
Reference in New Issue
Block a user