Documentation
¶
Overview ¶
init_importlib sequence. Mirrors the two-phase importlib bootstrap in pylifecycle.c: first the pure-Python _frozen_importlib is installed, then _frozen_importlib_external extends it.
In gopy the frozen code objects start as nil placeholders (see frozen_bootstrap.go). InitImportlib returns ErrBootstrapNotReady when the code objects have not been embedded yet; callers in the early lifecycle can treat this as a soft error and proceed with a reduced import system.
CPython: Python/pylifecycle.c:L987 init_importlib CPython: Python/pylifecycle.c:L1041 init_importlib_external
ExecCodeModule: execute a code object in a module's namespace and register the result in sys.modules. Mirrors PyImport_ExecCodeModule.
CPython: Python/import.c:L644 PyImport_ExecCodeModule CPython: Python/import.c:L670 exec_code_in_module
Package imp is the Go port of CPython's import machinery. imp/frozen.go implements the frozen module table: code objects that are compiled into the interpreter and can be imported without touching the filesystem.
CPython: Python/frozen.c CPython: Python/import.c:L1240 import_find_frozen CPython: Include/import.h:L24 struct _frozen
Frozen bootstrap module registrations. These correspond to the modules that CPython compiles from Lib/importlib/_bootstrap.py and Lib/importlib/_bootstrap_external.py at build time and embeds as frozen bytecode.
In gopy the Code fields start as nil (placeholder). They are filled in by the imp/bootstrap.go init sequence once the compiler produces compatible code objects.
CPython: Python/frozen.c:L56 _PyImport_FrozenModules bootstrap entries
ImportModuleLevel: the primary entry point for the import statement. Mirrors PyImport_ImportModuleLevelObject: check sys.modules, then try frozen modules, then built-in (inittab) modules. File-based loading via sys.path finders is deferred to the importlib bootstrap.
CPython: Python/import.c:L1561 PyImport_ImportModuleLevelObject CPython: Python/import.c:L1450 PyImport_ImportModule
Built-in module initializer table. Mirrors _PyImport_Inittab: a list of (name, initfunc) pairs for modules that are compiled in. AppendInittab registers new entries; FindInitFunc looks them up.
CPython: Python/import.c:L173 _PyImport_Inittab CPython: Python/import.c:L243 PyImport_AppendInittab CPython: Python/import.c:L212 PyImport_ExtendInittab
Source and bytecode loaders. Mirrors the CPython SourceFileLoader and SourcelessFileLoader from Lib/importlib/_bootstrap_external.py.
LoadPyc reads a .pyc file and calls ExecCodeModule. LoadSource compiles a .py file via a caller-provided SourceCompiler then calls ExecCodeModule; the compiler function is injected to avoid a circular import between imp and the parser/compile packages.
CPython: Lib/importlib/_bootstrap_external.py:L1045 SourceFileLoader CPython: Lib/importlib/_bootstrap_external.py:L1215 SourcelessFileLoader
Path-based finder. Mirrors the trio of CPython classes that locate a module on disk:
PathFinder - meta-path entry that walks sys.path FileFinder - per-directory finder SourceFileLoader - loads + compiles .py files
The CPython chain sits inside _frozen_importlib_external; the classes are full Python objects with caches, namespace-package support, and a path_importer_cache hook. gopy ports the slice that import statements actually exercise: walk a list of directories, look for `<tail>.py` or `<tail>/__init__.py`, hand the file to the existing LoadSourceFile path. Caching, .pyc fallback, namespace packages, and the path_hooks plumbing land later.
CPython: Lib/importlib/_bootstrap_external.py:1196 PathFinder CPython: Lib/importlib/_bootstrap_external.py:1322 FileFinder CPython: Lib/importlib/_bootstrap_external.py:962 SourceFileLoader
ReloadModule: re-execute a module against its existing namespace so importlib.reload(m) keeps the same module object alive while picking up new definitions. Mirrors PyImport_ReloadModule, which delegates to importlib.reload; gopy has no working importlib bootstrap yet, so we inline the bits of the Python-level reload that matter for the frozen and built-in module cases.
CPython: Python/import.c:3983 PyImport_ReloadModule CPython: Lib/importlib/__init__.py:94 reload
sys.modules registry. Mirrors the interp->modules dict that CPython uses as the global module cache. The dict returned by SysModules is the same object Python code sees as sys.modules: every import path writes through it, every cache hit reads from it.
CPython: Python/import.c:L276 PyImport_GetModule CPython: Python/import.c:L297 PyImport_AddModule CPython: Python/import.c:L329 PyImport_RemoveModule
Index ¶
- Variables
- func AddModule(name string, mod *objects.Module) *objects.Module
- func AppendInittab(name string, init InitFunc) error
- func ExecCodeModule(exec Executor, name string, code *objects.Code) (*objects.Module, error)
- func ExtendInittab(entries []InittabEntry) error
- func GetModule(name string) (*objects.Module, bool)
- func ImportModule(exec Executor, name string) (*objects.Module, error)
- func ImportModuleLevel(exec Executor, name, pkgname string, level int) (*objects.Module, error)
- func InitImportlib(exec Executor, sysmod *objects.Module) error
- func InitImportlibExternal(exec Executor) error
- func IsFrozen(name string) bool
- func LoadPyc(exec Executor, filename, name string) (*objects.Module, error)
- func LoadSource(exec Executor, compiler SourceCompiler, src, filename, name string) (*objects.Module, error)
- func LoadSourceFile(exec Executor, compiler SourceCompiler, filename, name string) (*objects.Module, error)
- func RegisterFrozen(m *FrozenModule)
- func ReloadModule(exec Executor, mod *objects.Module) (*objects.Module, error)
- func RemoveModule(name string)
- func SetPathFinder(f *PathFinder)
- func SysModules() *objects.Dict
- func SysModulesSnapshot() map[string]*objects.Module
- type Executor
- type FrozenModule
- type InitFunc
- type InittabEntry
- type PathFinder
- type SourceCompiler
Constants ¶
This section is empty.
Variables ¶
var ErrBootstrapNotReady = errors.New("imp: bootstrap: frozen importlib code objects are not yet embedded")
ErrBootstrapNotReady is returned when the frozen importlib code objects have not been embedded yet (placeholder state).
var ErrModuleNotFound = fmt.Errorf("imp: ModuleNotFoundError")
ErrModuleNotFound is returned when no finder can locate the named module.
Functions ¶
func AddModule ¶
AddModule adds mod to sys.modules under name. If an entry already exists it is replaced. The module pointer is returned for chaining.
CPython: Python/import.c:L297 PyImport_AddModule
func AppendInittab ¶
AppendInittab adds a single built-in module entry. It is safe to call from multiple goroutines and from init().
CPython: Python/import.c:L243 PyImport_AppendInittab
func ExecCodeModule ¶
ExecCodeModule executes code in a fresh module named name, sets the standard dunder attributes, registers the module in sys.modules, and returns it. If name is already in sys.modules the existing module is reused so that partially-initialized modules see updates in-place.
CPython: Python/import.c:L644 PyImport_ExecCodeModule
func ExtendInittab ¶
func ExtendInittab(entries []InittabEntry) error
ExtendInittab appends multiple entries at once. It stops and returns an error if any entry has a nil Init.
CPython: Python/import.c:L212 PyImport_ExtendInittab
func GetModule ¶
GetModule returns the module registered under name in sys.modules, or (nil, false) if absent or if the entry is not a module.
CPython: Python/import.c:L276 PyImport_GetModule
func ImportModule ¶
ImportModule performs an absolute import of name. It is the zero-level convenience wrapper around ImportModuleLevel.
CPython: Python/import.c:L1450 PyImport_ImportModule
func ImportModuleLevel ¶
ImportModuleLevel imports name relative to pkgname at the given level. level=0 is an absolute import; level>0 is relative.
The lookup order is:
- sys.modules cache
- Frozen modules (FrozenModule table)
- Built-in modules (Inittab)
- ErrModuleNotFound
File-based imports via sys.path and the importlib finder chain are resolved by the importlib bootstrap (imp/bootstrap.go), which registers a custom __import__ hook after it initializes.
CPython: Python/import.c:L1561 PyImport_ImportModuleLevelObject
func InitImportlib ¶
InitImportlib runs phase 1 of the importlib bootstrap: executes the _frozen_importlib code object and installs the resulting module into sys.modules. It then calls the module's _install(sys_module) hook.
Returns ErrBootstrapNotReady when the frozen code object has not been embedded yet.
CPython: Python/pylifecycle.c:L987 init_importlib
func InitImportlibExternal ¶
InitImportlibExternal runs phase 2 of the importlib bootstrap: executes _frozen_importlib_external and calls its _install hook with the _frozen_importlib module.
CPython: Python/pylifecycle.c:L1041 init_importlib_external
func IsFrozen ¶
IsFrozen reports whether name is in the frozen module table, regardless of whether its Code field is populated.
CPython: Python/import.c:L1268 PyImport_IsFrozenModule
func LoadPyc ¶
LoadPyc opens filename, validates the .pyc header, and executes the embedded code object in a module named name. The returned module is registered in sys.modules.
CPython: Lib/importlib/_bootstrap_external.py:L1215 SourcelessFileLoader.exec_module
func LoadSource ¶
func LoadSource(exec Executor, compiler SourceCompiler, src, filename, name string) (*objects.Module, error)
LoadSource compiles src to a code object via compiler, then executes it in a module named name. The returned module is registered in sys.modules.
CPython: Lib/importlib/_bootstrap_external.py:L1045 SourceFileLoader.exec_module
func LoadSourceFile ¶
func LoadSourceFile(exec Executor, compiler SourceCompiler, filename, name string) (*objects.Module, error)
LoadSourceFile reads filename, compiles it via compiler, and calls LoadSource. It is a convenience wrapper for the common case of loading from disk.
CPython: Lib/importlib/_bootstrap_external.py:L1045 SourceFileLoader.get_code
func RegisterFrozen ¶
func RegisterFrozen(m *FrozenModule)
RegisterFrozen adds or replaces a frozen module in the table. It is safe to call from multiple goroutines and from init().
CPython: Python/frozen.c — populated at link time via _PyImport_FrozenModules
func ReloadModule ¶ added in v0.10.1
ReloadModule re-executes mod's underlying source against its existing __dict__. The module pointer is preserved so callers that already hold a reference observe the new bindings in place.
The lookup mirrors ImportModuleLevel's order without the sys.modules short-circuit: frozen modules first, then the inittab. Source-only modules cannot be reloaded yet because gopy does not retain the originating Code on the module.
CPython: Python/import.c:3983 PyImport_ReloadModule CPython: Lib/importlib/__init__.py:94 reload
func RemoveModule ¶
func RemoveModule(name string)
RemoveModule removes the module registered under name. It is a no-op if name is not present.
CPython: Python/import.c:L329 PyImport_RemoveModule
func SetPathFinder ¶ added in v0.12.3
func SetPathFinder(f *PathFinder)
SetPathFinder installs the package-level PathFinder consulted by ImportModuleLevel after the inittab miss. Callers (lifecycle, cmd/gopy, tests) build a PathFinder with the desired Paths and Compiler and pass it here once at startup.
Passing nil clears the finder, which is useful for tests that want to confirm an import fails when path-based lookup is disabled.
func SysModules ¶ added in v0.12.3
SysModules returns the dict backing sys.modules. The same pointer is stamped onto the sys module as `sys.modules` so Python and Go share one view of the cache.
CPython: Python/sysmodule.c interp->modules
func SysModulesSnapshot ¶
SysModulesSnapshot returns a shallow copy of sys.modules as a plain Go map. Callers receive a stable snapshot; later mutations to the registry are not reflected. Non-module entries are skipped.
CPython: Python/sysmodule.c interp->modules
Types ¶
type Executor ¶
type Executor interface {
ExecCode(code *objects.Code, mod *objects.Module) (objects.Object, error)
}
Executor is the minimal interface the bootstrap needs from the eval loop: execute a code object in the given module's namespace and return its result.
CPython: Python/ceval.c:L753 _PyEval_EvalCode (simplified)
type FrozenModule ¶
type FrozenModule struct {
// Name is the dotted module name, e.g. "importlib._bootstrap".
Name string
// Code is the precompiled code object. nil for placeholder entries.
Code *objects.Code
// IsPackage is true when the frozen module is a package (has __path__).
IsPackage bool
}
FrozenModule holds a single frozen module entry. A nil Code pointer means the module is a known-frozen name but the bytecode has not yet been embedded (placeholder state).
CPython: Include/import.h:L24 struct _frozen
func FindFrozen ¶
func FindFrozen(name string) (*FrozenModule, bool)
FindFrozen looks up a frozen module by exact dotted name. It returns the entry and true if found, nil and false otherwise.
CPython: Python/import.c:L1240 import_find_frozen
func FrozenList ¶
func FrozenList() []*FrozenModule
FrozenList returns a snapshot of all registered frozen modules.
type InitFunc ¶
InitFunc is the initializer signature for a built-in module. It mirrors the C Py_InitProc signature.
CPython: Include/import.h:L8 PyImport_InitModuleFunc
func FindInitFunc ¶
FindInitFunc returns the InitFunc registered for name, or nil if the module is not in the built-in table.
CPython: Python/import.c:L256 _PyImport_FindExtensionObjectUnicode
type InittabEntry ¶
InittabEntry is one row in the built-in module table.
CPython: Include/import.h:L12 struct _inittab
func InittabSnapshot ¶
func InittabSnapshot() []InittabEntry
InittabSnapshot returns a copy of the current built-in module table.
type PathFinder ¶ added in v0.12.3
type PathFinder struct {
// Paths is the ordered directory list. Entries are absolute or
// relative to the process cwd; empty entries are treated as ".".
// CPython: Lib/importlib/_bootstrap_external.py:1290 path = sys.path
Paths []string
// Compiler is the SourceCompiler used to turn .py source into a
// code object. It is injected by the runtime to dodge a parser
// cycle on imp; see loader.go for the same hook on LoadSource.
// CPython: Python/pythonrun.c:1102 Py_CompileStringExFlags
Compiler SourceCompiler
}
PathFinder is the gopy port of importlib's PathFinder meta-path hook. It carries the directory list to search (the equivalent of sys.path) plus the SourceCompiler the resulting loader should use.
CPython: Lib/importlib/_bootstrap_external.py:1196 PathFinder
func GetPathFinder ¶ added in v0.12.3
func GetPathFinder() *PathFinder
GetPathFinder returns the currently installed PathFinder, or nil.
func (*PathFinder) FindModule ¶ added in v0.12.3
FindModule walks the directories that should be searched for name and either loads the matching source file as a module, returns errFinderMiss when no entry matched, or returns the loader's error when the file was found but compile/exec failed. Top-level names are searched against Paths; dotted names are searched against the parent package's __path__, matching CPython's FileFinder behavior.
CPython: Lib/importlib/_bootstrap_external.py:1357 FileFinder.find_spec CPython: Lib/importlib/_bootstrap.py:1184 _find_and_load
type SourceCompiler ¶
SourceCompiler compiles Python source text to a code object. Callers (lifecycle, pythonrun) inject a concrete implementation; this breaks the circular dependency between imp and parser/compile.
CPython: Python/pythonrun.c:L1102 Py_CompileStringExFlags