o
    ;i7                     @   sR  d Z ddlZddlZddlZddlZddlZddlZddlmZ ddlm	Z	 ddl
mZ ddlmZmZmZ ddlZddlmZ ddlmZ dd	lmZmZ dd
lmZ ddlmZmZ ddlmZ ddlmZ ej	G dd dZ d?de!de"de fddZ#dZ$d@de de!fddZ%e	ddG dd dZ&eee&ef Z'e	ddG d d! d!Z(G d"d# d#Z)d$e*e!ej+f de,e( fd%d&Z-		dAd'e,e( d(e!d)e"d*e"de,e( f
d+d,Z.d-e!fd.d/Z/d@de de!defd0d1Z0d-e de!ddfd2d3Z1d4e'defd5d6Z2ddd7de de!de3ee' e,e( f fd8d9Z4d'e,e( d:e!d;e"d<e"dee' f
d=d>Z5dS )BzLoad or import Python modules from the CLI.

For example, the function reference of `modal run some_file.py::app.foo_func`
or the app lookup of `modal deploy some_file.py`.

These functions are only called by the Modal CLI, not in tasks.
    N)defaultdict)	dataclass)Path)OptionalUnioncast)Markdown)deprecation_warning)AppLocalEntrypoint)Cls)InvalidError_CliUserExecutionError)Function)OutputManagerc                   @   s2   e Zd ZU eed< eed< ejddZeed< dS )	ImportReffile_or_moduleuse_module_mode )defaultobject_pathN)	__name__
__module____qualname__str__annotations__booldataclassesfieldr    r   r   I/home/ubuntu/.local/lib/python3.10/site-packages/modal/cli/import_refs.pyr       s   
 r   F
object_refr   returnc                 C   sT   |  ddkr| dd\}}n|  ddkrtd|  d| d}}t|||S )Nz::   :zInvalid object reference: z#. Did you mean '::' instead of ':'?r   )findsplitr   r   )r!   r   r   r   r   r   r    parse_import_ref-   s   
r'   appr   
import_refbase_cmdc              
   C   sX  dt jvrt jdd | jdr| jrC| js'tdd| d| j ddd	 z	t| j}W |S  t	yB } zt
| j|d }~ww t| j }d
|jdv r[td|jdt jdt|j t| j}|d usqJ tj|| j}|d usJ tj|}|t j|< z|jsJ |j| W |S  t	y } zt
t||d }~ww )Nr   r   z.py)i        z\Using Python module paths will require using the -m flag in a future version of Modal.
Use `z -m z
` instead.F)show_source.zInvalid Modal source filename: z?.

Source filename cannot contain additional period characters.)syspathinsertr   endswithr   r	   	importlibimport_module	Exceptionr   r   resolvenameremovesuffixr   r   parentinspectgetmodulenameutilspec_from_file_locationmodule_from_specmodulesloaderexec_module)r)   r*   moduleexc	full_pathmodule_namespecr   r   r    import_file_or_module;   sP   


rG   T)frozenc                   @   s"   e Zd ZU dZeed< eed< dS )MethodReferencez]This helps with deferring method reference until after the class gets instantiated by the CLIclsmethod_nameN)r   r   r   __doc__r   r   r   r   r   r   r    rI   i   s   
 rI   c                   @   s2   e Zd ZU ee ed< eed< eed< eed< dS )
CLICommandnamesrunnableis_web_endpointpriorityN)	r   r   r   listr   r   Runnabler   intr   r   r   r    rM   t   s
   
 rM   c                   @   s   e Zd ZdZdZdZdZdS )AutoRunPriorityr   r#   r+      N)r   r   r   MODULE_LOCAL_ENTRYPOINTMODULE_FUNCTIONAPP_LOCAL_ENTRYPOINTAPP_FUNCTIONr   r   r   r    rU   |   s
    rU   module_membersc              
      s
  t ttttf  dd |  D }tt}tdd |D ]j\}}|j D ]\}}|| | d|  t	j
|< q'|j D ]\}}|j rLqB|| | d|  t	j|< qB|j D ]$\}}	|	 D ]}
t|	|
}|| | d| d|
  t	j|< qkqcqdd |  D }|D ][\}}t|tr| r| D ]}
t||
}||g d| d|
  t	j|< qqt|tr| r||g d| t	j|< qt|tr||g d| t	j|< qdtd	tfd
