| 3414 | class StringPrefixTest(unittest.TestCase): |
| 3415 | @staticmethod |
| 3416 | def determine_valid_prefixes(): |
| 3417 | # Try all lengths until we find a length that has zero valid |
| 3418 | # prefixes. This will miss the case where for example there |
| 3419 | # are no valid 3 character prefixes, but there are valid 4 |
| 3420 | # character prefixes. That seems unlikely. |
| 3421 | |
| 3422 | single_char_valid_prefixes = set() |
| 3423 | |
| 3424 | # Find all of the single character string prefixes. Just get |
| 3425 | # the lowercase version, we'll deal with combinations of upper |
| 3426 | # and lower case later. I'm using this logic just in case |
| 3427 | # some uppercase-only prefix is added. |
| 3428 | for letter in itertools.chain(string.ascii_lowercase, string.ascii_uppercase): |
| 3429 | try: |
| 3430 | eval(f'{letter}""') |
| 3431 | single_char_valid_prefixes.add(letter.lower()) |
| 3432 | except SyntaxError: |
| 3433 | pass |
| 3434 | |
| 3435 | # This logic assumes that all combinations of valid prefixes only use |
| 3436 | # the characters that are valid single character prefixes. That seems |
| 3437 | # like a valid assumption, but if it ever changes this will need |
| 3438 | # adjusting. |
| 3439 | valid_prefixes = set() |
| 3440 | for length in itertools.count(): |
| 3441 | num_at_this_length = 0 |
| 3442 | for prefix in ( |
| 3443 | "".join(l) |
| 3444 | for l in itertools.combinations(single_char_valid_prefixes, length) |
| 3445 | ): |
| 3446 | for t in itertools.permutations(prefix): |
| 3447 | for u in itertools.product(*[(c, c.upper()) for c in t]): |
| 3448 | p = "".join(u) |
| 3449 | if p == "not": |
| 3450 | # 'not' can never be a string prefix, |
| 3451 | # because it's a valid expression: not "" |
| 3452 | continue |
| 3453 | try: |
| 3454 | eval(f'{p}""') |
| 3455 | |
| 3456 | # No syntax error, so p is a valid string |
| 3457 | # prefix. |
| 3458 | |
| 3459 | valid_prefixes.add(p) |
| 3460 | num_at_this_length += 1 |
| 3461 | except SyntaxError: |
| 3462 | pass |
| 3463 | if num_at_this_length == 0: |
| 3464 | return valid_prefixes |
| 3465 | |
| 3466 | |
| 3467 | def test_prefixes(self): |