hbllmutils.meta.code.imp

Module for analyzing and extracting import statements from Python source code.

This module provides comprehensive functionality to parse Python code and extract all import statements, including both regular imports and from-imports. It uses the Abstract Syntax Tree (AST) to analyze the code structure and collect detailed import information with position tracking.

The module contains the following main components:

Key Features:

  • Support for both absolute and relative imports

  • Wildcard import detection (from module import *)

  • Import alias tracking

  • Source location information (line number and column offset)

  • Module classification (builtin, standard library, third-party)

  • PyPI package popularity checking for filtering

Note

This module requires the hbutils package for reflection utilities and depends on sibling modules for PyPI information retrieval.

Warning

The module uses dynamic import mechanisms which may have security implications when analyzing untrusted code.

Example:

>>> code = '''
... import os
... import sys as system
... from typing import List, Dict
... from collections import *
... '''
>>> imports = analyze_imports(code)
>>> len(imports)
4
>>> print(imports[0])
import os
>>> print(imports[2])
from typing import List
>>> imports[3].is_wildcard
True
>>> 
>>> # Check if imports should be ignored based on popularity
>>> stmt = ImportStatement(module='requests', line=1, col_offset=0)
>>> stmt.check_ignore_or_not(min_last_month_downloads=1000000)
True

ImportStatementTyping

hbllmutils.meta.code.imp.ImportStatementTyping

Type alias for either ImportStatement or FromImportStatement.

This type alias is used throughout the module to represent any kind of import statement, providing flexibility in function signatures and return types.

Example:

>>> def process_import(stmt: ImportStatementTyping) -> str:
...     return str(stmt)
>>> 
>>> stmt1 = ImportStatement(module='os')
>>> stmt2 = FromImportStatement(module='typing', name='List', level=0)
>>> process_import(stmt1)
'import os'
>>> process_import(stmt2)
'from typing import List'

alias of ImportStatement | FromImportStatement

ImportStatement

class hbllmutils.meta.code.imp.ImportStatement(module: str, alias: str | None = None, line: int = 0, col_offset: int = 0)[source]

Data class representing a regular import statement.

This class stores information about an import statement of the form import module or import module as alias. It provides utilities for analyzing the import and determining whether it should be included in documentation or analysis based on module popularity and type.

Parameters:
  • module (str) – The name of the module being imported

  • alias (Optional[str]) – The alias name for the imported module, if any

  • line (int) – The line number where the import statement appears

  • col_offset (int) – The column offset where the import statement starts

Variables:
  • module (str) – The full module path being imported

  • alias (Optional[str]) – Optional alias for the imported module

  • line (int) – Line number in source code

  • col_offset (int) – Column offset in source code

Example:

>>> stmt = ImportStatement(module='os', alias='operating_system', line=1, col_offset=0)
>>> print(stmt)
import os as operating_system
>>> stmt.root_module
'os'
>>> 
>>> # Nested module import
>>> stmt = ImportStatement(module='os.path', line=2, col_offset=0)
>>> stmt.root_module
'os'
>>> print(stmt)
import os.path
__str__() str[source]

Return a Python-readable representation of the import statement.

Constructs a valid Python import statement string that includes the module name and optional alias.

Returns:

A string representation of the import statement

Return type:

str

Example:

>>> stmt = ImportStatement(module='os', alias='operating_system')
>>> str(stmt)
'import os as operating_system'
>>> stmt = ImportStatement(module='sys')
>>> str(stmt)
'import sys'
check_ignore_or_not(min_last_month_downloads: int = 1000000, ignore_modules: Iterable[str] | None = None, no_ignore_modules: Iterable[str] | None = None) bool[source]

Determine whether this import should be ignored in analysis or documentation.

This method checks various criteria to decide if an import statement should be excluded from analysis, such as:

  • Module popularity (based on PyPI download statistics)

  • Module type (standard library vs third-party)

  • Explicit inclusion in no-ignore list