d  fdd| D S )a{  
    Extracts all runnables found either directly in the input module, or in any of the Apps listed in that module

    Runnables includes all Functions, (class) Methods and Local Entrypoints, including web endpoints.

    The returned list consists of tuples:
    ([name1, name2...], Runnable)

    Where the first name is always the module level name if such a name exists
    c                 S   s"   g | ]\}}t |tr||fqS r   )
isinstancer
   .0r7   memberr   r   r    
<listcomp>   s   " z%list_cli_commands.<locals>.<listcomp>c                   S   s   t jS N)rU   rZ   r   r   r   r    <lambda>   s    z#list_cli_commands.<locals>.<lambda>r.   c                 S   s(   g | ]\}}t |tttfr||fqS r   )r\   r   r   r   r]   r   r   r    r`      s    r   rO   r"   c                 S   s@   t | tr|  rdS t | tr| j | j }| rdS dS )NTF)r\   r   _is_web_endpointrI   rJ   _get_partial_functionsrK   )rO   method_partialr   r   r    rc      s   
z+list_cli_commands.<locals>._is_web_endpointc                    s(   g | ]\}}t || || d qS ))rQ   )rM   )r^   rO   rN   rc   
prioritiesr   r    r`      s    )r   rR   tupler   r
   itemsr   registered_entrypointsappendrU   rY   registered_functionsinfois_service_classrZ   registered_classes_get_method_namesrI   r\   r   	_is_local
setdefaultr1   rX   r   r   rW   rS   r   )r[   appsall_runnablesapp_namer(   r7   local_entrypointfunctioncls_namerJ   rK   
method_refmodule_level_entitiesentityr   rf   r    list_cli_commands   sT   




r|   cli_commandsname_prefixaccept_local_entrypointsaccept_web_endpointsc                    s|   dt dtf fdd}g }| D ]+}||sq|jv r"|| qs*|| qfdd|jD }|r;|| q|S )zeFilters by name and type of runnable

    Returns generator of (matching names list, CLICommand)
    cli_commandr"   c                    s&    s
t | jtr
dS s| jrdS dS )NFT)r\   rO   r   rP   )r   )r   r   r   r    _is_accepted_type   s
   
z.filter_cli_commands.<locals>._is_accepted_typec                    s    g | ]}|   d r|qS )r.   )
startswith)r^   x)r~   r   r    r`      s     z'filter_cli_commands.<locals>.<listcomp>)rM   r   rN   rk   )r}   r~   r   r   r   resr   prefix_matchesr   )r   r   r~   r    filter_cli_commands   s    



r   app_refc                 C   s   t t| S ra   )import_app_from_refr'   )r   r   r   r    
import_app   s   r   c                 C   s   | j }| jpt}t| |}d|v rt| dt||}|d u rPt }|j	d| d| ddd |sKt
dt d	| d
| d}|j	|dd td t|ts]t| d|S )Nr.   z is not a Modal Appz$[bold red]Could not find Modal app 'z' in z.[/bold red]Tstderrz*Expected to find an app variable named **`z`** (the default app name). If your `modal.App` is assigned to a different variable name, you must specify it in the app ref argument. For example an App variable `app_2 = modal.App()` in `z` would be specified as `z	::app_2`.r#   )r   r   DEFAULT_APP_NAMErG   click
UsageErrorgetattrr   getprintr   r/   exitr\   r
   )r)   r*   import_pathr   rB   r(   outputguidance_msgr   r   r    r      s2   




r   c                 C   sp   | j }| j}t }|r|jd| d| ddd n|jd| ddd d| d| d	}|j|dd d S )
Nz=[bold red]Could not find Modal function or local entrypoint 'z' in 'z'.[/bold red]Tr   z][bold red]No function was specified, and no [green]`app`[/green] variable could be found in 'z
Usage:
z <file_or_module_path>::<function_name>

Given the following example `app.py`:
```
app = modal.App()

@app.function()
def foo():
    ...
```
You would run foo as [bold green]z app.py::foo[/bold green])r   r   r   r   r   )r   r*   r   r   r   r   r   r   r    _show_function_ref_help  s0   r   rO   c                 C   s8   t | tr| jS t | tr| j S t | tsJ | jS ra   )r\   r   r(   rI   rJ   _get_appr   )rO   r   r   r    _get_runnable_app=  s   


r   )accept_local_entrypointaccept_webhookc                C   sN   t | |}ttt|}t|d||}t|| j||}|r#||fS d|fS )aZ  Takes a function ref string and returns a single determined "runnable" to use, and a list of all available
    runnables.

    The function ref can leave out partial information (apart from the file name/module)
    as long as the runnable is uniquely identifiable by the provided information.

    When there are multiple runnables within the provided ref, the following rules should
    be followed:

    1. if there is a single local_entrypoint, that one is used
    2. if there is a single {function, class} that one is used
    3. if there is a single method (within a class) that one is used
    r   N)rG   r|   dictr:   
getmembersr   infer_runnabler   )r)   r*   r   r   rB   r}   all_usable_commandsinferred_runnabler   r   r    import_and_filterG  s   
r   r   r   r   c           
      C   sn   t | |||}t|dkrd S tt}|D ]
}||j | qt| \}}t|dkr5|d }	|	jS d S )Nr   r#   )	r   lenr   rR   rQ   rk   minri   rO   )
r}   r   r   r   filtered_commandsfiltered_commands_by_priocmd_highest_prio_commandsr   r   r   r    r   h  s   r   )F)r   )TT)6rL   r   r3   importlib.utilr:   r/   typingcollectionsr   r   pathlibr   r   r   r   r   rich.markdownr   modal._utils.deprecationr	   	modal.appr
   r   	modal.clsr   modal.exceptionr   r   modal.functionsr   modal.outputr   r   r   r   r'   r   rG   rI   rS   rM   rU   r   AnyrR   r|   r   r   r   r   r   rh   r   r   r   r   r   r    <module>   s   .
J
(& 
!