Exercise 1: A Real 'slug' Converter — Possible Solution ==================================================================== ADDING THE CONVERTER ------------------------------ CONVERTERS = { 'int': (r'\d+', int), 'str': (r'[^/]+', str), 'slug': (r'[a-z0-9]+(?:-[a-z0-9]+)*', str), } The regex requires one or more lowercase letters/digits, optionally followed by any number of "-" plus more lowercase letters/digits groups. This deliberately rejects a leading or trailing hyphen, and rejects two hyphens in a row, since each hyphen must be immediately followed by at least one more alphanumeric character. TESTING IT ------------------------------ pattern, types = compile_typed_pattern('/posts/') for test in ['/posts/hello-world-42', '/posts/Hello World!']: m = pattern.match(test) print(test, '->', m.groupdict() if m else 'no match') RESULTS ------------------------------ /posts/hello-world-42 -> {'title': 'hello-world-42'} /posts/Hello World! -> no match "hello-world-42" matches cleanly - all lowercase letters, digits, and single hyphens between alphanumeric groups. "Hello World!" fails on multiple counts: it contains uppercase letters (never in the character class at all), a literal space (not a valid path character to begin with, and not in the class either), and an exclamation mark (not in the class). The regex doesn't need any of these individually checked - they simply aren't part of what [a-z0-9]+(?:-[a-z0-9]+)* accepts, so the whole match fails outright. WHY THIS WORKS AS AN ANSWER ---------------------------- It adds a real converter following the chapter's own established (regex, cast_function) tuple shape, tests it against both a value that should pass and one that should genuinely fail for multiple concrete reasons, and shows the real printed output confirming both cases behave as expected rather than just asserting the regex is correct.