| 1906 | return dict(layout) |
| 1907 | |
| 1908 | def _classify(self, node: NodeInfo) -> str: |
| 1909 | name = node.name |
| 1910 | |
| 1911 | if name in self.EXACT_NAME_MODULES: |
| 1912 | return self.EXACT_NAME_MODULES[name] |
| 1913 | |
| 1914 | # Constants go to config/constants.py |
| 1915 | if node.kind == "constant" or re.match(r"^[A-Z][A-Z0-9_]{3,}$", name): |
| 1916 | return "config/constants.py" |
| 1917 | |
| 1918 | # Check class/exact patterns |
| 1919 | for pat_type, pattern, module in self.NAME_PATTERNS: |
| 1920 | if pat_type == "exact" and name == pattern: |
| 1921 | return module |
| 1922 | if pat_type == "prefix" and name.startswith(pattern): |
| 1923 | return module |
| 1924 | if pat_type == "suffix" and name.endswith(pattern): |
| 1925 | return module |
| 1926 | |
| 1927 | # Check function prefixes |
| 1928 | if node.kind in ("function", "assignment"): |
| 1929 | for pattern, module in self.FUNCTION_REGEX_RULES: |
| 1930 | if re.match(pattern, name): |
| 1931 | return module |
| 1932 | for prefix, module in self.FUNCTION_PREFIXES: |
| 1933 | if name.startswith(prefix) or name == prefix.rstrip("_"): |
| 1934 | return module |
| 1935 | |
| 1936 | # Proximity-based: functions near a class likely belong to it |
| 1937 | # (handled by the proximity pass in a future version) |
| 1938 | |
| 1939 | return "_unclassified.py" |
| 1940 | |
| 1941 | |
| 1942 | # ─── CLI ───────────────────────────────────────────────────────────────────── |