Skip to content

Commit ebae878

Browse files
committed
is_slug now allows multiple consecutive separator signs between words
1 parent bb8cef6 commit ebae878

File tree

3 files changed

+31
-4
lines changed

3 files changed

+31
-4
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ importable as before (`from string_utils import xxx`). Similarly `tests.py` has
6767
with a module for each test case
6868
- `is_snake_case()` now considers as "snake case" strings with mixed upper and lower case characters, strings with
6969
leading or trailing underscores and string containing multiple underscores in sequence
70+
- `is_slug()` now allows multiple consecutive separator signs between words
7071

7172
### Improvements:
7273

string_utils/validation.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -543,7 +543,7 @@ def is_isogram(input_string: Any) -> bool:
543543
return is_full_string(input_string) and len(set(input_string)) == len(input_string)
544544

545545

546-
def is_slug(input_string: Any, sign: str = '-') -> bool:
546+
def is_slug(input_string: Any, separator: str = '-') -> bool:
547547
"""
548548
Checks if a given string is a slug (as created by `slugify()`).
549549
@@ -554,14 +554,14 @@ def is_slug(input_string: Any, sign: str = '-') -> bool:
554554
555555
:param input_string: String to check.
556556
:type input_string: str
557-
:param sign: Join sign used by the slug.
558-
:type sign: str
557+
:param separator: Join sign used by the slug.
558+
:type separator: str
559559
:return: True if slug, false otherwise.
560560
"""
561561
if not is_full_string(input_string):
562562
return False
563563

564-
rex = r'^([a-z\d]+' + re.escape(sign) + r'?)*[a-z\d]$'
564+
rex = r'^([a-z\d]+' + re.escape(separator) + r'*?)*[a-z\d]$'
565565

566566
return re.match(rex, input_string) is not None
567567

tests/test_is_slug.py

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,11 @@ def test_recognizes_slugs(self):
2929
self.assertTrue(is_slug('yep.i.am.a.slug', '.'))
3030
self.assertTrue(is_slug('yep_i_am_a_slug', '_'))
3131

32+
def test_slug_can_have_multiple_consecutive_separator_signs(self):
33+
self.assertTrue(is_slug('oh-----yeah'))
34+
self.assertTrue(is_slug('oh_____yeah', '_'))
35+
self.assertTrue(is_slug('1----2'))
36+
3237
def test_slug_cannot_contain_spaces(self):
3338
self.assertFalse(is_slug('not - a - slug'))
3439
self.assertFalse(is_slug('not- a - slug'))
@@ -37,6 +42,18 @@ def test_slug_cannot_contain_spaces(self):
3742
self.assertFalse(is_slug('not-a-slug '))
3843
self.assertFalse(is_slug(' not-a-slug'))
3944

45+
def test_slug_cannot_contain_non_ascii_chars(self):
46+
self.assertFalse(is_slug('foò-bär'))
47+
48+
def test_slug_cannot_contain_punctuation(self):
49+
self.assertFalse(is_slug('foo.-bar'))
50+
self.assertFalse(is_slug('foo-bar.'))
51+
self.assertFalse(is_slug('foo-bar,'))
52+
self.assertFalse(is_slug('!foo-bar'))
53+
self.assertFalse(is_slug('foo-bar?'))
54+
self.assertFalse(is_slug('foo-bar:'))
55+
self.assertFalse(is_slug('foo-bar;'))
56+
4057
def test_exclude_invalid_slugs(self):
4158
self.assertFalse(is_slug(' nope'))
4259
self.assertFalse(is_slug('nope '))
@@ -46,3 +63,12 @@ def test_exclude_invalid_slugs(self):
4663
self.assertFalse(is_slug('-no-no-no-'))
4764
self.assertFalse(is_slug('100%no-slug!'))
4865
self.assertFalse(is_slug('NOT-AS-UPPERCASE'))
66+
67+
def test_slug_can_be_single_word(self):
68+
self.assertTrue(is_slug('hello'))
69+
self.assertTrue(is_slug('x'))
70+
self.assertTrue(is_slug('42'))
71+
self.assertTrue(is_slug('5'))
72+
73+
def test_slug_must_have_at_least_one_non_separator_char(self):
74+
self.assertFalse(is_slug('-'))

0 commit comments

Comments
 (0)