
    BVh[D                         d 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	 ddlm
Z
 ddlmZ dd	lmZ dd
lmZ ddlmZ d Z G d de      Z G d de      Z G d de      Zy)z2Generic source code transformation infrastructure.    N)cache)inspect_utils)loader)naming)origin_info)parser)	templates)transformer)
ag_loggingc           
         g }|D ]*  }d}	|j                  t        j                  |	|             , |r<t        j                  d|D 
cg c]  }
t        j
                  |
d       c}
d      }ng }|D 
cg c]-  }
t        j                  |
t        j                         dd      / }}
d	}	t        j                  |	|| |||||
      S c c}
w c c}
w )a
  Wraps an AST into the body of a factory with consistent lexical context.

  The AST is expected to define some symbol with a name given by `entity_name`.

  This mechanism ensures that the resulting transformed entity has lexical
  scoping identical to that of the source entity, while allowing extra
  parametrization.

  Two nested factories achieve the following:

   1. The inner factory dynamically creates the entity represented by `nodes`.
   2. The inner factory is parametrized by a custom set of arguments.
   3. The inner factory has a closure identical to that of the transformed
       entity.
   4. The inner factory has local variables named like `args`, which `nodes` may
       use as additional parameters.
   5. The inner factory returns the variables given by `entity_name`.
   6. The outer factory is niladic.
   7. The outer factory has no closure.
   8. The outer factory creates the necessary lexical scope for the inner
       factory, so that the loaded code has the given configuration for
       closure/globals.
   9. The outer factory returns the inner factory.

  Roughly speaking, the following code is generated:

      from __future__ import future_feature_1
      from __future__ import future_feature_2
      ...

      def outer_factory():
        closure_var_1 = None
        closure_var_2 = None
        ...

        def inner_factory(arg_1, arg_2, ...):
          <<nodes>>
          return entity

        return inner_factory

  The lexical scoping is created using dummy symbol declarations which create
  local variables in the body of the outer factory, so that the Python parser
  correctly marks them as free non-global variables upon load (that is, it
  creates cell slots for each symbol. These symbols are initialized with None,
  but their values are not expected to be used; instead, the caller is expected
  to replace them with the cells of the source entity. For more details, see:
  https://docs.python.org/3/reference/executionmodel.html#binding-of-names

  Args:
    nodes: Tuple[ast.AST], the source code to wrap.
    entity_name: Union[Text, ast.AST], the name of the principal entity that
      `nodes` define.
    inner_factory_name: Text, the name of the inner factory.
    outer_factory_name: Text, the name of the outer factory.
    closure_vars: Iterable[Text], names of the closure variables for the inner
      factory.
    factory_args: Iterable[Text], names of additional arguments for the
      inner factory. Useful to configure variables that the converted code can
      use. Typically, these are modules.
    future_features: Iterable[Text], names of future statements to associate the
      code with.

  Returns:
    ast.AST
  z
      var_name = None
    )var_name
__future__N)nameasnamer   )modulenameslevelctx
annotationtype_commentz
    future_imports
    def outer_factory_name():
      dummy_closure_defs
      def inner_factory_name(factory_args):
        entity_defs
        return entity_name
      return inner_factory_name
  )dummy_closure_defsentity_defsentity_namefactory_argsfuture_importsinner_factory_nameouter_factory_name)extendr	   replacegast
ImportFromaliasNameParam)nodesr   r   r   closure_varsr   future_featuresr   r   templater   r   s               [/home/dcms/DCMS/lib/python3.12/site-packages/tensorflow/python/autograph/pyct/transpiler.py_wrap_into_factoryr+   "   s    J  NhH i//8LM	N __>MNdtzztD1NN
 N 
 ii$**,4dK, 
( 
		+#++
- -' O
s   C	
62Cc                   0    e Zd ZdZd Z	 	 	 ddZ	 	 ddZy)_PythonFnFactoryz3Helper object that wraps a Python function factory.c                 X    || _         || _        || _        d| _        d| _        d| _        y)a4  Creates a new factory for a Python function.

    Args:
      name: The function name.
      freevars: The list of non-global free variables for the function.
      extra_locals: Dict[Text, Any], names and values for custom variables that
        are accessible to the generated code as local variables.
    N)_name	_freevars_extra_locals_unbound_factoryr   