Parameters:
  • min_last_month_downloads (int, optional) – Minimum monthly download threshold for considering a package as “hot” and ignorable, defaults to 1000000

  • ignore_modules (Optional[Iterable[str]], optional) – Iterable of module names that should always be ignored

  • no_ignore_modules (Optional[Iterable[str]], optional) – Iterable of module names that should never be ignored regardless of other criteria

Returns:

True if the import should be ignored, False if it should be included

Return type:

bool

Note

The logic for ignoring imports:

  • Modules in ignore_modules are always ignored

  • Modules in no_ignore_modules are never ignored

  • Unknown/unimportable modules are ignored

  • Standard library modules are ignored

  • Popular third-party packages (hot projects) are ignored

  • Less popular third-party packages are not ignored

Example:

>>> stmt = ImportStatement(module='requests', line=1, col_offset=0)
>>> # Popular package, should be ignored
>>> stmt.check_ignore_or_not(min_last_month_downloads=1000000)
True
>>> 
>>> # Force inclusion with no_ignore_modules
>>> stmt.check_ignore_or_not(no_ignore_modules={'requests'})
False
>>> 
>>> # Standard library module
>>> stmt = ImportStatement(module='os', line=1, col_offset=0)
>>> stmt.check_ignore_or_not()
True
property module_file: str

Get the source code file path of the imported module.

This property attempts to locate and return the file path where the module’s source code is defined. It uses dynamic import to resolve the module location.

Returns:

The file path of the module’s source code

Return type:

str

Raises:
  • TypeError – If the module is a built-in module without a source file

  • ImportError – If the module cannot be imported

Warning

This property performs dynamic imports which may have side effects if the module executes code at import time.

Example:

>>> stmt = ImportStatement(module='os')
>>> stmt.module_file  
'/usr/lib/python3.x/os.py'
property root_module: str

Get the root module name from a potentially nested module path.

Extracts the top-level module name from a dotted module path. For example, for import os.path, this returns 'os' instead of 'os.path'.

Returns:

The root module name

Return type:

str

Example:

>>> stmt = ImportStatement(module='os.path.join')
>>> stmt.root_module
'os'
>>> stmt = ImportStatement(module='numpy')
>>> stmt.root_module
'numpy'

FromImportStatement

class hbllmutils.meta.code.imp.FromImportStatement(module: str, name: str, alias: str | None = None, level: int = 0, line: int = 0, col_offset: int = 0)[source]

Data class representing a from-import statement.

This class stores information about an import statement of the form from module import name or from module import name as alias. It supports both absolute and relative imports, as well as wildcard imports.

Parameters:
  • module (str) – The name of the module to import from

  • name (str) – The name of the object being imported (can be ‘*’ for wildcard imports)

  • alias (Optional[str]) – The alias name for the imported object, if any

  • level (int) – The level of relative import (0 for absolute, 1+ for relative)

  • line (int) – The line number where the import statement appears

  • col_offset (int) – The column offset where the import statement starts

Variables:
  • module (str) – Module path to import from

  • name (str) – Name of the imported object or ‘*’

  • alias (Optional[str]) – Optional alias for the imported name

  • level (int) – Relative import level (0=absolute, 1+=relative)

  • line (int) – Line number in source code

  • col_offset (int) – Column offset in source code

Example:

>>> stmt = FromImportStatement(module='typing', name='List', alias=None, level=0, line=1, col_offset=0)
>>> print(stmt)
from typing import List
>>> 
>>> # Wildcard import
>>> stmt = FromImportStatement(module='collections', name='*', level=0)
>>> print(stmt)
from collections import *
>>> stmt.is_wildcard
True
>>> 
>>> # Relative import
>>> stmt = FromImportStatement(module='module', name='func', level=2)
>>> print(stmt)
from ..module import func
>>> stmt.is_relative
True
__str__() str[source]

Return a Python-readable representation of the from-import statement.

This method constructs a string representation that includes relative import dots, module path, imported name, and optional alias. It correctly handles all import variations including relative imports and wildcards.

Returns:

A string representation of the from-import statement

Return type:

str

Example:

