diff --git a/markdownify/__init__.py b/markdownify/__init__.py index 28cdaf6..ff0a3f2 100644 --- a/markdownify/__init__.py +++ b/markdownify/__init__.py @@ -210,6 +210,11 @@ def __init__(self, **options): if self.options['strip'] is not None and self.options['convert'] is not None: raise ValueError('You may specify either tags to strip or tags to' ' convert, but not both.') + if len(self.options['bullets']) == 0: + # convert_li cycles through bullets with `bullets[depth % len(bullets)]`, + # so an empty bullets sequence raises an opaque ZeroDivisionError deep in + # list conversion. Reject it up front with a clear message instead. + raise ValueError('bullets must contain at least one bullet character.') # If a string or list is passed to bs4_options, assume it is a 'features' specification if not isinstance(self.options['bs4_options'], dict): diff --git a/tests/test_args.py b/tests/test_args.py index 838ef9d..1fa914d 100644 --- a/tests/test_args.py +++ b/tests/test_args.py @@ -2,10 +2,26 @@ Test whitelisting/blacklisting of specific tags. """ -from markdownify import markdownify, LSTRIP, RSTRIP, STRIP, STRIP_ONE +import pytest + +from markdownify import MarkdownConverter, markdownify, LSTRIP, RSTRIP, STRIP, STRIP_ONE from .utils import md +@pytest.mark.parametrize("empty_bullets", ['', [], ()]) +def test_empty_bullets_rejected(empty_bullets): + # An empty bullets sequence has no bullet character to cycle through. It must + # be rejected at construction with a clear ValueError rather than raising an + # opaque ZeroDivisionError later, deep in list conversion. + with pytest.raises(ValueError, match="bullets must contain at least one"): + MarkdownConverter(bullets=empty_bullets) + + +def test_non_empty_bullets_still_accepted(): + assert md('