source_map)selfr   freevarsextra_localss       r*   __init__z_PythonFnFactory.__init__   s0     DJDN%D DDKDO    c           	      v   | j                   t        d      |j                  |d      }|j                  |d      }t        || j                  ||| j
                  | j                  j                         |      }t        j                  |d      \  }}}t        ||      }	 |	       | _         || _        || _        y)zInitializes a function.Nz2double initialization; create a new object instead T)include_source_map)r2   
ValueError
new_symbolr+   r/   r0   r1   keysr   load_astgetattrr   r3   )
r4   r&   namerr   r   r(   r   _r3   outer_factorys
             r*   createz_PythonFnFactory.create   s     (KLL))*<bA))*<bAudjj2D14>>#11668/KE #OO$(FAzF$67M)ODDK DOr8   Nc                   
 | j                   t        d      | j                   j                  }|j                  }t	        t        | j                  |            
t        
fd|j                  D              }t        |      t        |      k7  r%t        dj                  | j                  |            t        j                  ||| j                  d|      } |di | j                  }	|r||	_        |r||	_        |	S )z Creates a new function instance.zcall create firstc              3   (   K   | ]	  }|     y wNr:   ).0r   closure_maps     r*   	<genexpr>z/_PythonFnFactory.instantiate.<locals>.<genexpr>   s      @"D@s   z:closure mismatch, requested {}, but source function had {}r:   )codeglobalsr   argdefsclosure)r2   r<   __code__co_freevarsdictzipr0   tuplelenformattypesFunctionTyper/   r1   __defaults____kwdefaults__)r4   globals_rN   defaults
kwdefaultsfactory_codefactory_freevarsfactory_closurebound_factorynew_fnrI   s             @r*   instantiatez_PythonFnFactory.instantiate   s     $*++((11L#//s4>>734K @&2&>&>@ @O
?s7|+
F
M
Mnn.01 1 &&ZZ!M 0T//0F$f(fMr8   )inner_factoryrC   r:   )NN)__name__
__module____qualname____doc__r7   rD   rb   r:   r8   r*   r-   r-      s'    ;( !0 /!4  !	"r8   r-   c                   4    e Zd ZdZd Zd Zd Zd Zd Zd Z	y)	GenericTranspilera  A generic transpiler for Python functions.

  Its interface is the `transform` API, which can process Python function
  objects. Internally, it handles parsing.

  Users typically subclass this, customizing the `transform_ast` method. The
  output of transformed_ast is returned directly by `transform`. Existing
  methods like `transform_function` may also be overloaded.

  Example:

      class MyTransformer(GenericTranspiler):

        def transform_ast(self, node, ctx):
          result = <<transform node>>
          return result

      transformer = MyTransformer()

      result = transformer.transform(f, ...)
      # result is the output
  c                     t        |t        j                        ryt        |t        j                        r|j                  S t        dj                  |            )zEReturns a name for the output function. Subclasses may override this.lamzUnknown node type {})
isinstancer!   LambdaFunctionDefr   r<   rU   )r4   nodes     r*   get_transformed_namez&GenericTranspiler.get_transformed_name   sD    $$	D$**	+YY
+2248
99r8   c                     t        d      )zPerforms an actual transformation of a function's AST.

    Subclasses must implement this method, and do not usually call it.

    Args:
      node: One or more ast.AST nodes representing the AST to be transformed.
      ctx: transformer.Context.
    subclasses must override thisNotImplementedError)r4   ro   r   s      r*   transform_astzGenericTranspiler.transform_ast        =
>>r8   c                     t        j                  |      st        j                  |      r| j                  ||      S t	        dj                  t        |                  )a  Transforms a Python object.

    Users typically call this method.

    Args:
      obj: A Python object, function, type, etc.
      user_context: An opaque object (may be None) that is forwarded to
        transform_ast, through the ctx.user attribute.
    Returns:
      The result of calling transform_function.

    Raises:
      NotImplementedError: if the type of obj is not handled.
    zNon-function: {})inspect