>>> stmt = FromImportStatement(module='typing', name='List', level=0)
>>> str(stmt)
'from typing import List'
>>> 
>>> # With alias
>>> stmt = FromImportStatement(module='typing', name='Dict', alias='D', level=0)
>>> str(stmt)
'from typing import Dict as D'
>>> 
>>> # Relative import
>>> stmt = FromImportStatement(module='module', name='func', level=2)
>>> str(stmt)
'from ..module import func'
>>> 
>>> # Wildcard import (no alias allowed)
>>> stmt = FromImportStatement(module='collections', name='*', level=0)
>>> str(stmt)
'from collections import *'
check_ignore_or_not(min_last_month_downloads: int = 1000000, ignore_modules: Iterable[str] | None = None, no_ignore_modules: Iterable[str] | None = None) bool[source]

Determine whether this from-import should be ignored in analysis or documentation.

This method checks various criteria to decide if a from-import statement should be excluded from analysis. The logic differs from regular imports in that relative imports are never ignored since they refer to project-internal modules.

Parameters:
  • min_last_month_downloads (int, optional) – Minimum monthly download threshold for considering a package as “hot” and ignorable, defaults to 1000000

  • ignore_modules (Optional[Iterable[str]], optional) – Iterable of module names that should always be ignored

  • no_ignore_modules (Optional[Iterable[str]], optional) – Iterable of module names that should never be ignored regardless of other criteria

Returns:

True if the import should be ignored, False if it should be included

Return type:

bool

Note

The logic for ignoring from-imports:

  • Relative imports are never ignored (they’re project-internal)

  • Modules in ignore_modules are always ignored

  • Modules in no_ignore_modules are never ignored

  • Unknown/unimportable modules are ignored

  • Standard library modules are ignored

  • Popular third-party packages (hot projects) are ignored

  • Less popular third-party packages are not ignored

Example:

>>> # Relative import - never ignored
>>> stmt = FromImportStatement(module='module', name='func', level=1)
>>> stmt.check_ignore_or_not()
False
>>> 
>>> # Popular package - should be ignored
>>> stmt = FromImportStatement(module='requests', name='get', level=0)
>>> stmt.check_ignore_or_not(min_last_month_downloads=1000000)
True
>>> 
>>> # Force inclusion with no_ignore_modules
>>> stmt.check_ignore_or_not(no_ignore_modules={'requests'})
False
>>> 
>>> # Standard library module
>>> stmt = FromImportStatement(module='os', name='path', level=0)
>>> stmt.check_ignore_or_not()
True
property is_relative: bool

Check if this is a relative import statement.

A relative import is one that uses dots to indicate the current and parent packages (e.g., from . import module or from ..package import func), or has no module specified which implies the current package.

Returns:

True if this is a relative import, False otherwise

Return type:

bool

Example:

>>> # Absolute import
>>> stmt = FromImportStatement(module='typing', name='List', level=0)
>>> stmt.is_relative
False
>>> 
>>> # Relative import with level
>>> stmt = FromImportStatement(module='module', name='func', level=1)
>>> stmt.is_relative
True
>>> 
>>> # Current package import
>>> stmt = FromImportStatement(module='', name='func', level=1)
>>> stmt.is_relative
True
property is_wildcard: bool

Check if this is a wildcard import statement.

A wildcard import is one that uses ‘*’ to import all public names from a module, such as from module import *. This is generally discouraged in Python but is sometimes used for convenience.

Returns:

True if this is a wildcard import, False otherwise

Return type:

bool

Warning

Wildcard imports can pollute the namespace and make code harder to understand and maintain. They should be used sparingly.

Example:

>>> # Wildcard import
>>> stmt = FromImportStatement(module='collections', name='*', level=0)
>>> stmt.is_wildcard
True
>>> 
>>> # Regular import
>>> stmt = FromImportStatement(module='typing', name='List', level=0)
>>> stmt.is_wildcard
False

ImportVisitor

class hbllmutils.meta.code.imp.ImportVisitor[source]

Custom AST visitor class for collecting import information from Python code.

This class extends ast.NodeVisitor to traverse the Abstract Syntax Tree and collect all import statements (both regular imports and from-imports) found in the code. It handles all import variations including aliases, relative imports, and wildcard imports.

