* The repo files a Python module path can name from `fromFile`. Relative * paths (`..settings`) resolve exactly; absolute ones match a file path * suffix, so a source root (`src/`) still resolves — and two files sharing * the tail (`x/settings.py`, `y/settings.py`) both come back.
(dotted: string, fromFile: string, context: ResolutionContext)
| 694 | * the tail (`x/settings.py`, `y/settings.py`) both come back. |
| 695 | */ |
| 696 | function pythonModuleFiles(dotted: string, fromFile: string, context: ResolutionContext): string[] { |
| 697 | const dots = dotted.match(/^\.+/)?.[0].length ?? 0; |
| 698 | const parts = dotted.slice(dots).split('.').filter(Boolean); |
| 699 | if (!parts.length) return []; |
| 700 | let dir = ''; |
| 701 | if (dots) { |
| 702 | dir = path.posix.dirname(fromFile.replace(/\\/g, '/')); |
| 703 | for (let i = 1; i < dots; i++) dir = path.posix.dirname(dir); |
| 704 | if (dir === '.') dir = ''; |
| 705 | } |
| 706 | const rel = [dir, ...parts].filter(Boolean).join('/'); |
| 707 | const matches = (file: string, want: string) => dots ? file === want : file === want || file.endsWith(`/${want}`); |
| 708 | const last = parts[parts.length - 1]!; |
| 709 | return [ |
| 710 | ...context.getNodesByName(`${last}.py`), ...context.getNodesByName(`${last}.pyi`), ...context.getNodesByName('__init__.py'), |
| 711 | ].filter(n => n.kind === 'file' && (matches(n.filePath, `${rel}.py`) || matches(n.filePath, `${rel}.pyi`) || matches(n.filePath, `${rel}/__init__.py`))) |
| 712 | .map(n => n.filePath); |
| 713 | } |
| 714 | |
| 715 | /** |
| 716 | * How `filePath` spells the module `moduleFile`: `aliases` import exactly that |
no test coverage detected