isfunctionismethodtransform_functionrt   rU   type)r4   objuser_contexts      r*   	transformzGenericTranspiler.transform
  sM     #'"2"23"7$$S,77
077S	B
CCr8   c                 ,   |j                   }t        t        |j                              D ]$  }t	        j
                  d      |j                  |<   & t        |j                        D ]*  \  }}|	t	        j
                  d      |j                  |<   , |S )z@Erase arg default expressions, which would otherwise be unbound.None)argsrangerT   r[   r   parse_expression	enumeratekw_defaults)r4   ro   r   ids        r*   _erase_arg_defaultsz%GenericTranspiler._erase_arg_defaults  s    99D3t}}%& 9008dmmA9$**+ >1	
$55f=> Kr8   c                     g }|j                   j                         D ]:  }t        j                  |      r	 |j	                  | j                  ||             < |S # t        $ r Y Jw xY w)as  Transforms a module.

    Subclasses may override this method. The return value is opaque.

    The method receives the original AST. The result is passed as-is to the
    output of `transform`.

    Args:
      mod: A Python module.
      user_context: An opaque object (may be None) that is forwarded to
        transform_ast, through the ctx.user attribute.
    Returns:
      List[Tuple[Any, Any]]. By default it returns the output of transform_ast,
      evaluated on each supported member, other than modules, together with a
      `transformer.Context` containing information about the transformation
      process.
    )__dict__valuesrx   ismoduleappendr   rt   )r4   modr~   resultmembers        r*   transform_modulez"GenericTranspiler.transform_module(  sm    $ F,,%%' 			&	!dnnV\:;	 M ! s   !A	A('A(c                    t        j                  |      }t        j                  ||      \  }}t	        j
                  dd||       t        j                  |||       t        j                  |      }t        j                  |      }|j                  | j                  |      d      }t        j                  ||d||      }	t        j                  |	||      }
| j!                  |      }| j#                  ||
      }||
fS )a5  Transforms a function.

    Subclasses may override this method. The return value is opaque.

    The method receives the original AST. The result is passed as-is to the
    output of `transform`.

    Args:
      fn: A function or lambda.
      user_context: An opaque object (may be None) that is forwarded to
        transform_ast, through the ctx.user attribute.
    Returns:
      Tuple[Any, Any]. By default it returns the output of transform_ast,
      together with a `transformer.Context` containing information about the
      transformation process.
    r(      zSource code of %s:

%s
r:   z
<fragment>)r   source_codesource_filer(   	namespace)r   getfutureimportsr   parse_entitylogginglogr   resolve_entitygetnamespacer   Namerr=   rp   r
   
EntityInfoContextr   ru   )r4   fnr~   r(   ro   sourcer   rA   new_nameentity_infocontextr   s               r*   r{   z$GenericTranspiler.transform_functionD  s    " $44R8O&&r?KLD&KK/V<tVR0**2.ILL#E 9 9$ ?DH(( 'K !!+ulCG##D)Dg.F7?r8   N)
rd   re   rf   rg   rp   ru   r   r   r   r{   r:   r8   r*   ri   ri      s&    .:	?D(8%r8   ri   c                   :     e Zd ZdZd Zd Zd Zd Z fdZ xZ	S )PyToPya  A generic Python-to-Python transpiler.

  Its `transform` method offers a function-in, function-out interface.
  Internally, it takes care of parsing, caching and loading of the translated
  code.

  Users typically subclass this, overriding `transform_ast`.

  Usually, instances of this class are singletons, since each instance manages
  its own cache. The caching can be controlled by overriding `get_caching_key`.

  Example:

      class MyTransformer(PyToPy):

        def transform_ast(self, node, ctx):
          node = <<transform node, usually using ast.NodeTransformer classes>>
          return node

      transformer = MyTransformer()

      new_f, module, source_map = transformer.transform_function(f, ...)
      # new_f is a function with signature identical to f

  The transformed function has access to the same namespace as the original
  function. To allow access to internal APIs, users may inject additional
  symbols by overriding `get_extra_locals`.
  c                 h    t        j                         | _        t        j                         | _        y rG   )	threadingRLock_cache_lockr   CodeObjectCache_cacher4   s    r*   r7   zPyToPy.__init__  s!     (D'')DKr8   c                     t        d      )zReturns extra static local variables to be made to transformed code.

    Subclasses must override this.

    Returns:
      extra_locals: A Dict[Text, Any] containing additional variables to make
        available to the transformed code.
    rr   rs   r   s    r*   get_extra_localszPyToPy.get_extra_locals  rv   r8   c                     t        d      )ay  Returns a unique key to use for caching.

    Subclasses must override this.

    Calls made to `transform_function` with functions that have the same code
    object and caching key will return a cached instance on subsequent
    invocations.

    Args:
      user_context: The context object which was passed to `transform`.

    Returns:
      extra_locals: A hashable.
    rr   rs   )r4   r~   s     r*   get_caching_keyzPyToPy.get_caching_key  s     =
