Parse Unicode CaseFolding.txt into a dict: codepoint -> folded UTF-8 bytes. Uses status C (common) and F (full) mappings for full case folding.
(filepath: str)
| 70 | return sorted(codepoints) |
| 71 | |
| 72 | def parse_case_folding_file(filepath: str) -> Dict[int, bytes]: |
| 73 | """Parse Unicode CaseFolding.txt into a dict: codepoint -> folded UTF-8 bytes. |
| 74 | |
| 75 | Uses status C (common) and F (full) mappings for full case folding. |
| 76 | """ |
| 77 | folds = {} |
| 78 | with open(filepath, "r", encoding="utf-8") as f: |
| 79 | for line in f: |
| 80 | line = line.strip() |
| 81 | if not line or line.startswith("#"): |
| 82 | continue |
| 83 | parts = line.split(";") |
| 84 | if len(parts) < 3: |
| 85 | continue |
| 86 | status = parts[1].strip() |
| 87 | # C = common, F = full (for expansions like ß → ss) |
| 88 | # Skip S (simple) and T (Turkic) for full case folding |
| 89 | if status not in ("C", "F"): |
| 90 | continue |
| 91 | try: |
| 92 | codepoint = int(parts[0].strip(), 16) |
| 93 | # Mapping can be multiple codepoints separated by spaces (e.g., "0073 0073" for ß → ss) |
| 94 | target_cps = [int(x, 16) for x in parts[2].split("#")[0].strip().split()] |
| 95 | # Convert target codepoints to UTF-8 bytes |
| 96 | folded_str = "".join(chr(cp) for cp in target_cps) |
| 97 | folds[codepoint] = folded_str.encode("utf-8") |
| 98 | except (ValueError, IndexError): |
| 99 | continue |
| 100 | return folds |
| 101 | |
| 102 | |
| 103 | def _download_case_folding_file(version: str) -> str: |
no test coverage detected
searching dependent graphs…