Skip to content

patch

lazyllm.patch.LazyPatchFinder

Bases: MetaPathFinder

Lazy Patch Finder for intercepting specific module imports and applying patches.

The LazyPatchFinder is a meta path finder that intercepts import requests for 'requests' and 'httpx' modules during the import process, and uses a custom LazyPatchLoader to load these modules, automatically applying patches during module loading.

Note:

  • This finder only takes effect when modules are not already imported
  • If modules are already imported, directly calls patch_requests_and_httpx() function
  • Maintains the original attributes and paths of the modules
Source code in lazyllm/patch.py
class LazyPatchFinder(importlib.abc.MetaPathFinder):
    """Lazy Patch Finder for intercepting specific module imports and applying patches.

The ``LazyPatchFinder`` is a meta path finder that intercepts import requests for 
'requests' and 'httpx' modules during the import process, and uses a custom 
LazyPatchLoader to load these modules, automatically applying patches during module loading.

**Note:**

- This finder only takes effect when modules are not already imported
- If modules are already imported, directly calls patch_requests_and_httpx() function
- Maintains the original attributes and paths of the modules
"""
    def find_spec(self, fullname, path, target=None):
        """Find and return the module specification object for custom module loading process.

This method is the core method of MetaPathFinder, responsible for finding the specification 
object of the specified module during the import process. In LazyPatchFinder, it specifically 
intercepts import requests for 'requests' and 'httpx' modules, using a custom LazyPatchLoader 
to wrap the original module specification.

Args:
    fullname (str): The full name of the module to import
    path (list): Search path list, None for top-level modules
    target (module, optional): Target module object (used during reloading)

**Returns:**

- For 'requests' and 'httpx' modules: Returns module specification wrapped with LazyPatchLoader
- For other modules: Returns None, allowing other finders to continue processing

"""
        if fullname in LazyPatchLoader.PATCHS and fullname not in LazyPatchLoader.PATCHED:
            if self in sys.meta_path: sys.meta_path.remove(self)
            original_spec = importlib.util.find_spec(fullname)
            if len(LazyPatchLoader.PATCHS) > len(LazyPatchLoader.PATCHED) + 1:
                sys.meta_path.insert(0, self)
            if original_spec is None: return None
            return importlib.util.spec_from_loader(fullname, LazyPatchLoader(original_spec, fullname),
                                                   origin=original_spec.origin)
        return None

find_spec(fullname, path, target=None)

Find and return the module specification object for custom module loading process.

This method is the core method of MetaPathFinder, responsible for finding the specification object of the specified module during the import process. In LazyPatchFinder, it specifically intercepts import requests for 'requests' and 'httpx' modules, using a custom LazyPatchLoader to wrap the original module specification.

Parameters:

  • fullname (str) –

    The full name of the module to import

  • path (list) –

    Search path list, None for top-level modules

  • target (module, default: None ) –

    Target module object (used during reloading)

Returns:

  • For 'requests' and 'httpx' modules: Returns module specification wrapped with LazyPatchLoader
  • For other modules: Returns None, allowing other finders to continue processing
Source code in lazyllm/patch.py
    def find_spec(self, fullname, path, target=None):
        """Find and return the module specification object for custom module loading process.

This method is the core method of MetaPathFinder, responsible for finding the specification 
object of the specified module during the import process. In LazyPatchFinder, it specifically 
intercepts import requests for 'requests' and 'httpx' modules, using a custom LazyPatchLoader 
to wrap the original module specification.

Args:
    fullname (str): The full name of the module to import
    path (list): Search path list, None for top-level modules
    target (module, optional): Target module object (used during reloading)

**Returns:**

- For 'requests' and 'httpx' modules: Returns module specification wrapped with LazyPatchLoader
- For other modules: Returns None, allowing other finders to continue processing

"""
        if fullname in LazyPatchLoader.PATCHS and fullname not in LazyPatchLoader.PATCHED:
            if self in sys.meta_path: sys.meta_path.remove(self)
            original_spec = importlib.util.find_spec(fullname)
            if len(LazyPatchLoader.PATCHS) > len(LazyPatchLoader.PATCHED) + 1:
                sys.meta_path.insert(0, self)
            if original_spec is None: return None
            return importlib.util.spec_from_loader(fullname, LazyPatchLoader(original_spec, fullname),
                                                   origin=original_spec.origin)
        return None