>>r8   c                 \    | j                   |   |   }t        j                  dd|||       |S )Nr   zCache hit for %s subkey %s: %s)r   r   r   )r4   r   cache_subkeycached_factorys       r*   _cached_factoryzPyToPy._cached_factory  s2    [[_\2NKK3R r8   c           
         | j                  |      }| j                  j                  ||      r| j                  ||      }n| j                  5  | j                  j                  ||      r| j                  ||      }nt        j                  dd||       t        t        | '  ||      \  }}t        |t        j                        rVt        j                  t        j                  |j                  j                   t        j"                         dd      g|      }n|j                  j                   |_        t        j$                  d      r+t        j                  dd|t'        j(                  |             t+        |j                  j                   |j,                  j.                  | j1                               }|j3                  ||j4                  |j                  j6                         || j                  |   |<   ddd       j9                  |j:                  |j<                  xs d	|j>                  tA        |d
d            }||jB                  |jD                  fS # 1 sw Y   dxY w)a#  Transforms a function. See GenericTranspiler.transform_function.

    This overload wraps the parent's `transform_function`, adding caching and
    facilities to instantiate the output as a Python object. It also
    adds facilities to make new symbols available to the generated Python code,
    visible as local variables - see `get_extra_locals`.

    Args:
      fn: A function or lambda.
      user_context: An opaque object (may be None) that is forwarded to
        transform_ast, through the ctx.user attribute.

    Returns:
      A tuple:
        * A function or lambda with the same signature and closure as `fn`
        * The temporary module into which the transformed function was loaded
        * The source map as a
            Dict[origin_info.LineLocation, origin_info.OriginInfo]
       z%s is not cached for subkey %sNr   )targetsvalue   zTransformed %s:

%s
r   r:   rY   )rZ   rN   r[   r\   )#r   r   hasr   r   r   r   superr   r{   rl   r!   rm   Assignr$   infor   Storehas_verbosityr   unparser-   rO   rP   r   rD   rA   r(   rb   __globals____closure__rX   r@   r   r3   )	r4   r   r~   r   factoryr&   r   transformed_fn	__class__s	           r*   r{   zPyToPy.transform_function  s   ( ''5L{{r<($$R6g  2;;??2|,((\:' ++a92|
LVT=b,O*%t{{+KKII JJL#'%)	+ E EJ""1%KK4b&..:OP$hhmmR[[44d6K6K6MO'
..SYY0H0H  J*1$++b/,
'=2@ (($"2/6	 ) 8N
 7>>7+=+===K2 2s   F2I$$I-)
rd   re   rf   rg   r7   r   r   r   r{   __classcell__)r   s   @r*   r   r   l  s(    :*	??"@> @>r8   r   )rg   rx   r   rV   r!    tensorflow.python.autograph.pyctr   r   r   r   r   r   r	   r
   !tensorflow.python.autograph.utilsr   r   r+   objectr-   ri   r   r:   r8   r*   <module>r      se    9     2 : 3 3 8 3 6 8 Cj-ZMv M`J JZD> D>r8   