o
    i                     @   s   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Zd dlZd dl	Z	d dl
mZ d dlmZmZmZmZ G dd dZG dd dZdd	ed
efddZdS )    N)Enum)Optional
get_originget_argsget_type_hintsc                   @   s6   e Zd ZdZdd Zdd Zdedee fdd	Zd
S )TypeTrackerzOTracks types discovered during stub generation for automatic import generation.c                 C   s   i | _ h d| _t | _d S )N>   AnySetintsetstrDictListNoneboolcastdictlisttypeTupleUnionbytesfloattupleobjectr   Sequence
NamedTuple)discovered_typesbuiltin_typesr   already_imported)self r!   >/mnt/c/Users/fbmor/ComfyUI/comfy_api/internal/async_to_sync.py__init__   s   
zTypeTracker.__init__c                 C   s   |du s
|t du rdS t|dd}|r || jv s|| jv r dS t|dd}t|d|p,d}|dkr4dS |dkr>|dv r>dS |rO|d	vrQ|rS||f| j|< dS dS dS dS )
z:Track a type annotation and record its module/import info.N__name__
__module____qualname__ typingtypes)	UnionTypeGenericAlias)builtins__main__)r   getattrr   r   r   )r    
annotation	type_namemodulequalnamer!   r!   r"   
track_type/   s"   zTypeTracker.track_typemain_module_namereturnc                 C   s   g }i }t | j D ]"\}\}}|r||krq||vr g ||< ||| vr-|| | qt | D ]*\}}t|dkrL|d| d|d   q4|d| ddt t|  q4|S )z4Generate import statements for all discovered types.   from  import r   , )sortedr   itemsappendlenjoinr   )r    r4   importsimports_by_moduler0   r1   r2   r)   r!   r!   r"   get_importsL   s   &zTypeTracker.get_importsN)	r$   r%   r&   __doc__r#   r3   r   r   rA   r!   r!   r!   r"   r      s
    r   c                   @   s  e Zd ZU dZdZeejj e	d< e
 ZdZed2dejjfddZedd	 Zed3dedefddZe	d2dee defddZedd ZedefddZe			d4dejdedee dee def
ddZe		d5dededee defddZedededee fdd Zededee eef  fd!d"Z!e	#	d6d$ed%ed&edee dee f
d'd(Z"e	#d7d)ed&edee fd*d+Z#ed,ee dee fd-d.Z$eded/eddfd0d1Z%dS )8AsyncToSyncConverterz]
    Provides utilities to convert async classes to sync classes with proper type hints.
    N_thread_poolFr5   c                 C   sv   | j r| jdusJ d| jS | j | j s"tjj|dd| _d| _ W d   n1 s,w   Y  | jdus8J | jS )zLGet or create the shared thread pool with proper thread-safe initialization.Nz!Thread pool should be initializedasync_to_sync_)max_workersthread_name_prefixT)_thread_pool_initializedrD   _thread_pool_lock