lazyllm.patch.LazyPatchLoader

Bases: Loader

Lazy Patch Loader for automatically applying patches during module loading.

The LazyPatchLoader is an import system loader that automatically applies patches to the requests and httpx libraries when a module is executed. This loader wraps the original module specification and automatically calls patch functions after module execution.

Parameters:

  • original_spec (ModuleSpec) –

    The original module's specification object containing module loading information and paths.

Features:

  • Automatically sets correct package and path attributes during module loading
  • Executes the original loader's module execution logic
  • Automatically applies patches to requests and httpx libraries after module execution
Source code in lazyllm/patch.py
class LazyPatchLoader(importlib.abc.Loader):
    """Lazy Patch Loader for automatically applying patches during module loading.

The ``LazyPatchLoader`` is an import system loader that automatically applies patches 
to the requests and httpx libraries when a module is executed. This loader wraps the 
original module specification and automatically calls patch functions after module execution.

Args:
    original_spec (ModuleSpec): The original module's specification object containing 
                                module loading information and paths.

Features:

- Automatically sets correct package and path attributes during module loading
- Executes the original loader's module execution logic
- Automatically applies patches to requests and httpx libraries after module execution

"""
    PATCHS = {
        'httpx': patch_httpx,
    }
    PATCHED = set()

    def __init__(self, original_spec, package_name):
        self.original_spec = original_spec
        self._package_name = package_name

    def create_module(self, spec):
        return None

    def exec_module(self, module):
        """Execute the module loading and initialization process.

This method is the core method of the import system loader, responsible for executing 
the module's code and initializing the module object. In LazyPatchLoader, this method 
first sets the module's package and path attributes, then executes the original loader's 
module execution logic, and finally automatically applies patches to the requests and 
httpx libraries.

Args:
    module (ModuleType): The module object to be executed.

"""
        if self.original_spec.submodule_search_locations is not None:
            module.__package__ = self.original_spec.name
        elif '.' in self.original_spec.name:
            module.__package__ = self.original_spec.name.rpartition('.')[0]
        else:
            module.__package__ = ''

        if self.original_spec.submodule_search_locations is not None:
            module.__path__ = self.original_spec.submodule_search_locations

        self.original_spec.loader.exec_module(module)
        LazyPatchLoader.PATCHS[self._package_name]()
        LazyPatchLoader.PATCHED.add(self._package_name)

exec_module(module)

Execute the module loading and initialization process.

This method is the core method of the import system loader, responsible for executing the module's code and initializing the module object. In LazyPatchLoader, this method first sets the module's package and path attributes, then executes the original loader's module execution logic, and finally automatically applies patches to the requests and httpx libraries.

Parameters:

  • module (ModuleType) –

    The module object to be executed.

Source code in lazyllm/patch.py
    def exec_module(self, module):
        """Execute the module loading and initialization process.

This method is the core method of the import system loader, responsible for executing 
the module's code and initializing the module object. In LazyPatchLoader, this method 
first sets the module's package and path attributes, then executes the original loader's 
module execution logic, and finally automatically applies patches to the requests and 
httpx libraries.

Args:
    module (ModuleType): The module object to be executed.

"""
        if self.original_spec.submodule_search_locations is not None:
            module.__package__ = self.original_spec.name
        elif '.' in self.original_spec.name:
            module.__package__ = self.original_spec.name.rpartition('.')[0]
        else:
            module.__package__ = ''

        if self.original_spec.submodule_search_locations is not None:
            module.__path__ = self.original_spec.submodule_search_locations

        self.original_spec.loader.exec_module(module)
        LazyPatchLoader.PATCHS[self._package_name]()
        LazyPatchLoader.PATCHED.add(self._package_name)