@@ -278,6 +278,53 @@ def __getattr__(name): # pragma: no cover
278278 globals ()[_name ] = replacement
279279
280280
281+ # Lightweight lazy proxy objects so the attribute exists in the
282+ # module dict immediately. This helps REPLs and completers that
283+ # inspect `module.__dict__` or `dir(module)` prefer the callable/class
284+ # export over a same-named submodule while still deferring the real
285+ # import until first use.
286+ def _resolve_lazy (name , submodule ): # pragma: no cover
287+ full_module_path = f"{ __package__ } .{ submodule } "
288+ module = importlib .import_module (full_module_path )
289+ obj = getattr (module , name )
290+ globals ()[name ] = obj
291+ return obj
292+
293+
294+ # Eagerly import exports that would otherwise collide with
295+ # same-named submodules. This keeps lazy imports for most names but
296+ # ensures that when a top-level exported name exactly matches its
297+ # submodule (e.g., `stump` -> `stump.py`), the exported attribute is
298+ # available immediately so REPL completers prefer the callable/class
299+ # instead of the module.
300+ for _name , _sub in _lazy_imports .items (): # pragma: no cover
301+ try :
302+ if _name == _sub :
303+ filepath = pathlib .Path (__file__ ).parent / f"{ _sub } .py"
304+ if filepath .exists ():
305+ module = importlib .import_module (f"{ __package__ } .{ _sub } " )
306+ try :
307+ globals ()[_name ] = getattr (module , _name )
308+ except AttributeError :
309+ # If the submodule doesn't define the attribute, keep it lazy
310+ pass
311+ except Exception :
312+ # Be conservative: don't let eager-import attempts raise during package import
313+ pass
314+
315+
281316def __dir__ (): # pragma: no cover
282317 # Expose lazy names in dir() for discoverability
283- return sorted (list (globals ().keys ()) + list (_lazy_imports .keys ()))
318+ # Also include __all__ so tools that consult it will see the intended
319+ # top-level exports (this helps some REPL completers prefer the
320+ # callable/class exports over same-named submodules).
321+ all_names = list (globals ().keys ()) + list (_lazy_imports .keys ())
322+ all_names += list (globals ().get ("__all__" , []))
323+ return sorted (all_names )
324+
325+
326+ # Make the lazy-exported names explicit for tools that respect __all__.
327+ # This helps REPL tab-completion prefer functions/classes over submodules
328+ # when names collide (e.g., `stumpy.stump` should point to the function
329+ # rather than the module during completion).
330+ __all__ = sorted (list (_lazy_imports .keys ()))
0 commit comments