concurrentfuturesThreadPoolExecutor)clsrF   r!   r!   r"   get_thread_pooln   s   z$AsyncToSyncConverter.get_thread_poolc                    s\   t  ddd fdd}|  }||}|  d dur*d d S )z
        Run an async function in a separate thread from the thread pool.
        Blocks until the async function completes.
        Properly propagates contextvars between threads and manages event loops.
        N)result	exceptionc                     s6  t  } t |  z`z fdd}| j| }|d< W n ty6 } z
|d< W Y d }~nd }~ww W zt | }|D ]}|  q@|rT| t j|ddi W n	 ty^   Y nw | 	  t d  d S zt | }|D ]}|  qr|r| t j|ddi W n	 ty   Y nw | 	  t d  w )Nc                      s    i I d H S Nr!   r!   )args	coro_funckwargsr!   r"   run_with_context   s   zYAsyncToSyncConverter.run_async_in_thread.<locals>.run_in_thread.<locals>.run_with_contextrO   rP   return_exceptionsT)
asyncionew_event_loopset_event_looprunrun_until_complete	Exception	all_taskscancelgatherclose)looprU   rO   ependingtaskrR   contextrS   rT   result_containerr!   r"   run_in_thread   sN   




z?AsyncToSyncConverter.run_async_in_thread.<locals>.run_in_threadrP   rO   )contextvarscopy_contextrN   submitrO   )rM   rS   rR   rT   rh   thread_poolfuturer!   re   r"   run_async_in_thread   s   
)
z(AsyncToSyncConverter.run_async_in_thread
   async_classc                    s   d} |  j j| d} fdd}||d< tj tjdD ]0\}}|dr-q#t|rCt	||dd	d
}|||< q#t	||ddd}	|	||< q#t dd D ]\}}
dd }|||
||< q\t
|tf|}|S )a#  
        Creates a new class with synchronous versions of all async methods.

        Args:
            async_class: The async class to convert
            thread_pool_size: Size of thread pool to use

        Returns:
            A new class with sync versions of all async methods
        ComfyAPISyncStub)rB   r%   r&   __orig_class__c                    sz   |i || _ zt }W n  ty.   i }tt D ]}t|dr+||j qY nw |	 D ]\}}t| j |rt
| j |}t|drddlm} t||ryz|j}	t|	}
||
_ t| ||
 W q3 tyx   t| || Y q3w t| || q3t|trt |jrt
 |j}ddlm} z)t||r| }n| }|}	t|	}
||
_ t| ||
 t| j || W q3 ty } ztd| d|  W Y d }~q3d }~ww q3t| j D ]U\}}|dst| |rqt|tr:t|tttttt t!fs:ddlm} t||r:z|j}	t|	}
||
_ t| ||
 W q ty9   t| || Y qw qd S )N__annotations__	__class__r   )ProxiedSingletonzFailed to create instance for : _)"_async_instancer   r\   reversedinspectgetmrohasattrupdaters   r;   r.   comfy_api.internal.singletonru   
isinstancecreate_sync_classrt   r   __new__setattrr   r$   
issubclassget_instanceloggingwarning
getmembers
startswithr   r
   r   r   r   r   r   )r    rR   rT   all_annotations
base_class	attr_name	attr_typeattrru   sync_attr_class	sync_attrinner_classasync_instancerb   namerp   rM   r!   r"   r#      s   
	








z8AsyncToSyncConverter.create_sync_class.<locals>.__init__r#   	predicaterw   )_method_namec                _   s$   t | j|}tj|g|R i |S rQ   )r.   rx   rC   rn   )r    r   rR   rT   async_methodr!   r!   r"   sync_methodD  s   z;AsyncToSyncConverter.create_sync_class.<locals>.sync_methodc                _   s   t | j|}||i |S rQ   )r.   rx   )r    r   rR   rT   methodr!   r!   r"   proxy_methodO  s   z<AsyncToSyncConverter.create_sync_class.<locals>.proxy_methodc                 S   
   t | tS rQ   r   propertyxr!   r!   r"   <lambda>Y     
 z8AsyncToSyncConverter.create_sync_class.<locals>.<lambda>c                    s.    fdd} fdd}t ||jr|S d S )Nc                    s*   t | j t r fdd}|S  S )Nc                     s   t j g| R i |S rQ   )rC   rn   )rR   rT   valuer!   r"   sync_fna  s   z^AsyncToSyncConverter.create_sync_class.<locals>.make_property.<locals>.getter.<locals>.sync_fn)r.   rx   rz   iscoroutinefunction)r    r   r   r   r"   getter]  s
   
zMAsyncToSyncConverter.create_sync_class.<locals>.make_property.<locals>.getterc                    s   t | j | d S rQ   )r   rx   )r    r   r   r!   r"   setteri  s   zMAsyncToSyncConverter.create_sync_class.<locals>.make_property.<locals>.setter)r   fset)r   prop_objr   r   r!   r   r"   make_property\  s   z=AsyncToSyncConverter.create_sync_class.<locals>.make_property)rN   rB   r%   rz   r   
isfunctionr   r   	functoolswrapsr   r   )rM   rp   thread_pool_sizesync_class_namesync_class_dictr#   r   r   r   r   propr   
sync_classr!   r   r"   r      s8   
]



z&AsyncToSyncConverter.create_sync_classtype_trackerc           
   	   C   s  |t jju s|t jju rdS |tdu rdS |r|| z\t|}t|}|durx|r1|| t|dt	|}d|v rD|
dd }t	|dksN|dkrPd	}|rug }|D ]}|r_|| || || qV| d
d| dW S |W S W n ttfy   Y nw t|drt|dr|j}t|dr|jnt	|
dd }g }|jD ]}|| || q| d
d| dS t|dr|jS t|drt|dr|jS t	|}|dr|dr|dd }dD ]}	||	r|t|	d }q|dv rdS |dkrdS |S )zFConvert a type annotation to its string representation for stub files.r   Nr   r$   .z<class 'types.UnionType'>r*   r   [r9   ]
__origin____args__'r6   r%   r&   z<class 'z'>   )ztyping.z	builtins.ztypes.)_emptyzinspect._emptyNoneType)rz   	Parameterempty	Signaturer   r3   r   r   r.   r   splitr<   _format_type_annotationr>   AttributeError	TypeErrorr|   r   r$   r   r&   r   endswithr=   )
rM   r/   r   originrR   origin_nameformatted_argsargtype_strprefixr!   r!   r"   r   u  sp   







z,AsyncToSyncConverter._format_type_annotationc                 C   s&   t |drt|jdkr|jd S |S )z;Extract the actual return type from a Coroutine annotation.r      )r|   r=   r   )rM   r/   r!   r!   r"   _extract_coroutine_return_type  s   
z3AsyncToSyncConverter._extract_coroutine_return_typec                 C   sR   |t jju rdS |du rdS t|trd| S |i krdS |g kr$dS d| S )z2Format a parameter's default value for stub files.r'   Nz = Nonez = z = {}z = [])rz   r   r   r   r   )rM   default_valuer!   r!   r"   _format_parameter_default  s   


z.AsyncToSyncConverter._format_parameter_defaultTsig	skip_self
type_hintsc                 C   s   g }|du ri }t |j D ]F\}\}}|dkr%|dkr%|r%|d q|||j}	| |	|}
| |j}|	t	j
ju rI|| d|  q|| d|
 |  qd|S )z(Format method parameters for stub files.Nr   r    z: Anyrv   r9   )	enumerate
parametersr;   r<   getr/   r   r   defaultrz   r   r   r>   )rM   r   r   r   r   paramsi
param_nameparamr/   r   default_strr!   r!   r"   _format_method_parameters  s   	
z.AsyncToSyncConverter._format_method_parametersmethod_nameis_asyncc                 C   s   t |}zddlm} ||}W n ty   i }Y nw |d|j}|r0t |r0| |}| j	|||d}	| 
||}
|t jju rFd}
d| d|	 d|
 d	S )
z4Generate a complete method signature for stub files.r   r   r5   r   r   r   def () -> : ...)rz   	signaturer(   r   r\   r   return_annotationr   r   r   r   r   r   )rM   r   r   r   r   r   r   r   r   
params_strreturn_typer!   r!   r"   _generate_method_signature  s   
	
z/AsyncToSyncConverter._generate_method_signaturec                    s  g }| d |jdkrt|}g }|rdt|dd}tt|D ]A\}}t|trc|dur9||vr9||j	vr9q"t
|trOt|drO| | |j| q"t
|trc|dkrc| | |j| q"|r|d|jg| }	| d|j d	|	  n| d|j d	|j  ||j|jd
 tt|drt|j}
d|
v r|
dd  t fdd|D s| d   |S )z-Generate import statements for the stub file.z[from typing import Any, Dict, List, Optional, Tuple, Union, Set, Sequence, cast, NamedTupler,   __all__N_fieldsr   r9   r7   r8   )r4   r$   r   r   c                 3   s     | ]}| d   V  qdS )r7   N)r   ).0impbase_moduler!   r"   	<genexpr>q  s    z9AsyncToSyncConverter._generate_imports.<locals>.<genexpr>import )r<   r%   rz   	getmoduler.   r:   r   r   r   r   r   r   r|   r   addr   r>   r$   extendrA   r   any)rM   rp   r   r?   r1   additional_types
module_allr   objtype_importsmodule_namer!   r   r"   _generate_imports4  sJ   





z&AsyncToSyncConverter._generate_importsc                 C   s   g }zt |}W n ty   i }Y nw tt|D ]*\}}t|tr1|ds1|||f q||v rE|| }t|trE|||f q|S )z5Extract class attributes that are classes themselves.rw   )	r   r\   r:   rz   r   r   r   r   r<   )rM   rp   class_attributesr   r   r   r/   r!   r!   r"   _get_class_attributesv  s   
z*AsyncToSyncConverter._get_class_attributes    r   r   indentc              
   C   s  g }| | d| d t|dr"|jr"|| |j| d t|drzLt|d}t|}zddlm	} ||}	W n t
yI   i }	Y nw | j||	|d}
t|drg|jrg|| |j| d | | d	|
 d
 W n ttfy   | | d Y nw d}ttj|tjdD ]G\}}|drqd}z%|jr|| |j| d | j||d|d}| | d|  W q ttfy   | | d| d Y qw |s| | d |S )z!Generate stub for an inner class.class zSync:rB   r   r#   r   r   r       def __init__() -> None: ...4    def __init__(self, *args, **kwargs) -> None: ...Fr   rw   Tr   r       def (self, *args, **kwargs): ...z    pass)r<   r|   rB   r   _format_docstring_for_stubr.   rz   r   r(   r   r\   r   
ValueErrorr   r:   r   r   r   r   )rM   r   r   r  r   
stub_linesinit_methodinit_sigr   
init_hintsr   has_methodsr   r   
method_sigr!   r!   r"   _generate_inner_class_stub  sr   	



z/AsyncToSyncConverter._generate_inner_class_stub	docstringc                 C   sx   |sg S t | }|d}g }|| d |D ]}| r,|| |  q|d q|| d |S )zHFormat a docstring for inclusion in a stub file with proper indentation.
z"""r'   )textwrapdedentstripr   r<   )rM   r  r  dedentedlinesrO   liner!   r!   r"   r	    s   
z/AsyncToSyncConverter._format_docstring_for_stubstub_contentc                 C   sb   g }|D ]*}| dr|| q|  dr)| dr)d|vr)|dd}|| q|S )z6Post-process stub content to fix any remaining issues.)r7   r   r   r   r   z -> None: ...)r   r<   r  r   replace)rM   r  	processedr  r!   r!   r"   _post_process_stub_content  s   

z/AsyncToSyncConverter._post_process_stub_contentr   c           '   
   C   s$  zc|j dkr
W dS t|}|sW dS |j}|sW dS tj|}tj|d}tj|dd tj	|}|
drA|dd }tj||j d}t }	g }
t|
}|
d	 |
d
|j d |jrq|
| |jd zE|j}t|}zddlm} ||}W n ty   i }Y nw | j|||	d}t|dr|jr|
| |jd |
d| d W n ttfy   |
d Y nw |
d	 | |}|D ]\}}| j|||	d}|
| |
d	 qt }ttj|tj dD ]U\}}|!ds||v rq|"| z&| j#||d|	d}|jr$|
| |jd |
d|  |
d	 W q ttfyL   |
d| d |
d	 Y qw tt|dd D ].\}}|
d |
d| d |j$r|
d| d |
d| d  |
d	 qWi }z||}W n# ty   i }t%t&|D ]}t|d!r|'|j( qY nw t|) D ]-\}}|D ]%\}}||kst|d"r|j|kst*|t+r||kr|||< qq|D ]\}}|,||}|
d| d#| d$ q|
d	 | -||	} t }!g }"| D ]}#|#|!vr%|!"|# |"|# qt./d%|#  q|"|
||d& < | 0|
}
t1|d'}$|$2d(|
 W d   n	1 sUw   Y  t.3d)|  W dS  ty }% z t.4d*|j d#t+|%  ddl5}&t.4|&6  W Y d}%~%dS d}%~%ww )+z_
        Generate a .pyi stub file for the sync class to help IDEs with type checking.
        r-   N	generatedT)exist_okz.pyz.pyir'   r  :r   r   r   r   rB   r  r  r  )r   r   rw   r  r  r  c                 S   r   rQ   r   r   r!   r!   r"   r     r   z9AsyncToSyncConverter.generate_stub_file.<locals>.<lambda>z    @propertyz(self) -> Any: ...z    @z.setterz(self, value: Any) -> None: ...rs   r$   rv   SynczDuplicate import detected: r6   wr  zGenerated stub file: zError generating stub file for )7r%   rz   r   __file__ospathdirnamer>   makedirsbasenamer   r$   r   r=   r<   rB   r   r	  r#   r   r(   r   r\   r   r|   r
  r   r   r  r   r:   r   r   r   r   r   r   ry   r{   r}   rs   r;   r   r   r   r   r   r   r  openwriteinfoerror	traceback
format_exc)'rM   rp   r   r1   module_path
module_dirstub_dirr   sync_stub_pathr   r  imports_placeholder_indexr  init_signaturer   r  r   r   r   r   inner_class_stubprocessed_methodsr   r  r   attribute_mappingsr   r   r   r   
class_name
class_typer?   seenunique_importsr   frb   r.  r!   r!   r"   generate_stub_file  s  
















z'AsyncToSyncConverter.generate_stub_filerQ   ro   )TNN)FN)r   N)r   )&r$   r%   r&   rB   rD   r   rJ   rK   rL   rs   	threadingLockrI   rH   classmethodrN   rn   r   r   r   r   r   r   r   rz   r   r   r   r   r   r   r   r   r   r  r	  r  r>  r!   r!   r!   r"   rC   e   s   
 
@ 2d
!A OrC   ro   rp   r5   c                 C   s   t | |S )z
    Creates a sync version of an async class

    Args:
        async_class: The async class to convert
        thread_pool_size: Size of thread pool to use

    Returns:
        A new class with sync versions of all async methods
    )rC   r   )rp   r   r!   r!   r"   r     s   r   r?  )rW   concurrent.futuresrJ   ri   r   rz   r   r%  r  r@  enumr   r(   r   r   r   r   r   rC   r   r   r!   r!   r!   r"   <module>   s*    W       