Variables:

imports (List[ImportStatementTyping]) – List of collected import statements

Note

The visitor collects imports in the order they appear in the source code, preserving line numbers and column offsets for each import.

Example:

>>> code = '''
... import os
... import sys as system
... from typing import List, Dict
... from collections import *
... '''
>>> tree = ast.parse(code)
>>> visitor = ImportVisitor()
>>> visitor.visit(tree)
>>> len(visitor.imports)
5
>>> print(visitor.imports[0])
import os
>>> print(visitor.imports[2])
from typing import List
>>> visitor.imports[4].is_wildcard
True
__init__()[source]

Initialize the ImportVisitor.

Creates an empty list to store collected import statements during AST traversal.

Example:

>>> visitor = ImportVisitor()
>>> len(visitor.imports)
0
visit_Import(node: Import) None[source]

Visit an Import node in the AST.

This method is called automatically when an import statement is encountered during AST traversal. It extracts information about each imported module and creates ImportStatement objects with position information.

Parameters:

node (ast.Import) – The Import AST node to visit

Note

A single import statement can import multiple modules (e.g., import os, sys), so this method may create multiple ImportStatement objects from a single node.

Example:

>>> code = "import os, sys as system"
>>> tree = ast.parse(code)
>>> visitor = ImportVisitor()
>>> visitor.visit(tree)
>>> len(visitor.imports)
2
>>> print(visitor.imports[0])
import os
>>> print(visitor.imports[1])
import sys as system
visit_ImportFrom(node: ImportFrom) None[source]

Visit an ImportFrom node in the AST.

This method is called automatically when a from-import statement is encountered during AST traversal. It extracts information about each imported name and creates FromImportStatement objects. This includes support for wildcard imports (from module import *) and relative imports.

Parameters:

node (ast.ImportFrom) – The ImportFrom AST node to visit

Note

A single from-import statement can import multiple names (e.g., from typing import List, Dict), so this method may create multiple FromImportStatement objects from a single node.

Example:

>>> code = '''
... from typing import List, Dict as D
... from collections import *
... from ..module import func
... '''
>>> tree = ast.parse(code)
>>> visitor = ImportVisitor()
>>> visitor.visit(tree)
>>> len(visitor.imports)
4
>>> print(visitor.imports[0])
from typing import List
>>> print(visitor.imports[1])
from typing import Dict as D
>>> visitor.imports[2].is_wildcard
True
>>> visitor.imports[3].is_relative
True

analyze_imports

hbllmutils.meta.code.imp.analyze_imports(code_text: str) List[ImportStatement | FromImportStatement][source]

Analyze Python code text and extract all import statements.

This function parses the provided Python source code using the AST module and collects all import statements (both regular imports and from-imports), including wildcard imports and relative imports. It returns a comprehensive list of all imports with their position information.

Parameters:

code_text (str) – The Python source code to analyze

Returns:

A list of all import statements found in the code, in order of appearance

Return type:

List[ImportStatementTyping]

Raises:

SyntaxError – If the code_text contains invalid Python syntax

Note

The function preserves the order of imports as they appear in the source code and includes detailed position information (line number and column offset) for each import statement.

Warning

The code_text must be syntactically valid Python code. If it contains syntax errors, a SyntaxError will be raised during parsing.

Example:

>>> code = '''
... import os
... import sys as system
... from typing import List, Dict
... from ..module import func
... from collections import *
... '''
>>> imports = analyze_imports(code)
>>> len(imports)
6
>>> 
>>> # Check first import
>>> print(imports[0])
import os
>>> imports[0].line
2
>>> 
>>> # Check from-import
>>> print(imports[2])
from typing import List
>>> 
>>> # Check wildcard import
>>> print(imports[5])
from collections import *
>>> imports[5].is_wildcard
True
>>> 
>>> # Check relative import
>>> imports[4].is_relative
True
>>> 
>>> # Handle syntax error
>>> try:
...     analyze_imports("import os as")
... except SyntaxError as e:
...     print("Syntax error detected")
Syntax error detected