MCPcopy
hub / github.com/colbymchenry/codegraph / resolvePythonModuleMember

Function resolvePythonModuleMember

src/resolution/import-resolver.ts:1348–1400  ·  view source on GitHub ↗

* Resolve a Python qualified reference whose receiver is an imported MODULE: * `certs.where()` after `from . import certs`, `mod.func()` after `import mod` * or `from pkg import mod`. The receiver names a submodule (a file), not a * symbol, so the generic symbol lookup in `resolveViaImport` can't

(
  ref: UnresolvedRef,
  imports: ImportMapping[],
  context: ResolutionContext
)

Source from the content-addressed store, hash-verified

1346 * to the other strategies untouched.
1347 */
1348function resolvePythonModuleMember(
1349 ref: UnresolvedRef,
1350 imports: ImportMapping[],
1351 context: ResolutionContext
1352): ResolvedRef | null {
1353 const dotIdx = ref.referenceName.indexOf('.');
1354 if (dotIdx <= 0) return null;
1355 const receiver = ref.referenceName.substring(0, dotIdx);
1356 // The immediate member of the module (first segment after the receiver).
1357 const member = ref.referenceName.substring(dotIdx + 1).split('.')[0];
1358 if (!member) return null;
1359
1360 for (const imp of imports) {
1361 if (imp.localName !== receiver) continue;
1362
1363 // `import mod` / `import numpy as np` bind the module at `source` itself;
1364 // `from . import certs` / `from pkg import mod` bind a SUBMODULE whose
1365 // dotted path is the source joined with the imported name.
1366 const modulePath = imp.isNamespace
1367 ? imp.source
1368 : imp.source.endsWith('.')
1369 ? imp.source + imp.localName
1370 : imp.source + '.' + imp.localName;
1371
1372 // resolveImportPath only maps RELATIVE dotted paths (`.mod`, `..pkg.mod`); an
1373 // ABSOLUTE package path (`pkg.module` from `from pkg import module`, or a bare
1374 // `import pkg.mod`) resolves to null there, so fall back to the dotted-module
1375 // file lookup — the same asymmetry resolveModuleImportToFile already handles
1376 // for the file→file import edge. Without this, a `module.func()` call after
1377 // `from pkg import module` dropped its `calls` edge even though the import
1378 // edge resolved (#578).
1379 let resolvedPath = resolveImportPath(modulePath, ref.filePath, ref.language, context);
1380 if (!resolvedPath) {
1381 resolvedPath = findPythonModuleFile(modulePath, context, ref.filePath)?.filePath ?? null;
1382 }
1383 if (!resolvedPath || resolvedPath === ref.filePath) continue;
1384
1385 // Find the member as a top-level definition in the module file. Exclude
1386 // `method` so `mod.foo` never lands on a same-named class method.
1387 const target = context.getNodesInFile(resolvedPath).find(
1388 (n) =>
1389 n.name === member &&
1390 (n.kind === 'function' ||
1391 n.kind === 'class' ||
1392 n.kind === 'variable' ||
1393 n.kind === 'constant')
1394 );
1395 if (target) {
1396 return { original: ref, targetNodeId: target.id, confidence: 0.85, resolvedBy: 'import' };
1397 }
1398 }
1399 return null;
1400}
1401
1402/**
1403 * Resolve a whole-MODULE import to that module's file (a file→file dependency).

Callers 1

resolveViaImportFunction · 0.85

Calls 3

resolveImportPathFunction · 0.85
findPythonModuleFileFunction · 0.85
getNodesInFileMethod · 0.65

Tested by

no test coverage detected