o
    i                     @   s~   d Z ddlmZmZ ddlmZmZmZmZ ddl	m
Z
mZmZmZ ddlmZ ddlmZ G dd	 d	eZG d
d dZdS )a
  Generic handler resolution logic for container standards.

This module provides a reusable template for resolving handlers with a consistent
priority order across different container types (SageMaker, etc.).

## Handler Resolution Priority Order

1. **Environment variable** specified function
2. **Registry** @decorated function
3. **Customer script** function
4. **Default** handler (if any)

## Usage Examples

```python
from model_hosting_container_standards.handler_resolver import GenericHandlerResolver

# Define handler-specific configuration
class MyHandlerConfig:
    def get_env_handler(self, handler_type: str):
        # Return handler from environment variable
        pass

    def get_customer_script_handler(self, handler_type: str):
        # Return handler from customer script
        pass

# Create resolver with configuration
resolver = GenericHandlerResolver(MyHandlerConfig())

# Resolve specific handlers
ping_handler = resolver.resolve_handler("ping")
invoke_handler = resolver.resolve_handler("invoke")
```
    )ABCabstractmethod)AnyCallableOptionalUnion)HandlerFileNotFoundErrorHandlerNotFoundErrorHandlerResolutionErrorInvalidHandlerSpecError)logger   )handler_registryc                   @   sZ   e Zd ZdZededeedef edf fddZ	edede
edef  fdd	ZdS )
HandlerConfigzAbstract base class for handler configuration.

    Subclasses must implement methods to load handlers from different sources.
    handler_typereturn.Nc                 C      dS )a  Get handler from environment variable.

        Args:
            handler_type: Type of handler (e.g., "ping", "invoke")

        Returns:
            Callable: Function handler
            str: Router path
            None: No handler found

        Raises:
            HandlerResolutionError: If env var is set but invalid
            InvalidHandlerSpecError: If handler spec is malformed
        N selfr   r   r   m/home/ubuntu/.local/lib/python3.10/site-packages/model_hosting_container_standards/common/handler/resolver.pyget_env_handler9   s   zHandlerConfig.get_env_handlerc                 C   r   )zGet handler from customer script.

        Args:
            handler_type: Type of handler (e.g., "ping", "invoke")

        Returns:
            Callable function or None if not found
        Nr   r   r   r   r   get_customer_script_handlerM   s   z)HandlerConfig.get_customer_script_handler)__name__
__module____qualname____doc__r   strr   r   r   r   r   r   r   r   r   r   r   3   s    r   c                   @   s|   e Zd ZdZddeddfddZdedee fdd	Z	dedee fd
dZ
dedee fddZdedee fddZdS )GenericHandlerResolverzGeneric handler resolver that implements consistent priority order.

    The resolver uses a clean separation of concerns with individual methods
    for each resolution step, making the code more maintainable and testable.
    Nconfigr   c                 C   s   || _ |pt| _dS )zInitialize the handler resolver.

        Args:
            config: Handler configuration for loading from different sources
            registry: Handler registry (defaults to global registry)
        N)r   r   registry)r   r   r    r   r   r   __init__c   s   zGenericHandlerResolver.__init__r   c              	   C   s   z/| j |}t|r!t|dt|}td| d|  |W S |r.td| d|  W n tt	fyB   t
d| d  w td| d	 d
S )a[  Try to resolve handler from environment variable.

        Args:
            handler_type: Type of handler to resolve

        Returns:
            Handler function if found, None otherwise

        Raises:
            HandlerResolutionError: If env var is set but invalid
            InvalidHandlerSpecError: If handler spec is malformed
        r   z
Found env 
 handler: zEnv z handler is router path: zEnvironment variable z handler configuration errorzNo env  handler foundN)r   r   callablegetattrr   r   infodebugr
   r   error)r   r   env_handlerhandler_namer   r   r   _try_env_handlerm   s&   
z'GenericHandlerResolver._try_env_handlerc                 C   sP   | j |}|rt|dt|}td| d|  |S td| d dS )zTry to resolve handler from registry decorators.

        Args:
            handler_type: Type of handler to resolve

        Returns:
            Handler function if found, None otherwise
        r   zFound decorator r"   zNo decorator r#   N)r    get_decorator_handlerr%   r   r   r'   )r   r   decorated_handlerr*   r   r   r   _try_decorator_handler   s   	
z-GenericHandlerResolver._try_decorator_handlerc              
   C   s   z | j |}|rt|dt|}td| d|  |W S W n2 ttfyB } ztd| dt|j	  W Y d}~nd}~w t
yR   td| d  w td	| d
 dS )zTry to resolve handler from customer script.

        Args:
            handler_type: Type of handler to resolve

        Returns:
            Handler function if found, None otherwise
        r   zFound customer module z: zNo customer script z function found: NzCustomer script z function failed to loadzNo customer module z found)r   r   r%   r   r   r'   r   r	   typer   	Exceptionr(   )r   r   customer_handlerr*   er   r   r   _try_customer_script_handler   s(   	
z3GenericHandlerResolver._try_customer_script_handlerc                 C   sR   t d| d | j| j| jfD ]}||}|r|  S qt d| d dS )a  
        Resolve handler with priority order:
        1. Environment variable specified function
        2. Registry @decorated function
        3. Customer script function
        4. Default handler registered by the framework

        Args:
            handler_type: Type of handler to resolve (e.g., "ping", "invoke")

        Returns:
            Resolved handler function or None if not found
        resolve_z_handler calledzNo z handler found anywhereN)r   r'   r+   r.   r3   )r   r   resolver_methodhandlerr   r   r   resolve_handler   s   	z&GenericHandlerResolver.resolve_handler)N)r   r   r   r   r   r!   r   r   r   r+   r.   r3   r7   r   r   r   r   r   \   s    
$r   N)r   abcr   r   typingr   r   r   r   ,model_hosting_container_standards.exceptionsr   r	   r
   r   0model_hosting_container_standards.logging_configr   r    r   r   r   r   r   r   r   <module>   s    $)