
    6                    :   S r SSKJr  SSKJr  SSKrSSKrSSKrSSKrSSKrSSK	J
r
  SSKJr  SSKJr  SSKJr  SS	KJr  SS
KJr  SSKJr  SSKJr  SSKJr  SSKJr  / SQr\R2                  r\(       a  SSKJr  SrSrSrS rS@S jr  " S S\!5      r" " S S\"5      r# " S S\!5      r$ " S S\%5      r& " S S\
RN                  " \&\!5      5      r( " S  S!\(5      r) " S" S#\(5      r*S$r+ " S% S&\RX                  5      r- " S' S(\!5      r. " S) S*\!5      r/ " S+ S,\!5      r0 " S- S.\!5      r1 " S/ S0\15      r2 " S1 S2\*5      r3 " S3 S4\15      r4S5r5S6r6S7r7S8r8S9 r9S: r: " S; S<\!5      r;S= r<\Rz                  R|                  \R~                  \Rz                  R                  \R                  \Rz                  R                  \R                  \Rz                  R                  \R                  \Rz                  R                  \R                  \Rz                  R                  \R                  \Rz                  R                  \R                  \Rz                  R                  \R                  \Rz                  R                  \R                  0	rO0 rP\(       Ga  \R                  R                  \R~                  \R                  R                  \R                  \R                  R                  \R                  \R                  R                  \R                  \R                  R                  \R~                  \R                  R                  \R                  \R                  R                  \R                  \R                  R                  \R                  0rPS> rZS? r[g)Az~Asynchronous datastore API.

This is designed to be the lowest-level API to be used by all Python
datastore client libraries.
    )absolute_import)unicode_literalsN)
six_subset)api_base_pb)apiproxy_rpc)apiproxy_stub_map)datastore_errors)datastore_types)datastore_pb)datastore_pbs)	entity_pb)apiproxy_errors)AbstractAdapterBaseConfigurationBaseConnectionConfigOptionConfiguration
ConnectionIdentityAdapterMultiRpcTransactionalConnectionTransactionModeTransactionOptions)googledatastorei ʚ;datastore_v3cloud_datastore_v1c                    ^  U 4S jnU$ )zuA decorator to declare that only the first N arguments may be positional.

Note that for methods, n includes 'self'.
c                 J   >^  [         R                  " T 5      UU 4S j5       nU$ )Nc            	         > [        U 5      T:  a/  SnTS:w  a  Sn[        STR                  TU[        U 5      4-  5      eT" U 0 UD6$ )N    sz6%s() takes at most %d positional argument%s (%d given))len	TypeError__name__)argskwdsplural_smax_pos_argswrappeds      7lib/googlecloudsdk/appengine/datastore/datastore_rpc.pypositional_wrapperE_positional.<locals>.positional_decorator.<locals>.positional_wrapperX   sa    	T\	!1(
B\8SY
?@A 	A d#d##    )	functoolswraps)r*   r,   r)   s   ` r+   positional_decorator)_positional.<locals>.positional_decoratorW   s&    __W$ $ r.    )r)   r1   s   ` r+   _positionalr4   R   s    
 
r.   c                 |    [         R                  " S5      nXS4;  a  [        R                  $ [        R                  $ )Tries to get the datastore type for the given app.

This function is only guaranteed to return something other than
UNKNOWN_DATASTORE when running in production and querying the current app.
N)r
   ResolveAppIdr   UNKNOWN_DATASTOREHIGH_REPLICATION_DATASTORE)appcurrent_apps     r+   _GetDatastoreTyper<   f   s7      ,,T2+d##+++		2	22r.   c                       \ rS rSrSr\R                  " 5       r\R                  " \5      r	SS jr
S rS rS rS rS	 rS
 rS rS rS rS rS rS rS rS rS rSrg)r   r   a  Abstract interface between protobufs and user-level classes.

This class defines conversions between the protobuf classes defined
in entity_pb.py on the one hand, and the corresponding user-level
classes (which are defined by higher-level API libraries such as
datastore.py or db.py) on the other hand.

The premise is that the code in this module is agnostic about the
user-level classes used to represent keys and entities, while at the
same time provinging APIs that accept or return such user-level
classes.

Higher-level libraries must subclass this abstract class and pass an
instance of the subclass to the Connection they want to use.

These methods may raise datastore_errors.Error for bad inputs.
Nc                     U(       aA  [         R                  " U5      U l        [         R                  " U R                  5      U l        g g N)r   get_entity_converter_entity_converter_QueryConverter_query_converter)selfid_resolvers     r+   __init__AbstractAdapter.__init__   s<    ,AA
 d+;;

 
 "d r.   c                     U R                   $ r@   )rB   rE   s    r+   rA   $AbstractAdapter.get_entity_converter   s    !!!r.   c                     U R                   $ r@   )rD   rJ   s    r+   get_query_converter#AbstractAdapter.get_query_converter   s       r.   c                     [         e)z2Turn an entity_pb.Reference into a user-level key.NotImplementedErrorrE   pbs     r+   	pb_to_keyAbstractAdapter.pb_to_key       
r.   c                     [         R                  " 5       nU R                  R                  X5        U R	                  U5      $ )z2Turn an googledatastore.Key into a user-level key.)r   	ReferencerB   v1_to_v3_referencerT   )rE   rS   v3_refs      r+   pb_v1_to_keyAbstractAdapter.pb_v1_to_key   s3      "F--b9>>&!!r.   c                     [         e)z7Turn an entity_pb.EntityProto into a user-level entity.rP   rR   s     r+   pb_to_entityAbstractAdapter.pb_to_entity   rV   r.   c                     [         R                  " 5       nU R                  R                  XU5        U R	                  U5      $ )z8Turn an googledatastore.Entity into a user-level entity.)r   EntityProtorB   v1_to_v3_entityr^   )rE   rS   is_projection	v3_entitys       r+   pb_v1_to_entityAbstractAdapter.pb_v1_to_entity   s7    %%'I**2-HY''r.   c                     UR                   (       a  U R                  UR                  5      $ U R                  U[	        UR
                  5      5      $ )z>Turn an googledatastore.Entity into a user-level query result.)	keys_onlyr[   keyre   bool
projectionrE   rS   query_optionss      r+   pb_v1_to_query_result%AbstractAdapter.pb_v1_to_query_result   s>    rvv&&!!"d=+C+C&DEEr.   c                     [         e)zHTurn an entity_pb.CompositeIndex into a user-level Index
representation.rP   rR   s     r+   pb_to_indexAbstractAdapter.pb_to_index   s
     r.   c                     UR                   (       a  U R                  UR                  5       5      $ U R                  U5      $ )z=Turn an entity_pb.EntityProto into a user-level query result.)rh   rT   ri   r^   rl   s      r+   pb_to_query_result"AbstractAdapter.pb_to_query_result   s1    ^^BFFH%%r""r.   c                     [         e)z2Turn a user-level key into an entity_pb.Reference.rP   rE   ri   s     r+   	key_to_pbAbstractAdapter.key_to_pb   rV   r.   c                     U R                  U5      n[        R                  " 5       nU R                  R	                  X#5        U$ )z2Turn a user-level key into an googledatastore.Key.)rx   r   KeyrB   v3_to_v1_key)rE   ri   rZ   v1_keys       r+   key_to_pb_v1AbstractAdapter.key_to_pb_v1   s7    ^^C F  "F''7Mr.   c                     [         e)z7Turn a user-level entity into an entity_pb.EntityProto.rP   rE   entitys     r+   entity_to_pbAbstractAdapter.entity_to_pb   rV   r.   c                     U R                  U5      n[        R                  " 5       nU R                  R	                  X#5        U$ )z5Turn a user-level entity into an googledatastore.Key.)r   r   EntityrB   v3_to_v1_entity)rE   r   rd   	v1_entitys       r+   entity_to_pb_v1AbstractAdapter.entity_to_pb_v1   s:    !!&)I&&(I**9@r.   c                 ,    [         R                  " 5       $ )z(Create a new, empty entity_pb.Reference.)r   rX   rJ   s    r+   
new_key_pbAbstractAdapter.new_key_pb   s      r.   c                 ,    [         R                  " 5       $ )z*Create a new, empty entity_pb.EntityProto.)r   ra   rJ   s    r+   new_entity_pbAbstractAdapter.new_entity_pb   s      ""r.   )rB   rD   r@   )r%   
__module____qualname____firstlineno____doc__r   rA   rB   rC   rD   rG   rM   rT   r[   r^   re   rn   rq   rt   rx   r~   r   r   r   r   __static_attributes__r3   r.   r+   r   r   r   s{    $ $88:"223DE""!"(F
#!#r.   r   c                   N   ^  \ rS rSrSrS
U 4S jjrS rS rS rS r	S r
S	rU =r$ )r      zA concrete adapter that implements the identity mapping.

This is used as the default when a Connection is created without
specifying an adapter; that's primarily for testing.
c                 ,   > [         [        U ]  U5        g r@   )superr   rG   )rE   rF   	__class__s     r+   rG   IdentityAdapter.__init__   s    	/4)+6r.   c                     U$ r@   r3   rR   s     r+   rT   IdentityAdapter.pb_to_key       Ir.   c                     U$ r@   r3   rR   s     r+   r^   IdentityAdapter.pb_to_entity   r   r.   c                     U$ r@   r3   rw   s     r+   rx   IdentityAdapter.key_to_pb   s    Jr.   c                     U$ r@   r3   r   s     r+   r   IdentityAdapter.entity_to_pb   s    Mr.   c                     U$ r@   r3   rR   s     r+   rq   IdentityAdapter.pb_to_index   r   r.   r3   r@   )r%   r   r   r   r   rG   rT   r^   rx   r   rq   r   __classcell__r   s   @r+   r   r      s+    7 r.   r   c                   0    \ rS rSrSrS rS rS rS rSr	g)	r      aw  A descriptor for a Configuration option.

This class is used to create a configuration option on a class that inherits
from BaseConfiguration. A validator function decorated with this class will
be converted to a read-only descriptor and BaseConfiguration will implement
constructor and merging logic for that configuration option. A validator
function takes a single non-None value to validate and either throws
an exception or returns that value (or an equivalent value). A validator is
called once at construction time, but only if a non-None value for the
configuration option is specified the constructor's keyword arguments.
c                     Xl         g r@   	validator)rE   r   s     r+   rG   ConfigOption.__init__  s    Nr.   c                 l    Uc  U $ UR                   R                  U R                  R                  S 5      $ r@   )_valuesgetr   r%   )rE   objobjtypes      r+   __get__ConfigOption.__get__  s+    
{k;;??4>>22D99r.   c                 J    [        SU R                  R                  < S35      e)Nz%Configuration options are immutable ())AttributeErrorr   r%   )rE   r   values      r+   __set__ConfigOption.__set__
  s!    
..114 5 5r.   c                 `   U R                   R                  nU H  n[        U[        S5      [        R
                  45      (       a  M/  [        U[        5      (       d  [        R                  " SU< S35      eX#R                  ;   d  Mp  XR                  U   L d  M  UR                  U   s  $    g)aK  Gets the first non-None value for this option from the given args.

Args:
  *arg: Any number of configuration objects or None values.

Returns:
  The first value for this ConfigOption found in the given configuration
objects or None.

Raises:
  datastore_errors.BadArgumentError if a given in object is not a
configuration object.
Ninvalid config argument (r   )r   r%   
isinstancetyper   UserRPCr   r	   BadArgumentErrorr   _options)rE   r&   nameconfigs       r+   __call__ConfigOption.__call__  s     >>""D	FT$Z):)B)BC	D	D&"344//.468 	8>>!dood.C&C~~d##  r.   r   N)
r%   r   r   r   r   rG   r   r   r   r   r3   r.   r+   r   r      s    
:
5r.   r   c                       \ rS rSrSrS rSrg)_ConfigurationMetaClassi)  zThe metaclass for all Configuration types.

This class is needed to store a class specific list of all ConfigOptions in
cls._options, and insert a __slots__ variable into the class dict before the
class is created to impose immutability.
c                 F   US:X  a  [         R                  XX#5      $ [        U;   a  S/US'   O/ US'   [         R                  XX#5      n[        U;  a  0 n[        UR                  5       H3  nSUR
                  ;   d  M  UR                  UR
                  S   5        M5     XTl        UR
                  R                  5        H\  u  px[        U[        5      (       d  M  XtR                  ;   a  [        U< SUR                  < S35      eXR                  U'   XHl        M^     U$ )N_MergedConfigurationr   	__slots__r   z cannot be overridden (r   )r   __new__objectreversed__mro____dict__updater   itemsr   r   r$   r%   _cls)		metaclass	classnamebases	classDictclsoptionscoptionr   s	            r+   r   _ConfigurationMetaClass.__new__1  s    **\\)AA  ){i!i
,,yU
>CUg$!#
..J/
0 % l<<--/-&e\**||##S\\3 4 4!&,,v
* 0 Jr.   r3   N)r%   r   r   r   r   r   r   r3   r.   r+   r   r   )  s    r.   r   c                   z   ^  \ rS rSrSr0 rSU 4S jjrS rS rS r	S r
S r\S	 5       rS
 rS rS rS rSrU =r$ )r   iO  a  A base class for a configuration object.

Subclasses should provide validation functions for every configuration option
they accept. Any public function decorated with ConfigOption is assumed to be
a validation function for an option of the same name. All validation functions
take a single non-None value to validate and must throw an exception or return
the value to store.

This class forces subclasses to be immutable and exposes a read-only
property for every accepted configuration option. Configuration options set by
passing keyword arguments to the constructor. The constructor and merge
function are designed to avoid creating redundant copies and may return
the configuration objects passed to them if appropriate.

Setting an option to None is the same as not specifying the option except in
the case where the 'config' argument is given. In this case the value on
'config' of the same name is ignored. Options that are not specified will
return 'None' when accessed.
c                   > Uc  O[        U[        5      (       a  XR                  L a  UR                  " S0 UD6(       a  U$ UR                  R                  5        H?  u  p4[        XR                  U   R                  5      (       d  M.  UR                  X45        MA     O[        R                  " SU< S35      e[        [        U ]7  U 5      n0 Ul        UR                  5        H>  u  p4Uc  M
   UR                  U   nUR!                  U5      nUc  M0  XER                  U'   M@     U$ ! [         a  n[        SU-  5      eSnAff = f)aD  Immutable constructor.

If 'config' is non-None all configuration options will default to the value
it contains unless the configuration option is explicitly set to 'None' in
the keyword arguments. If 'config' is None then all configuration options
default to None.

Args:
  config: Optional base configuration providing default values for
    parameters not specified in the keyword arguments.
  **kwargs: Configuration options to store on this object.

Returns:
  Either a new Configuration object or (if it would be equivalent)
  the config argument unchanged, but never None.
Nz)config argument should be Configuration (r   z!Unknown configuration option (%s)r3   )r   r   r   _BaseConfiguration__is_strongerr   r   
issubclassr   r   
setdefaultr	   r   r   r   KeyErrorr$   r   )	r   r   kwargsri   r   r   config_optionerrr   s	           r+   r   BaseConfiguration.__new__f  s1   " ~
	F-	.	.	  	 V%9%9%CF%C,,.*#c??3/4455


C
' /
 --<B
DF F !3
/
4CCKlln
			E,,s+- ''."++c
 % J  	E=CD
D	Es   0D))
E3EEc                     XL a  g[        U[        5      (       d  [        $ U R                  UR                  :H  =(       a    U R                  UR                  :H  $ NT)r   r   NotImplementedr   r   )rE   others     r+   __eq__BaseConfiguration.__eq__  sC    }e.//==ENN*Lt||u}}/LLr.   c                 H    U R                  U5      nU[        L a  U$ U(       + $ r@   )r   r   )rE   r   equals      r+   __ne__BaseConfiguration.__ne__  s%    KKEl9r.   c                     [        [        U R                  R                  5       5      5      [        [        U R                  R                  5       5      5      -  $ r@   )hash	frozensetr   r   r   rJ   s    r+   __hash__BaseConfiguration.__hash__  s@    4<<--/014==..0123 4r.   c                     / n[        U R                  R                  5       5       H  nUR                  SU-  5        M     U R                  R
                  < SSR                  U5      < S3$ )Nz%s=%r(z, r   )sortedr   r   appendr   r%   join)rE   r&   	key_values      r+   __repr__BaseConfiguration.__repr__  sQ    DDLL..01	
kk'I%& 2~~..		$@@r.   c                 |    UR                  5        H(  u  p#X R                  ;  d  X0R                  U   :w  d  M(    g   g)a  Internal helper to ask whether a configuration is stronger than another.

A configuration is stronger when it contains every name/value pair in
kwargs.

Example: a configuration with:
  (deadline=5, on_configuration=None, read_policy=EVENTUAL_CONSISTENCY)
is stronger than:
  (deadline=5, on_configuration=None)
but not stronger than:
  (deadline=5, on_configuration=None, read_policy=None)
or
  (deadline=10, on_configuration=None, read_policy=None).

More formally:
  - Any value is stronger than an unset value;
  - Any value is stronger than itself.

Returns:
  True if each of the self attributes is stronger than the
corresponding argument.
FT)r   r   )rE   r   ri   r   s       r+   __is_strongerBaseConfiguration.__is_stronger  s6    . lln
	LL	 E\\#->$> % r.   c                 R    [        U[        5      =(       a    UR                  U 5      $ )aL  True if configuration obj handles all options of this class.

Use this method rather than isinstance(obj, cls) to test if a
configuration object handles the options of cls (is_configuration
is handled specially for results of merge which may handle the options
of unrelated configuration classes).

Args:
  obj: the object to test.
)r   r   _is_configuration)r   r   s     r+   is_configuration"BaseConfiguration.is_configuration  s"     c,-L#2G2G2LLr.   c                     [        X5      $ r@   )r   )rE   r   s     r+   r  #BaseConfiguration._is_configuration  s    d  r.   c                 X  ^ ^ Tb  TT L a  T $ [        T[        5      (       d  [        T [        5      (       d  [        TT R                  5      (       a'  T R                   H  nUTR                  ;  d  M    O   T$ [        T TR                  5      (       a#  T R                  " S0 TR                  D6(       a  T $ UU 4S jn[        TT R                  5      (       a  U" [        T5      " 5       5      $ [        T TR                  5      (       a  U" [        T 5      " 5       5      $ [        TT 5      $ )a&  Merge two configurations.

The configuration given as an argument (if any) takes priority;
defaults are filled in from the current configuration.

Args:
  config: Configuration providing overrides, or None (but cannot
    be omitted).

Returns:
  Either a new configuration object or (if it would be equivalent)
  self or the config argument unchanged, but never None.

Raises:
  BadArgumentError if self or config are of configurations classes
  with conflicting options (i.e. the same option name defined in
  two different configuration classes).
c                    > TR                   R                  5       U l         U R                   R                  TR                   5        U $ r@   )r   copyr   )r   r   rE   s    r+   _quick_merge-BaseConfiguration.merge.<locals>._quick_merge   s2    ll'')6>>*
r.   r3   )r   r   r   r   r   r   )rE   r   ri   r
  s   ``  r+   mergeBaseConfiguration.merge  s    & ~4k v344t122 
FDNN	+	+<<C&   -	D&**	+	+00+
 
FDNN	+	+DLN++	D&**	+	+DJL))  --r.   c                     SU R                   0$ )Nr   r   rJ   s    r+   __getstate__BaseConfiguration.__getstate__  s    t||$$r.   c                 P    U R                   " S0 US   D6nUR                  U l        g )Nr   r3   )r   r   rE   stater   s      r+   __setstate__BaseConfiguration.__setstate__  s%     ..
,5+
,C;;DLr.   r  r@   )r%   r   r   r   r   r   r   r   r   r   r   r   classmethodr  r  r  r  r  r   r   r   s   @r+   r   r   O  s`    & (+ZM4A8 M M!4.l% r.   r   c                   R   ^  \ rS rSrSr/ SQrU 4S jrS rS rS r	S r
S	 rS
rU =r$ )r   i  a%  Helper class to handle merges of configurations.

Instances of _MergedConfiguration are in some sense "subclasses" of the
argument configurations, i.e.:
- they handle exactly the configuration options of the argument configurations
- the value of these options is taken in priority order from the arguments
- isinstance is true on this configuration if it is true on any of the
  argument configurations
This class raises an exception if two argument configurations have an option
with the same name but coming from a different configuration class.
)r   _configsr   _classesc           	      D  > [         [        U ]  U 5      nXl        0 Ul        U H  nUR                  R                  5        H  u  pEXBR                  ;   ak  XRR                  U   LaZ  SU< SUR                  R                  < SUR                  U   R                  R                  < S3n[        R                  " U5      eXRR                  U'   M     M     0 Ul
        [        U5       H4  nUR                  R                  5        H  u  pGXrR                  U'   M     M6     U$ )Nzmerge conflict on 'z' from 'z' and '')r   r   r   r  r   r   r   r%   r	   r   r   r   )	r   configsr   r   r   r   errorr   r   s	           r+   r   _MergedConfiguration.__new__%  s    
!3
/
4CL CL ////1,$<<<<--FKK00ll4(--668E #33E::#T 2  CK7#--/+$!D 0 $ Jr.   c                 `    U R                   R                  < [        U R                  5      < 3$ r@   )r   r%   tupler  rJ   s    r+   r   _MergedConfiguration.__repr__<  s     ^^,,eDMM.BCCr.   c                 Z    U R                    H  nUR                  U5      (       d  M    g   g)NTF)r  r  )rE   r   r   s      r+   r  &_MergedConfiguration._is_configuration?  s)    --		!	!#	&	&   r.   c                 ~    XR                   ;   a  XR                  ;   a  U R                  U   $ g [        SU< S35      e)Nz Configuration has no attribute 'r  )r   r   r   )rE   r   s     r+   __getattr__ _MergedConfiguration.__getattr__E  s6    }}		||D!!
$H
IIr.   c                     SU R                   0$ Nr  )r  rJ   s    r+   r  !_MergedConfiguration.__getstate__M  s    &&r.   c                     [        US   6 nUR                  U l        UR                  U l        UR                  U l        g r)  )r   r   r  r   r  s      r+   r  !_MergedConfiguration.__setstate__P  s2    
j 1
2C;;DLLLDMLLDMr.   )r  r   r   )r%   r   r   r   r   r   r   r   r  r&  r  r  r   r   r   s   @r+   r   r     s4    
 >).DJ'! !r.   r   c                       \ rS rSrSrSr Sr Sr \" \\\45      r	\
S 5       r\
S 5       r\
S 5       r\
S	 5       r\
S
 5       r\
S 5       r\
S 5       r\
S 5       r\
S 5       r\
S 5       rSrg)r   iX  a  Configuration parameters for datastore RPCs.

This class reserves the right to define configuration options of any name
except those that start with 'user_'. External subclasses should only define
function or variables with names that start with in 'user_'.

The options defined on this class include generic RPC parameters (deadline)
but also datastore-specific parameters (on_completion and read_policy).

Options are set by passing keyword arguments to the constructor corresponding
to the configuration options defined below.
r   r!      c                     [        U [        R                  [        4-   5      (       d  [        R
                  " SU < S35      eU S::  a  [        R
                  " SU < S35      eU $ )zThe deadline for any RPC issued.

If unset the system default will be used which is typically 5 seconds.

Raises:
  BadArgumentError if value is not a number or is less than zero.
z,deadline argument should be int/long/float (r   r   z!deadline argument should be > 0 ()r   r   integer_typesfloatr	   r   r   s    r+   deadlineConfiguration.deadline  s^     eZ55@AA--=BDF Fz--279; ;Lr.   c                     U $ )a
  A callback that is invoked when any RPC completes.

If specified, it will be called with a UserRPC object as argument when an
RPC completes.

NOTE: There is a subtle but important difference between
UserRPC.callback and Configuration.on_completion: on_completion is
called with the RPC object as its first argument, where callback is
called without arguments.  (Because a Configuration's on_completion
function can be used with many UserRPC objects, it would be awkward
if it was called without passing the specific RPC.)
r3   r2  s    r+   on_completionConfiguration.on_completion  s	      Lr.   c                 d    U [         R                  ;  a  [        R                  " SU < S35      eU $ )zThe read policy to use for any relevent RPC.

if unset STRONG_CONSISTENCY will be used.

Raises:
  BadArgumentError if value is not a known read policy.
zread_policy argument invalid (r   )r   ALL_READ_POLICIESr	   r   r2  s    r+   read_policyConfiguration.read_policy  s0     M333--/468 8Lr.   c                 f    [        U [        5      (       d  [        R                  " SU < S35      eU $ )zyIf a write request should succeed even if the app is read-only.

This only applies to user controlled read-only periods.
zforce_writes argument invalid (r   r   rj   r	   r   r2  s    r+   force_writesConfiguration.force_writes  s/     eT""--0579 9Lr.   c                 |    [        U [        R                  5      (       a  U S:  d  [        R                  " S5      eU $ )a  The maximum number of entity groups that can be represented in one rpc.

For a non-transactional operation that involves more entity groups than the
maximum, the operation will be performed by executing multiple, asynchronous
rpcs to the datastore, each of which has no more entity groups represented
than the maximum.  So, if a put() operation has 8 entity groups and the
maximum is 3, we will send 3 rpcs, 2 with 3 entity groups and 1 with 2
entity groups.  This is a performance optimization - in many cases
multiple, small, concurrent rpcs will finish faster than a single large
rpc.  The optimal value for this property will be application-specific, so
experimentation is encouraged.
r   z6max_entity_groups_per_rpc should be a positive integerr   r   r0  r	   r   r2  s    r+   max_entity_groups_per_rpc'Configuration.max_entity_groups_per_rpc  s:     uj6677EAI--
BD DLr.   c                 |    [        U [        R                  5      (       a  U S:  d  [        R                  " S5      eU $ )z3The maximum number of keys in a v1 AllocateIds rpc.r   z2max_allocate_ids_keys should be a positive integerrA  r2  s    r+   max_allocate_ids_keys#Configuration.max_allocate_ids_keys  s:     uj6677EAI--
>@ @Lr.   c                 |    [        U [        R                  5      (       a  U S:  d  [        R                  " S5      eU $ )zAThe maximum serialized size of a Get/Put/Delete without batching.r   z*max_rpc_bytes should be a positive integerrA  r2  s    r+   max_rpc_bytesConfiguration.max_rpc_bytes  s8     uj6677EAI--46 6Lr.   c                 |    [        U [        R                  5      (       a  U S:  d  [        R                  " S5      eU $ )z5The maximum number of keys in a Get without batching.r   z)max_get_keys should be a positive integerrA  r2  s    r+   max_get_keysConfiguration.max_get_keys  s8     uj6677EAI--35 5Lr.   c                 |    [        U [        R                  5      (       a  U S:  d  [        R                  " S5      eU $ )z9The maximum number of entities in a Put without batching.r   z-max_put_entities should be a positive integerrA  r2  s    r+   max_put_entitiesConfiguration.max_put_entities  s8     uj6677EAI--79 9Lr.   c                 |    [        U [        R                  5      (       a  U S:  d  [        R                  " S5      eU $ )z8The maximum number of keys in a Delete without batching.r   z,max_delete_keys should be a positive integerrA  r2  s    r+   max_delete_keysConfiguration.max_delete_keys  s8     uj6677EAI--68 8Lr.   r3   N)r%   r   r   r   r   STRONG_CONSISTENCYEVENTUAL_CONSISTENCYAPPLY_ALL_JOBS_CONSISTENCYr   r9  r   r3  r6  r:  r>  rB  rE  rH  rK  rN  rQ  r   r3   r.   r+   r   r   X  s    ?  !  !3!5!;!# $     "      $          r.   r   cloud_datastore_noopc                   8   ^  \ rS rSrSrU 4S jrS rS rSrU =r	$ )_NoopRPCi   z?An RPC implementation that does not modify the response object.c                 *   > [         [        U ]  5         g r@   )r   rX  rG   )rE   r   s    r+   rG   _NoopRPC.__init__  s    	(D"$r.   c                     gr   r3   rJ   s    r+   	_WaitImpl_NoopRPC._WaitImpl  s    r.   c                 B    [         R                  R                  U l        g r@   )r   RPC	FINISHING_staterJ   s    r+   _MakeCallImpl_NoopRPC._MakeCallImpl	  s    "",,DKr.   )ra  )
r%   r   r   r   r   rG   r\  rb  r   r   r   s   @r+   rX  rX     s    G%- -r.   rX  c                       \ rS rSrSrS rSrg)_NoopRPCStubi  z+An RPC stub which always creates a NoopRPC.c                     [        5       $ r@   )rX  rJ   s    r+   	CreateRPC_NoopRPCStub.CreateRPC  s
    :r.   r3   N)r%   r   r   r   r   rg  r   r3   r.   r+   re  re    s
    3r.   re  c                       \ rS rSrSrSS jr\S 5       r\S 5       rS r	S r
S	 r\S
 5       r\S 5       r\S 5       rSrg)r   i  a  A wrapper around multiple UserRPC objects.

This provides an API similar to that of UserRPC, but wraps multiple
RPCs such that e.g. .wait() blocks until all wrapped RPCs are
complete, and .get_result() returns the combined results from all
wrapped RPCs.

Class methods:
  flatten(rpcs): Expand a list of UserRPCs and MultiRpcs
    into a list of UserRPCs.
  wait_any(rpcs): Call UserRPC.wait_any(flatten(rpcs)).
  wait_all(rpcs): Call UserRPC.wait_all(flatten(rpcs)).

Instance methods:
  wait(): Wait for all RPCs.
  check_success(): Wait and then check success for all RPCs.
  get_result(): Wait for all, check successes, then merge
    all results.

Instance attributes:
  rpcs: The list of wrapped RPCs (returns a copy).
  state: The combined state of all RPCs.
Nc                 <    U R                  U5      U l        X l        g)zConstructor.

Args:
  rpcs: A list of UserRPC and MultiRpc objects; it is flattened
    before being stored.
  extra_hook: Optional function to be applied to the final result
    or list of results.
N)flatten_MultiRpc__rpcs_MultiRpc__extra_hook)rE   rpcs
extra_hooks      r+   rG   MultiRpc.__init__-  s     ,,t$DK"r.   c                 ,    [        U R                  5      $ )zrGet a flattened list containing the RPCs wrapped.

This returns a copy to prevent users from modifying the state.
)listrl  rJ   s    r+   rn  MultiRpc.rpcs9  s     r.   c                 &   [         R                  R                  n[         R                  R                  nU R                   H-  n[        XR                  5      n[        X#R                  5      nM/     X:X  a  U$ [         R                  R                  $ )zGet the combined state of the wrapped RPCs.

This mimics the UserRPC.state property.  If all wrapped RPCs have
the same state, that state is returned; otherwise, RUNNING is
returned (which here really means 'neither fish nor flesh').
)	r   r_  r`  IDLErl  minr  maxRUNNING)rE   lohirpcs       r+   r  MultiRpc.stateA  sn     
			#	#B					B{{r99br99b  
xi###r.   c                 V    [         R                  R                  U R                  5        g)zMWait for all wrapped RPCs to finish.

This mimics the UserRPC.wait() method.
N)r   r   wait_allrl  rJ   s    r+   waitMultiRpc.waitR  s    
 &&t{{3r.   c                 j    U R                  5         U R                   H  nUR                  5         M     g)zCheck success of all wrapped RPCs, failing if any of the failed.

This mimics the UserRPC.check_success() method.

NOTE: This first waits for all wrapped RPCs to finish before
checking the success of any of them.  This makes debugging easier.
N)r  rl  check_successrE   r{  s     r+   r  MultiRpc.check_successY  s'     	IIK{{	 r.   c                 v   [        U R                  5      S:X  a  U R                  S   R                  5       nOc/ nU R                   HQ  nUR                  5       n[        U[        5      (       a  UR                  U5        M;  Uc  M@  UR                  U5        MS     U R                  b  U R                  U5      nU$ )a  Return the combined results of all wrapped RPCs.

This mimics the UserRPC.get_results() method.  Multiple results
are combined using the following rules:

1. If there are no wrapped RPCs, an empty list is returned.

2. If exactly one RPC is wrapped, its result is returned.

3. If more than one RPC is wrapped, the result is always a list,
   which is constructed from the wrapped results as follows:

   a. A wrapped result equal to None is ignored;

   b. A wrapped result that is a list (but not any other type of
      sequence!) has its elements added to the result list.

   c. Any other wrapped result is appended to the result list.

After all results are combined, if __extra_hook is set, it is
called with the combined results and its return value becomes the
final result.

NOTE: This first waits for all wrapped RPCs to finish, and then
checks all their success.  This makes debugging easier.
r!   r   )r#   rl  
get_resultr   rr  extendr   rm  )rE   resultsr{  results       r+   r  MultiRpc.get_resulte  s    J 4;;1A))+gg #!fd##
..
 
..
   $!!'*gNr.   c                    / nU H  n[        U[        5      (       a  UR                  UR                  5        M5  [        U[        R
                  5      (       d  [        R                  " SU< S35      eUR                  U5        M     U$ )a"  Return a list of UserRPCs, expanding MultiRpcs in the argument list.

For example: given 4 UserRPCs rpc1 through rpc4,
flatten(rpc1, MultiRpc([rpc2, rpc3], rpc4)
returns [rpc1, rpc2, rpc3, rpc4].

Args:
  rpcs: A list of UserRPC and MultiRpc objects.

Returns:
  A list of UserRPC objects.
z#Expected a list of UserRPC object (r   )	r   r   r  rl  r   r   r	   r   r   )r   rn  flatr{  s       r+   rk  MultiRpc.flatten  sr     D	C	"	" 	CJJ#08899 118;=? ?C  Kr.   c                 ^    [         R                  R                  U R                  U5      5      $ )zWait until one of the RPCs passed in is finished.

This mimics UserRPC.wait_any().

Args:
  rpcs: A list of UserRPC and MultiRpc objects.

Returns:
  A UserRPC object or None.
)r   r   wait_anyrk  r   rn  s     r+   r  MultiRpc.wait_any  s$     $$--ckk$.?@@r.   c                 `    [         R                  R                  U R                  U5      5        g)zWait until all RPCs passed in are finished.

This mimics UserRPC.wait_all().

Args:
  rpcs: A list of UserRPC and MultiRpc objects.
N)r   r   r~  rk  r  s     r+   r~  MultiRpc.wait_all  s!     &&s{{4'89r.   )__extra_hook__rpcsr@   )r%   r   r   r   r   rG   propertyrn  r  r  r  r  r  rk  r  r~  r   r3   r.   r+   r   r     s    0
#   $ $ 4
3j  6 A A : :r.   r   c                   $    \ rS rSrSrSrSrSrSrg)r   i  a  The mode of a Datastore transaction.

Specifying the mode of the transaction can help to improve throughput, as it
provides additional information about the intent (or lack of intent, in the
case of a read only transaction) to perform a write as part of the
transaction.
r   r!   r.  r3   N)	r%   r   r   r   r   UNKNOWN	READ_ONLY
READ_WRITEr   r3   r.   r+   r   r     s     ')*r.   r   c                      \ rS rSrSrSrSrSr\" \	\
45      r\" S5      SS\	4S j5       r\S 5       r\S	 5       rS
 rS rS rS rS1S jrS rS2S jr\rS1S jrS r  S3S jr\rS rSrSrSr Sr!Sr"Sr#S r$S r%S r&S r'S r(S r)S r*S  r+S1S! jr,S" r-S# r.S$ r/S2S% jr0S& r1S' r2S1S( jr3S) r4S* r5S1S+ jr6S, r7S\8Rr                  4S- jr:S\8Rr                  4S. jr;S/ r<S0r=g)4r   i  a 	  Datastore connection base class.

NOTE: Do not instantiate this class; use Connection or
TransactionalConnection instead.

This is not a traditional database connection -- with App Engine, in
the end the connection is always implicit in the process state.
There is also no intent to be compatible with PEP 249 (Python's
Database-API).  But it is a useful abstraction to have an explicit
object that manages the database interaction, and especially
transactions.  Other settings related to the App Engine datastore
are also stored here (e.g. the RPC timeout).

A similar class in the Java API to the App Engine datastore is
DatastoreServiceConfig (but in Java, transaction state is always
held by the current thread).

To use transactions, call connection.new_transaction().  This
returns a new connection (an instance of the TransactionalConnection
subclass) which you should use for all operations in the
transaction.

This model supports multiple unrelated concurrent transactions (but
not nested transactions as this concept is commonly understood in
the relational database world).

When the transaction is done, call .commit() or .rollback() on the
transactional connection.  If .commit() returns False, the
transaction failed and none of your operations made it to the
datastore; if it returns True, all your operations were committed.
The transactional connection cannot be used once .commit() or
.rollback() is called.

Transactions are created lazily.  The first operation that requires
a transaction handle will issue the low-level BeginTransaction
request and wait for it to return.

Transactions keep track of the entity group.  All operations within
a transaction must use the same entity group.  An entity group
(currently) comprises an app id, a namespace, and a top-level key (a
kind and an id or name).  The first operation performed determines
the entity group.  There is some special-casing when the first
operation is a put() of an entity with an incomplete key; in this case
the entity group is determined after the operation returns.

NOTE: the datastore stubs in the dev_appserver currently support
only a single concurrent transaction.  Specifically, the (old) file
stub locks up if an attempt is made to start a new transaction while
a transaction is already in use, whereas the sqlite stub fails an
assertion.
r   r!   r.  Nc                 d   Uc
  [        5       n[        U[        5      (       d  [        R                  " SU< S35      eXl        Uc  [        5       nO5[        R                  U5      (       d  [        R                  " SU< S35      eX l        X0R                  ;  a  [        R                  " SU< S35      eU[        :X  a[  [        (       d$  [        R                  " [        R                  5      e[        R                  R!                  ["        [%        5       5        X0l        [)        5       U l        g)Constructor.

All arguments should be specified as keyword arguments.

Args:
  adapter: Optional AbstractAdapter subclass instance;
    default IdentityAdapter.
  config: Optional Configuration object.
Nzinvalid adapter argument (r   r   zunsupported API version ()r   r   r   r	   r   _BaseConnection__adapterr   r  _BaseConnection__config#_BaseConnection__SUPPORTED_VERSIONS_CLOUD_DATASTORE_V1_CLOUD_DATASTORE_ENABLEDr   MISSING_CLOUD_DATASTORE_MESSAGEr   apiproxyReplaceStub_NOOP_SERVICEre  _api_versionset_BaseConnection__pending_rpcs)rE   adapterr   r  s       r+   rG   BaseConnection.__init__  s     !gg//---4
68 8N~f++F33--,2
46 6M444--,8
:< <**%%//99; 	;   ,,]LNK$%Dr.   c                     U R                   $ )z$The adapter used by this connection.)r  rJ   s    r+   r  BaseConnection.adapterB  s     >>r.   c                     U R                   $ )z2The default configuration used by this connection.)r  rJ   s    r+   r   BaseConnection.configG  s     ==r.   c                 h    [        U[        5      (       a   eU R                  R                  U5        g)znAdd an RPC object to the list of pending RPCs.

The argument must be a UserRPC object, not a MultiRpc object.
N)r   r   r  addr  s     r+   _add_pendingBaseConnection._add_pendingN  s+    
 #x((((C r.   c                     [        U[        5      (       a%  UR                   H  nU R                  U5        M     g U R                  R                  U5        g! [         a     gf = f)zRemove an RPC object from the list of pending RPCs.

If the argument is a MultiRpc object, the wrapped RPCs are removed
from the list of pending RPCs.
N)r   r   rl  _remove_pendingr  remover   rE   r{  wrapped_rpcs      r+   r  BaseConnection._remove_pendingV  s^     #x   ,,+[) -""3'  	s   A 
A%$A%c                     [        U[        5      (       a,  UR                   H  nU R                  U5      (       d  M    g   gXR                  ;   $ )a  Check whether an RPC object is currently pending.

Note that 'pending' in this context refers to an RPC associated
with this connection for which _remove_pending() hasn't been
called yet; normally this is called by check_rpc_success() which
itself is called by the various result hooks.  A pending RPC may
be in the RUNNING or FINISHING state.

If the argument is a MultiRpc object, this returns true if at least
one of its wrapped RPCs is pending.
TF)r   r   rl  
is_pendingr  r  s      r+   r  BaseConnection.is_pendingi  sG     #x  ,,+??;'' - ''''r.   c                 ,    [        U R                  5      $ )z6Return (a copy of) the list of currently pending RPCs.)r  r  rJ   s    r+   get_pending_rpcsBaseConnection.get_pending_rpcs}  s    t""##r.   c                     [        U5      $ )r6   )r<   )rE   r:   s     r+   get_datastore_type!BaseConnection.get_datastore_type  s     S!!r.   c                    U R                   (       a   [        R                  R                  U R                   5      nUc  [
        R                  " S5        MV  UR                  [        R                  R                  :X  d   eXR                   ;   a   U R                  U5        U R                   (       a  M  gg! [         a    [
        R                  " SSS9   M  f = f! [         a    [
        R                  " SSS9   N\f = f)z0Wait for all currently pending RPCs to complete.z4wait_for_all_pending_rpcs(): exception in wait_any()T)exc_infoNzwait_any() returned Nonez=wait_for_all_pending_rpcs(): exception in check_rpc_success())r  r   r   r  	Exceptionlogginginfodebugr  r   r_  r`  check_rpc_successr  s     r+   wait_for_all_pending_rpcs(BaseConnection.wait_for_all_pending_rpcs  s    


	''001D1DE 
01YY,**44444	##	#	&

 
 
%/ 


  
 	K"	$*  	&
,, : $&	&s#   )B7 C 7CCC?>C?c                    ^^ [         R                  XR                  5      n[         R                  XR                  5      mSnUc  U R                  nTb  UU4S jn[
        R                  " X#U5      mT$ )a^  Create an RPC object using the configuration parameters.

Internal only.

Args:
  config: Optional Configuration object.
  service_name: Optional datastore service name.

Returns:
  A new UserRPC object with the designated settings.

NOTES:

(1) The RPC object returned can only be used to make a single call
    (for details see apiproxy_stub_map.UserRPC).

(2) To make a call, use one of the specific methods on the
    Connection object, such as conn.put(entities).  This sends the
    call to the server but does not wait.  To wait for the call to
    finish and get the result, call rpc.get_result().
Nc                     > T " T5      $ r@   r3   )r6  r{  s   r+   callback,BaseConnection._create_rpc.<locals>.callback  s    S!!r.   )r   r3  r  r6  r  r   r   )rE   r   service_namer3  r  r6  r{  s        @@r+   _create_rpcBaseConnection._create_rpc  sg    , %%fmm<H!//FMH &&l "

#
#LH
ECJr.   c                    [        U[        R                  5      (       a  [        USS5      nO[        R                  U5      nUc  U R                  R
                  n[        US5      (       ao  [        US5      (       a^  U[        R                  :X  a  UR                  S5        gU[        R                  :X  a#  UR                  S5        UR                  S5        gg[        US5      (       a?  U[        R                  :X  a*  [        R                  R                  UR                  l        gg["        R$                  " S	5      e)
a  Set the read policy on a request.

This takes the read policy from the config argument or the
configuration's default configuration, and sets the request's read
options.

Args:
  request: A read request protobuf.
  config: Optional Configuration object.

Returns:
  True if the read policy specifies a read current request, False if it
    specifies an eventually consistent request, None if it does
    not specify a read consistency.
r:  Nset_failover_msstrongTFread_optionsz1read_policy is only supported on read operations.)r   r   r   getattrr   r:  r  hasattrrU  
set_strongrT  r  r   ReadOptionsEVENTUALr  read_consistencyr	   BadRequestError)rE   requestr   r:  s       r+   _set_request_read_policy'BaseConnection._set_request_read_policy  s   " &+3344FM48k!--f5k MM--kw)**ww/I/I	@@	@4 -<<<5! 	#	.	)	) 
::	:''00 	-,,
=? ?r.   c                     g)a  Set the current transaction on a request.

NOTE: This version of the method does nothing.  The version
overridden by TransactionalConnection is the real thing.

Args:
  request: A protobuf with a transaction field.

Returns:
  An object representing a transaction or None.
Nr3   )rE   r  s     r+   _set_request_transaction'BaseConnection._set_request_transaction  s     r.   c                     [        U[        R                  5      (       a  UnOU R                  X5      nUR	                  [
        R                  " U5      X4XV5        U R                  U5        U$ )a  Make an RPC call.

Internal only.

Except for the added config argument, this is a thin wrapper
around UserRPC.make_call().

Args:
  config: A Configuration object or None.  Defaults are taken from
    the connection's default configuration.
  method: The method name.
  request: The request protocol buffer.
  response: The response protocol buffer.
  get_result_hook: Optional get-result hook function.  If not None,
    this must be a function with exactly one argument, the RPC
    object (self).  Its return value is returned from get_result().
  user_data: Optional additional arbitrary data for the get-result
    hook function.  This can be accessed as rpc.user_data.  The
    type of this value is up to the service module.

Returns:
  The UserRPC object used for the call.
)r   r   r   r  	make_callr   ensure_binaryr  )	rE   r   methodr  responseget_result_hook	user_datar  r{  s	            r+   _make_rpc_callBaseConnection._make_rpc_call  s^    8 &+3344cV2cMM***62G!.cJr.   c                      UR                  5         U R                  U5         UR                  5         g! U R                  U5        f = f! [        R                   a  n[        U5      eSnAff = f)a  Check for RPC success and translate exceptions.

This wraps rpc.check_success() and should be called instead of that.

This also removes the RPC from the list of pending RPCs, once it
has completed.

Args:
  rpc: A UserRPC or MultiRpc object.

Raises:
  Nothing if the call succeeded; various datastore_errors.Error
  subclasses if ApplicationError was raised by rpc.check_success().
N)r  r  r  r   ApplicationError_ToDatastoreErrorrE   r{  r   s      r+   r   BaseConnection.check_rpc_successC  se     	hhj 3#	 3 ++ #c""#s    5 A AA/A**A/i   i  i  
   c                 f    [         R                  XR                  5      =(       d    U R                  $ )zFInternal helper: figures out max_entity_groups_per_rpc for the config.)r   rB  r  !DEFAULT_MAX_ENTITY_GROUPS_PER_RPC)rE   r   s     r+   __get_max_entity_groups_per_rpc.BaseConnection.__get_max_entity_groups_per_rpcl  s,    22 I"&"H"HIr.   c                 f   [         (       a+  [        U[        R                  5      (       a  UR                  n[        U[
        R                  5      (       a  UR	                  5       n[         (       aS  [        U[        R                  5      (       a4  UR                  S   nUR                  nUR                  nUR                  nOOUR                  5       R                  S5      nUR                  5       nUR                  5       nUR                  5       nXS=(       d    U=(       d    S[        U5      44$ )a  Internal helper: extracts the entity group from a key or entity.

Supports both v3 and v1 protobufs.

Args:
  value: an entity_pb.{Reference, EntityProto} or
      googledatastore.{Key, Entity}.

Returns:
  A tuple consisting of:
    - kind
    - name, id, or ('new', unique id)
r   new)r  r   r   r   ri   r   ra   r{   pathidr   kindelementr   )rE   r   elemelem_id	elem_namer  s         r+   _extract_entity_group$BaseConnection._extract_entity_groupq  s      Juo6L6L$M$Miie%..//iikeJuo6I6I$J$JZZ]dg))iYYdZZ\!!!$dYY[d	g))+i ;Y;5"T(*;<<r.   c                     [         R                  " [        5      n[        U5       H'  u  pVU" U5      nXC" U5         R	                  Xu45        M)     [        UR                  5       5      $ )a  Internal helper: map values to keys and group by key. Here key is any
object derived from an input value by map_fn, and which can be grouped
by group_fn.

Args:
  values: The values to be grouped by applying get_group(to_ref(value)).
  map_fn: a function that maps a value to a key to be grouped.
  group_fn: a function that groups the keys output by map_fn.

Returns:
  A list where each element is a list of (key, index) pairs.  Here
  index is the location of the value from which the key was derived in
  the original list.
)collectionsdefaultdictrr  	enumerater   values)rE   r  map_fngroup_fnindexed_key_groupsindexr   ri   s           r+   _map_and_groupBaseConnection._map_and_group  s_     %006!&)5Mc#'..|< * "))+,,r.   c                    ^ U4S jnU$ )a  Internal helper: build a function that ties an index with each result.

Args:
  indexes: A list of integers.  A value x at location y in the list means
    that the result at location y in the result list needs to be at location
    x in the list of results returned to the user.
c                 .   > [        [        U T5      5      $ r@   )rr  zip)r  indexess    r+   create_result_index_pairsMBaseConnection.__create_result_index_pairs.<locals>.create_result_index_pairs  s    #gw'((r.   r3   )rE   r  r  s    ` r+   __create_result_index_pairs*BaseConnection.__create_result_index_pairs  s    )$$r.   c                    ^ U4S jnU$ )aJ  Builds a function that sorts the indexed results.

Args:
  extra_hook: A function that the returned function will apply to its result
    before returning.

Returns:
  A function that takes a list of results and reorders them to match the
  order in which the input values associated with each results were
  originally provided.
c                 Z   > S /[        U 5      -  nU  H	  u  p#X!U'   M     Tb  T" U5      nU$ r@   )r#   )result_index_pairsr  r  r  ro  s       r+   sort_result_index_pairsIBaseConnection.__sort_result_index_pairs.<locals>.sort_result_index_pairs  s=    /00g--& .		W%nr.   r3   )rE   ro  r  s    ` r+   __sort_result_index_pairs(BaseConnection.__sort_result_index_pairs  s     #"r.   c              #     #    [         R                  XPR                  5      =(       d    U R                  n/ n/ nUn	Sn
U H  nU
S-  n
Ub  X:  a  Xx4v   / n/ nUn	Sn
U H  nUu  pUR	                  5       S-   n[        U[        R                  5      (       d+  [        U5      U:  d  U(       a  X-   U:  a  Xx4v   / n/ nUn	Sn
UR                  U5        UR                  U5        X-  n	M     M     Xx4v   g7f)a  Internal helper: repeatedly yield a list of 2 elements.

Args:
  grouped_values: A list of lists.  The inner lists consist of objects
    grouped by e.g. entity group or id sequence.

  base_size: An integer representing the base size of an rpc.  Used for
    splitting operations across multiple RPCs due to size limitations.

  max_count: An integer representing the maximum number of objects we can
    send in an rpc.  Used for splitting operations across multiple RPCs.

  max_groups: An integer representing the maximum number of groups we can
    have represented in an rpc.  Can be None, in which case no constraint.

  config: The config object, defining max rpc size in bytes.

Yields:
  Repeatedly yields 2 element tuples.  The first element is a list of
  protobufs to send in one batch.  The second element is a list containing
  the original location of those protobufs (expressed as an index) in the
  input.
r   r!   N   )
r   rH  r  MAX_RPC_BYTESByteSizer   r   r   r#   r   )rE   grouped_values	base_size	max_count
max_groupsr   max_sizepbs
pb_indexessize
num_groupsindexed_pbs
indexed_pbrS   r  	incr_sizes                   r+   _generate_pb_lists!BaseConnection._generate_pb_lists  s    2 ++FMMB #"" 
CJDJ%Aoj		J$;

#*  KKMA%	
 6#4#<#<==X"st/?(/J!
!#*$*

2% + $ &< 
s   C4C6c                     [        U[        R                  [        R                  [        R                  45      (       a  UR                  S5        gg)z'Configure a request to force mutations.TN)r   r   
PutRequestTouchRequestDeleteRequest	set_force)rE   reqs     r+   __forceBaseConnection.__force  sC    #//$11$224 5 5 
mmD5r.   c                 B    U R                  SU5      R                  5       $ )zSynchronous Get operation.

Args:
  keys: An iterable of user-level key objects.

Returns:
  A list of user-level entity objects and None values, corresponding
  1:1 to the argument keys.  A None means there is no entity for the
  corresponding key.
N)	async_getr  rE   keyss     r+   r   BaseConnection.get  s     >>$%0022r.   c           
        ^ ^ SUU 4S jjnT R                   [        :X  a,  [        R                  " 5       nT R                  R
                  nO<[        R                  " 5       nUR                  S5        T R                  R                  nT R                  UT5      nT R                  U5      n[        T[        R                  5      (       d  [        U5      S::  a   U V	s/ s H
  o" U	5      PM     n
n	U" XZU5      $ [         R#                  TT R$                  5      =(       d    T R&                  nT R)                  X&T R*                  5      nUc!  T R-                  5       [.        R0                  :H  nU(       a  Uc  T R3                  T5      nOSnT R5                  UUR7                  5       UUT5      n/ nU H-  u  n
nUR9                  U" XZT R;                  U5      5      5        M/     [=        UT R?                  U5      5      $ s  sn	f )a;  Asynchronous Get operation.

Args:
  config: A Configuration object or None.  Defaults are taken from
    the connection's default configuration.
  keys: An iterable of user-level key objects.
  extra_hook: Optional function to be called on the result once the
    RPC has completed.

Returns:
  A MultiRpc object.
Nc           
        > [         R                  " U 5      nTR                  [        :X  a3  SnUR                  R                  U5        [        R                  " 5       nO6SnUR                  5       R                  U5        [        R                  " 5       nTX4nTR                  TXCUTR                  UTR                  S9$ )NLookupGetr  r  r  )r	  deepcopyr  r  r:  r  r   LookupResponsekey_listr   GetResponser  _BaseConnection__get_hook)	base_reqr&  ro  r4  r  respr  r   rE   s	          r+   make_get_call/BaseConnection.async_get.<locals>.make_get_call)  s    MM(#c			1	1--/c"'') #)i  d15+4.2.?.? ! A Ar.   Tr!   r@   ) r  r  r   LookupRequestr  r~   r   
GetRequestset_allow_deferredrx   r  r  r   r   r   r#   r   rK  r  MAX_GET_KEYSr  r  r  r   r9   ._BaseConnection__get_max_entity_groups_per_rpcr-  r   r   *_BaseConnection__create_result_index_pairsr   (_BaseConnection__sort_result_index_pairs)rE   r   r:  ro  rH  rF  rx   is_read_currenttxnri   r&  r#  indexed_keys_by_entity_groupmax_egs_per_rpcpbsgenrn  r  s   ``               r+   r8  BaseConnection.async_get  s   A A. // ..0h..--i((*h!!$'..**i33HfEO

'
'
1C &+3344D	Q'+,tYs^tc,8*55++FDMMB #""  $(#6#633$5  002'BBCo 3;<<VDoo $$%A%-%6%6%8)%4f>F DW
kk- $ @ @ IK L  D$88DEE? -s   G=c                    U R                  U5        UR                  u  p#nU R                  [        :X  a  UR                  R                  5       (       aw  / nUR                  R                  5        HU  nUR                  5       (       a*  U R                  R                  UR                  5       5      nOSnUR                  U5        MW     GO-UR                  n0 n	U R                  UU	5        [        R                  " UR                  5      n
U R                  [         :X  a  Sn["        R$                  " 5       nUR&                  (       a  U
R)                  S5        U
R*                  R-                  UR&                  5        UR/                  5         U R1                  X+XU R                  S9nUR3                  5         UR                  nU R                  UU	5        UR&                  (       a  M  OSn[4        R6                  " 5       nUR9                  5       (       a  U
R;                  5         U
R=                  5       R-                  UR9                  5       5        UR/                  5         U R1                  X+XU R                  S9nUR3                  5         UR                  nU R                  UU	5        UR9                  5       (       a  M  U Vs/ s H(  nU	R?                  [@        RB                  " U5      5      PM*     nnUb  U" U5      nU$ s  snf ):Internal method used as get_result_hook for Get operation.Nr>  r:  r  r?  )"r  r  r  _DATASTORE_V3r  in_orderentity_list
has_entityr  r^   r   r   2_BaseConnection__add_get_response_entities_to_dictr	  rA  r  r  r   rB  deferred
ClearFieldr:  r  Clearr  r  r   rD  deferred_list	clear_keyrC  r   r
   ReferenceToKeyValue)rE   r{  r   keys_from_requestro  entitiesentity_resultr   current_get_responseresult_dictdeferred_reqr  deferred_respdeferred_rpcrS   s                  r+   
__get_hookBaseConnection.__get_hookm  s   3 -0MM)FzM)cll.C.C.E.E h<<335-##%%>>..}/C/C/EF&& 6 !\\k
../C/:<
 ]]3;;/l			1	1'668"++

!
!&
)



"
"#7#@#@
A



,,V-9:>:K:K - M, 
!
!
#!-!6!6
 
2
23G3>@ #+++ $002"0022

 
 
"



!
(
()=)K)K)M
N



,,V-9:>:K:K - M, 
!
!
#!-!6!6
 
2
23G3>@ #0022" ./-b ///"E"Eb"IJ-  /
 H%hO/s   /Lc                 F   [         (       a  [        U[        R                  5      (       ah  UR                   HW  nUR
                  R                  nU R                  R                  UR
                  S5      nXR[        R                  " U5      '   MY     gUR                  5        H{  nUR                  5       (       d  M  UR                  5       R                  5       n[        R                  " U5      nU R                  R                  UR                  5       5      nXRU'   M}     g)aU  Converts entities from the get response and adds them to the dict.

The Key for the dict will be calculated via
datastore_types.ReferenceToKeyValue.  There will be no entry for entities
that were not found.

Args:
  get_response: A datastore_pb.GetResponse or
      googledatastore.LookupResponse.
  result_dict: The dict to add results to.
FN)r  r   r   rB  foundr   ri   r  re   r
   rd  r\  r]  r^   )	rE   get_responseri  r  r}   r   rg  reference_pbhashable_keys	            r+   #__add_get_response_entities_to_dict2BaseConnection.__add_get_response_entities_to_dict  s     	! |_%C%CDD &&&""//uECIO77?@ '
 (335-##%%
 '--/335,(<<\J,>>..}/C/C/EF&&,l
# 6r.   c                 @    U R                  S5      R                  5       $ )zQSynchronous get indexes operation.

Returns:
  user-level indexes representation
N)async_get_indexesr  rJ   s    r+   get_indexesBaseConnection.get_indexes  s     !!$'2244r.   c           
          [         R                  " 5       nUR                  [        R                  " U5      5        [         R
                  " 5       nU R                  USXEU R                  U[        S9$ )a  Asynchronous get indexes operation.

Args:
  config: A Configuration object or None.  Defaults are taken from
    the connection's default configuration.
  extra_hook: Optional function to be called once the RPC has completed.

Returns:
  A MultiRpc object.

GetIndicesr@  )	r   GetIndicesRequest
set_app_idr
   r7   CompositeIndicesr  !_BaseConnection__get_indexes_hookrZ  )rE   r   ro  _appr4  rG  s         r+   rw   BaseConnection.async_get_indexes  sd     
(
(
*CNN?//56((*Dv|S/3/F/F)3,9  ; ;r.   c                     U R                  U5        UR                  R                  5        Vs/ s H  nU R                  R	                  U5      PM      nnUR
                  (       a  UR                  U5      nU$ s  snf )rX  )r  r  
index_listr  rq   r  )rE   r{  r  r  s       r+   __get_indexes_hook!BaseConnection.__get_indexes_hook  sk    3LL335755 ~~))%05  7
}}g&gN	7s   %A9c                 B    U R                  SU5      R                  5       $ )a(  Synchronous Put operation.

Args:
  entities: An iterable of user-level entity objects.

Returns:
  A list of user-level key objects, corresponding 1:1 to the
  argument entities.

NOTE: If any of the entities has an incomplete key, this will
*not* patch up those entities with the complete key.
N)	async_putr  )rE   rf  s     r+   putBaseConnection.put  s     >>$)4466r.   c           
      ~  ^ ^ SUU 4S jjnT R                   [        :X  aK  [        R                  " 5       n[        R                  R                  Ul        T R                  R                  nO+[        R                  " 5       nT R                  R                  nT R                  U5        [        R                  TT R                  5      (       a  T R                  U5        [!        T["        R$                  5      (       d  ['        U5      S::  a   U Vs/ s H
  ov" U5      PM     nnU" XXU5      $ [        R)                  TT R                  5      =(       d    T R*                  n	T R                   [        :X  a  UR,                  (       a  UR/                  5       (       d  T R1                  T5      n
OSn
T R3                  X&T R4                  5      nT R7                  UUR9                  5       U	U
T5      n/ nU H,  u  pUR;                  U" XXT R=                  U5      5      5        M.     [?        UT RA                  U5      5      $ s  snf )a  Asynchronous Put operation.

Args:
  config: A Configuration object or None.  Defaults are taken from
    the connection's default configuration.
  entities: An iterable of user-level entity objects.
  extra_hook: Optional function to be called on the result once the
    RPC has completed.

 Returns:
  A MultiRpc object.

NOTE: If any of the entities has an incomplete key, this will
*not* patch up those entities with the complete key.
Nc           
        > [         R                  " U 5      nT	R                  [        :X  aV  U H8  nUR                  R                  5       nUR                  R                  U5        M:     Sn[        R                  " 5       nO6UR                  5       R                  U5        Sn[        R                  " 5       nX4nT	R                  TXcUT	R                  UT	R                  S9$ )NCommitPutr@  )r	  rA  r  r  	mutationsr  upsertCopyFromr   CommitResponser\  r  r   PutResponser  _BaseConnection__put_hook)
rF  r&  r  r4  r   mutationr  rG  r   rE   s
           r+   make_put_call/BaseConnection.async_put.<locals>.make_put_call  s    MM(#c			1	1F]]&&((
//
"
"6
*  --/  %'').i  d15+4.2.?.? ! A Ar.   r!   r@   )!r  r  r   CommitRequestNON_TRANSACTIONALmoder  r   r   r0  r   r  r   r>  r  _BaseConnection__forcer   r   r   r#   rN  MAX_PUT_ENTITIEStransactionhas_transactionrN  r  r  r-  r   r   rO  r   rP  )rE   r   rf  ro  r  rF  r   r   r&  r#  rT   indexed_entities_by_entity_grouprU  rn  r  s   ``             r+   r  BaseConnection.async_put  s   "A A& // ..0h%33EEhm^^33l((*h^^00l!!(+!!&$--88
ll8 &+3344H8J089f\&!c98*55//F '&& 			1	1!!$$&&<<VDoo'+':': : :(<$
 $$%E%-%6%6%8)%4f>F D
kk- $ @ @ IK L  D$88DEE3 :s   H:c                    U R                  U5        UR                  u  p#[        (       a  [        UR                  [
        R                  5      (       a  / nSnU H|  n[        R                  " UR                  5      (       a  UR                  UR                  5        ME  UR                  UR                  R                  U   R                  5        US-  nM~     U Vs/ s H  opR                  R                  U5      PM     nnOBUR                  R                  5        Vs/ s H  opR                  R                  U5      PM     nnUb  U" U5      nU$ s  snf s  snf )z:Internal method used as get_result_hook for Put operation.r   r!   )r  r  r  r   r  r   r  r   is_complete_v1_keyri   r   mutation_resultsr  r[   rC  rT   )rE   r{  entities_from_requestro  r:  ir   ri   s           r+   
__put_hookBaseConnection.__put_hookT  s   3(+%  s||_%C%CDDd
a)&++FJJ77
++fjj
!
++cll33A6::
;
q&! * ;??$3nn))#.$d?d7:||7L7L7NO7Nnn&&s+7NdO dK @Os   $E!$Ec                 B    U R                  SU5      R                  5       $ )zfSynchronous Delete operation.

Args:
  keys: An iterable of user-level key objects.

Returns:
  None.
N)async_deleter  r9  s     r+   deleteBaseConnection.deletem  s      T4(3355r.   c                 >  ^ ^ SUU 4S jjnT R                   [        :X  aK  [        R                  " 5       n[        R                  R                  Ul        T R                  R                  nO+[        R                  " 5       nT R                  R                  nT R                  U5        [        R                  TT R                  5      (       a  T R                  U5        [!        T["        R$                  5      (       d  ['        U5      S::  a   U Vs/ s H
  ov" U5      PM     nnU" XXU5      $ [        R)                  TT R                  5      =(       d    T R*                  n	T R                   [        :X  a  UR,                  (       a  UR/                  5       (       d  T R1                  T5      n
OSn
T R3                  X&T R4                  5      nT R7                  UUR9                  5       U	U
T5      n/ nU H  u  pUR;                  U" XX5      5        M     [=        X5      $ s  snf )a,  Asynchronous Delete operation.

Args:
  config: A Configuration object or None.  Defaults are taken from
    the connection's default configuration.
  keys: An iterable of user-level key objects.
  extra_hook: Optional function to be called once the RPC has completed.

Returns:
  A MultiRpc object.
Nc           
        > [         R                  " U 5      nT	R                  [        :X  aV  U H8  nUR                  R                  5       nUR                  R                  U5        M:     Sn[        R                  " 5       nO6UR                  5       R                  U5        Sn[        R                  " 5       nT	R                  TXcUT	R                  UT	R                  S9$ )Nr  Deleter@  )r	  rA  r  r  r  r  r  r  r   r  rC  r  r   DeleteResponser  _BaseConnection__delete_hook)
rF  r&  r  r4  rS   r  r  rG  r   rE   s
           r+   make_delete_call5BaseConnection.async_delete.<locals>.make_delete_call  s    MM(#c			1	1B]]&&((
//
"
"2
&  --/c"**,  d151C1C+4.2.?.? ! A Ar.   r!   r@   )r  r  r   r  r  r  r  r~   r   r2  rx   r  r   r>  r  r  r   r   r   r#   rQ  MAX_DELETE_KEYSr  r  rN  r  r  r-  r   r   r   )rE   r   r:  ro  r  rF  rx   ri   r&  r#  rT  rS  rU  rn  _s   ``             r+   r  BaseConnection.async_deletex  s   A A$ // ..0h%33EEhm..--i++-h..**i!!(+!!&$--88
ll8 &+3344D	Q'+,tYs^tc,hZ88..vt}}E &%% 			1	1!!$$&&<<VDoo#'#6#633$5 
 $$%A%-%6%6%8)%4f>F D
kk"812 D%%1 -s   Hc                 d    U R                  U5        UR                  b  UR                  S5        gg)z=Internal method used as get_result_hook for Delete operation.N)r  r  r  s     r+   __delete_hookBaseConnection.__delete_hook  s+    3
}} 	mmD !r.   c                 D    U R                  SXU5      R                  5       $ )am  Synchronous BeginTransaction operation.

NOTE: In most cases the new_transaction() method is preferred,
since that returns a TransactionalConnection object which will
begin the transaction lazily.

Args:
  app: Application ID.
  previous_transaction: The transaction to reset.
  mode: The transaction mode.

Returns:
  An object representing a transaction or None.
N)async_begin_transactionr  )rE   r:   previous_transactionr  s       r+   begin_transaction BaseConnection.begin_transaction  s"    $ ((s$OZ\r.   c           	      f   [        U[        R                  5      (       a  U(       d  [        R                  " SU< S35      eUb*  U[
        R                  :X  a  [        R                  " S5      eU R                  [        :X  a  [        R                  " 5       n[        R                  " 5       nUb  [
        R                  nU[
        R                  :X  a  GOU[
        R                  :X  a&  UR                  R                  R!                  5         GO|U[
        R                  :X  aD  Ub  UUR                  R"                  l        GOHUR                  R"                  R!                  5         GO"[&        R                  " 5       nUR)                  U5        [*        R-                  XR.                  5      (       a  UR1                  S5        U[
        R                  :X  a  O{U[
        R                  :X  a*  UR3                  [&        R                  R                  5        O=U[
        R                  :X  a)  UR3                  [&        R                  R                  5        Ub  UR5                  5       R7                  U5        [&        R8                  " 5       nU R;                  USXVU R<                  U R                  S9$ )a%  Asynchronous BeginTransaction operation.

Args:
  config: A configuration object or None.  Defaults are taken from
    the connection's default configuration.
  app: Application ID.
  previous_transaction: The transaction to reset.
  mode: The transaction mode.

Returns:
  A MultiRpc object.
z7begin_transaction requires an application id argument (r   zRbegin_transaction requires mode != READ_ONLY when previous_transaction is not NoneTBeginTransactionr  r  )r   r   string_typesr	   r   r   r  r  r  r   BeginTransactionRequestBeginTransactionResponser  r  transaction_options	read_onlySetInParent
read_writer  r   set_appr   xgr  set_allow_multiple_egset_modemutable_previous_transactionr  Transactionr  '_BaseConnection__begin_transaction_hook)rE   r   r:   r  r  r4  rG  s          r+   r  &BaseConnection.async_begin_transaction  s   " c:22333--JM
OQ Q 'DO4M4M,M--- 
 //335c557d 
	)))	((	(?,,,))557?---+$8 ""-- 

!
!
,
,
8
8
:002c	kk#



6
6!!$'	((	(?,,,\99CCD?---\99DDE		)((*334HI%%'dv'93/3/L/L,0,=,=  ? ?r.   c                     U R                  U5        U R                  [        :X  a  UR                  R                  $ UR                  $ )z=Internal method used as get_result_hook for BeginTransaction.)r  r  r  r  r  r  s     r+   __begin_transaction_hook'BaseConnection.__begin_transaction_hook  s9    3//\\%%%\\r.   )	__adapter__config__pending_rpcsr  r@   NNNNN)>r%   r   r   r   r   r8   PRIMARY_STANDBY_DATASTOREr9   r   rZ  r  r  r4   rG   r  r  r   r  r  r  r  r  r  r  
create_rpcr  r  r  make_rpc_callr  r  rM  r  r  MAX_ALLOCATE_IDS_KEYSr  rN  r  r  rO  rP  r-  r  r   r8  rE  r^  rx  rw  r  r  r  r  r  r  r  r   r  r  r  r  r   r3   r.   r+   r   r     s   2h  "M$7$9 : q>!$] $  $ P    !&(($"&F&R *4?l 6:"&#L !-#< -,/ ')#I
=@-*
%#,=~3PFdGR->5;&7JFX2	6D&L .2,440 48#2#:#:	@?Dr.   r   c                      ^  \ rS rSrSr\" S5      SS\4U 4S jj5       rSS\R                  4S jr
SS jr  SS jrS	 rS
 rSS jrS rSrU =r$ )r   i'  zTransaction-less connection class.

This contains those operations that are not allowed on transactional
connections.  (Currently only allocate_ids and reserve_key_ids.)
r!   Nc                 n   > [         [        U ]  XUS9  U R                  U l        U R
                  U l        g)r  r  r   r  N)r   r   rG   r  _Connection__adapterr   _Connection__config)rE   r  r   r  r   s       r+   rG   Connection.__init__.  s5     
*d$W2> % @\\DNKKDMr.   c                 z    U R                   R                  U5      n[        U R                  UU R                  UUS9$ )a  Create a new transactional connection based on this one.

This is different from, and usually preferred over, the
begin_transaction() method; new_transaction() returns a new
TransactionalConnection object.

Args:
  config: A configuration object for the new connection, merged
    with this connection's config.
  previous_transaction: The transaction being reset.
  mode: The transaction mode.
)r  r   r  r  r  )r  r  r   r  r  )rE   r   r  r  s       r+   new_transactionConnection.new_transaction@  s<     ]]  (F"4>>&040A0A8L(,. .r.   c                 D    U R                  SXU5      R                  5       $ )a  Synchronous AllocateIds operation.

Exactly one of size and max must be specified.

Args:
  key: A user-level key object.
  size: Optional number of IDs to allocate.
  max: Optional maximum ID to allocate.

Returns:
  A pair (start, end) giving the (inclusive) range of IDs allocation.
N)async_allocate_idsr  )rE   ri   r(  rw  s       r+   allocate_idsConnection.allocate_idsV  s"     ""4C8CCEEr.   c           
      X   Ub  Ub  [         R                  " S5      e[        U[        R                  5      (       d  [         R                  " SU< S35      eU[
        :  a"  [         R                  " S[
        < SU< 35      eUS::  a  [         R                  " SU-  5      eUbY  [        U[        R                  5      (       d  [         R                  " SU< S35      eUS:  a  [         R                  " S	U-  5      e[        R                  " 5       nUR                  5       R                  U R                  R                  U5      5        Ub  UR                  U5        Ub  UR                  U5        [        R                  " 5       nU R                  US
XgU R                   U["        S9nU$ )a  Asynchronous AllocateIds operation.

Args:
  config: A Configuration object or None.  Defaults are taken from
    the connection's default configuration.
  key: A user-level key object.
  size: Optional number of IDs to allocate.
  max: Optional maximum ID to allocate.
  extra_hook: Optional function to be called on the result once the
    RPC has completed.

Returns:
  A MultiRpc object.
z+Cannot allocate ids using both size and maxzInvalid size (r   zCannot allocate more than z ids at a time; received r   z+Cannot allocate less than 1 id; received %szInvalid max (z>Cannot allocate a range with a max less than 0 id; received %sAllocateIdsr@  )r	   r   r   r   r0  _MAX_ID_BATCH_SIZEr   AllocateIdsRequestmutable_model_keyr  r  rx   set_sizeset_maxAllocateIdsResponser  _Connection__allocate_ids_hookrZ  )	rE   r   ri   r(  rw  ro  r4  rG  r{  s	            r+   r  Connection.async_allocate_idse  s     	//
79 	9j6677//t0MNN	"	"//'( 	( 
//
7$
>@ 	@
Z5566//c0KLL	q//
J
 	 
)
)
+C$$T^^%=%=c%BC	ll4
	kk#++-D


fmS.2.F.F(2+8  :C Jr.   c                     U R                  U5        UR                  R                  5       UR                  R                  5       4nUR                  b  UR	                  U5      nU$ )z8Internal method used as get_result_hook for AllocateIds.)r  r  startendr  )rE   r{  pairs      r+   __allocate_ids_hookConnection.__allocate_ids_hook  sQ    3<<!1!1!33D
}} ]]4 dKr.   c                 D    U R                  SU5      R                  5         g)zSynchronous AllocateIds operation to reserve the given keys.

Sends one or more v3 AllocateIds rpcs with keys to reserve.
Reserved keys must be complete and must have valid ids.

Args:
  keys: Iterable of user-level keys.
N)_async_reserve_keysr  r9  s     r+   _reserve_keysConnection._reserve_keys  s     	T4(335r.   c                   ^  U 4S jnT R                  UT R                  R                  U5      n[        R	                  UT R
                  5      =(       d    T R                  n/ nT R                  USUSU5      nU H  u  p[        R                  " 5       nUR                  5       R                  U	5        [        R                  " 5       nUR                  T R                  USXT R                  U[         S95        M     [#        U5      $ )a  Asynchronous AllocateIds operation to reserve the given keys.

Sends one or more v3 AllocateIds rpcs with keys to reserve.
Reserved keys must be complete and must have valid ids.

Args:
  config: A Configuration object or None to use Connection default.
  keys: Iterable of user-level keys.
  extra_hook: Optional function to be called on rpc result.

Returns:
  None, or the result of user-supplied extra_hook.
c                 l   > U R                  5       R                  5       S:X  a  gTR                  U 5      $ )Nr!   
root_idkey)r  element_sizer  )ri   rE   s    r+   	to_id_key1Connection._async_reserve_keys.<locals>.to_id_key  s.    		 	 	"a	'))#..r.   r   Nr  r@  )r  r  rx   r   rE  r  r  r-  r   r  reserve_listr  r  r   r  _Connection__reserve_keys_hookrZ  r   )rE   r   r:  ro  r   keys_by_idkeyr#  rn  rU  r&  r  r4  rG  s   `            r+   r  Connection._async_reserve_keys  s    / ''dnn.F.F(13M44VT]]K ,++  D$$]Ay$OF++-c	$--/d
kk$%%fmS6:6N6N0:3@ & B C	  D>r.   c                 v    U R                  U5        UR                  b  UR                  UR                  5      $ g)z+Internal get_result_hook for _reserve_keys.N)r  r  r  r  s     r+   __reserve_keys_hookConnection.__reserve_keys_hook  s2    3
}} ]]3<<(( !r.   )r  r  r  r  r@   )r%   r   r   r   r   r4   rZ  rG   r   r  r  r  r  r  r  r  r  r   r   r   s   @r+   r   r   '  sk     q>!$]    " $(d*22.,F <@$(/b	6#J) )r.   r   c                       \ rS rSrSrSr Sr Sr Sr \	" \\\\45      r
\S 5       r\S 5       r\S	 5       r\S
 5       rSrg)r   i  z;An immutable class that contains options for a transaction.r!   r.        c                 d    U [         R                  ;  a  [        R                  " SU < S35      eU $ )aX  How existing transactions should be handled.

One of NESTED, MANDATORY, ALLOWED, INDEPENDENT. The interpertation of
these types is up to higher level run-in-transaction implementations.

WARNING: Using anything other than NESTED for the propagation flag
can have strange consequences.  When using ALLOWED or MANDATORY, if
an exception is raised, the transaction is likely not safe to
commit.  When using INDEPENDENT it is not generally safe to return
values read to the caller (as they were not read in the caller's
transaction).

Raises: datastore_errors.BadArgumentError if value is not reconized.
zUnknown propagation value (r   )r   _PROPAGATIONr	   r   r2  s    r+   propagationTransactionOptions.propagation  s3      &333--/4/7 8 8Lr.   c                 f    [        U [        5      (       d  [        R                  " SU < S35      eU $ )znWhether to allow cross-group transactions.

Raises: datastore_errors.BadArgumentError if value is not a bool.
zxg argument should be bool (r   r=  r2  s    r+   r  TransactionOptions.xg  s/     eT""--/4
68 8Lr.   c                 P    [         R                  " U S[        R                  SS9  U $ )zHow many retries to attempt on the transaction.

The exact retry logic is implemented in higher level run-in-transaction
implementations.

Raises: datastore_errors.BadArgumentError if value is not an integer or
  is not greater than zero.
retriesT)zero_ok)r
   ValidateIntegerr	   r   r2  s    r+   r  TransactionOptions.retries		  s*     ##E$-$4$E$E,02 Lr.   c                 R    [         R                  " U S[        R                  5        U $ )zThe application in which to perform the transaction.

Raises: datastore_errors.BadArgumentError if value is not a string
  or is the empty string.
r:   )r
   ValidateStringr	   r   r2  s    r+   r:   TransactionOptions.app	  s(     ""5#(#3#D#DF Lr.   r3   N)r%   r   r   r   r   NESTED	MANDATORYALLOWEDINDEPENDENTr   r  r   r  r  r  r:   r   r3   r.   r+   r   r     s    C&:) '9+HFIwDE, (     	 	r.   r   c                      ^  \ rS rSrSrSrSrSrSr\	" S5      SSSS\
S\R                  4U 4S jj5       r\S	 5       r\S
 5       rS rSU 4S jjrS rS rSU 4S jjrS rS rS rS rS rS rS rSrU =r$ )r   i&	  zA connection specific to one transaction.

It is possible to pass the transaction and entity group to the
constructor, but typically the transaction is lazily created by
_get_transaction() when the first operation is started.
r   r!   r.  r
  Nc                   > [         [        U ]  UUUS9  [        R                  U l        Ub  Ub  [
        R                  " S5      eU R                  U l        U R                  U l
        Uck  [        R                  U R                  5      n[        R                  " [        R                  U R                  5      5      nU R                  SXU5      U l        OkU R"                  [$        :X  a  [&        R(                  n	O[*        R,                  n	[/        X95      (       d  [
        R                  " SU-  5      eX0l        SU l        0 U l        0 U l        g)aW  Constructor.

All arguments should be specified as keyword arguments.

Args:
  adapter: Optional AbstractAdapter subclass instance;
    default IdentityAdapter.
  config: Optional Configuration object.
  transaction: Optional datastore_db.Transaction object.
  entity_group: Deprecated, do not use.
  previous_transaction: Optional datastore_db.Transaction object
    representing the transaction being reset.
  mode: Optional datastore_db.TransactionMode representing the transaction
    mode.

Raises:
  datastore_errors.BadArgumentError: If previous_transaction and transaction
    are both set.
r  Nz>Only one of transaction and previous_transaction should be setzInvalid transaction (%r))r   r   rG   OPENra  r	   r   r  !_TransactionalConnection__adapterr    _TransactionalConnection__configr   r:   r
   r7   r  )_TransactionalConnection__transaction_rpcr  r  r   binary_typer   r  r   %_TransactionalConnection__transaction,_TransactionalConnection__pending_v1_upserts,_TransactionalConnection__pending_v1_deletes)rE   r  r   r  entity_groupr  r  r  r:   	txn_classr   s             r+   rG    TransactionalConnection.__init__4	  s.   0 

!41'9??K 2 M *..DK'K,C--
JL L \\DNKKDM""4;;/c(();)?)?)LMc#;;
4 1d 
		1	1**	 ,,	////&46 	6&#d !#D "Dr.   c                 <    U R                   [        R                  :g  $ r@   )ra  r   r   rJ   s    r+   finished TransactionalConnection.finishedl	  s    ;;16666r.   c                     U R                   b&  U R                   R                  5       U l        SU l         U R                  $ )z5The current transaction. None when state == FINISHED.N)r#  r  r%  rJ   s    r+   r  #TransactionalConnection.transactionp	  s;     )11<<>d#dr.   c                    U R                   (       a  [        R                  " S5      eU R                  nU R                  [
        :X  a  [        U[        R                  [        R                  45      (       a  X!l        OW[        U[        R                  [        R                  45      (       a  X!R                  l        O[        S[        U5      -  5      eX!R                  l        U$ UR                  5       R!                  U5        U$ )a  Set the current transaction on a request.

This accesses the transaction property.  The transaction object
returned is both set as the transaction field on the request
object and returned.

Args:
  request: A protobuf with a transaction field.

Returns:
  An object representing a transaction or None.

Raises:
  ValueError: if called with a non-Cloud Datastore request when using
      Cloud Datastore.
z7Cannot start a new operation in a finished transaction.z3Cannot use Cloud Datastore V1 transactions with %s.)r,  r	   r  r  r  r  r   r   r  RollbackRequestrJ  RunQueryRequestr  
ValueErrorr   mutable_transactionr  )rE   r  r  s      r+   r  0TransactionalConnection._set_request_transactionx	  s    " }},,
CE E""K//	Go;;-==? 
@ 
@)g = = / ? ? A B B+6( Ng' ( 	()4&  !!#,,[9r.   c           
      H  > U R                   [        :w  a  [        [        U ]  XU5      $ U Vs/ s H  nU R
                  R                  U5      PM      nn[        R                  " 5       nU H]  n[        R                  " UR                  5      (       a  M*  UR                  R                  5       R                  UR                  5        M_     XS4n[        n	UR                  (       d  [        n	U R!                  USU[        R"                  " 5       U R$                  UU	S9$ s  snf )a  Transactional asynchronous Put operation.

Args:
  config: A Configuration object or None.  Defaults are taken from
    the connection's default configuration.
  entities: An iterable of user-level entity objects.
  extra_hook: Optional function to be called on the result once the
    RPC has completed.

 Returns:
  A MultiRpc object.

NOTE: If any of the entities has an incomplete key, this will
*not* patch up those entities with the complete key.
r  r@  )r  r  r   r   r  r  r   r   r  r   r  ri   r:  r  r  r  r  r  2_TransactionalConnection__v1_put_allocate_ids_hook)rE   r   rf  ro  r   v1_entitiesv1_reqr   r  r  r   s             r+   r  !TransactionalConnection.async_put	  s     //*D;
J( ( "*+!)v <<//7!)  + //1F 	--imm<<""9==1 ! 'I&L;;"lv}f.BBD/3/N/N)2,8	  : :+s   %Dc                     U R                  U5        UR                  nU R                  [        UR                  5      UR
                  5      $ )z=Internal method used as get_result_hook for AllocateIds call.)r  r  -_TransactionalConnection__v1_build_put_resultrr  r:  r  )rE   r{  v1_resps      r+   __v1_put_allocate_ids_hook2TransactionalConnection.__v1_put_allocate_ids_hook	  s>    3llG%%d7<<&8&)mm5 5r.   c                 $   Uu  p4/ nSnU H  n[         R                  " U5      n[        R                  " UR                  5      (       d"  UR                  R                  X   5        US-  n[        R                  " UR                  5      nU R                  R                  US5        XpR                  U'   UR                  U R                  R                  [         R                  " UR                  5      5      5        M     U(       a  U" U5      nU$ )aZ  Internal method that builds the result of a put operation.

Converts the results from a v1 AllocateIds operation to a list of user-level
key objects.

Args:
  v1_allocated_keys: a list of googledatastore.Keys that have been allocated
  user_data: a tuple consisting of:
    - a list of googledatastore.Entity objects
    - an optional extra_hook
r   r!   N)r	  rA  r   r  ri   r  r
   rd  r'  popr&  r   r  r[   )	rE   v1_allocated_keysr  r8  ro  r:  idxr   rs  s	            r+   __v1_build_put_result-TransactionalConnection.__v1_build_put_result	  s     (KD
C 	 --	*i--imm<<056q$88Gl
##L$7 1:-
kk$,,++DMM)--,HIJ# !( dKr.   c           
        > U R                   [        :w  a  [        [        U ]  UUU5      $ U Vs/ s H  o@R
                  R                  U5      PM     nnU HC  n[        R                  " U5      nU R                  R                  US5        X@R                  U'   ME     U R                  USS[        R                  " 5       U R                  U[         S9$ s  snf )a:  Transactional asynchronous Delete operation.

Args:
  config: A Configuration object or None.  Defaults are taken from
    the connection's default configuration.
  keys: An iterable of user-level key objects.
  extra_hook: Optional function to be called once the RPC has completed.

Returns:
  A MultiRpc object.
Nr  r@  )r  r  r   r   r  r!  r~   r
   rd  r&  rA  r'  r  r   r  (_TransactionalConnection__v1_delete_hookr  )rE   r   r:  ro  ri   v1_keysrs  r   s          r+   r  $TransactionalConnection.async_delete	  s     //*D>v?C?IK K <@@4C~~**3/4G@$88=l
##L$7 14-  vx.==?/3/D/D)3,9	  ; ; As   $Cc                 <    UR                   nU(       a	  U" S 5        g g r@   )r  )rE   r{  ro  s      r+   __v1_delete_hook(TransactionalConnection.__v1_delete_hook 
  s    J r.   c                 ~    U R                  U R                  S9nU R                  U5      nUc  gUR                  5       $ )zSynchronous Commit operation.

Returns:
  True if the transaction was successfully committed.  False if
  the backend reported a concurrent transaction error.
rY  T)r  r  async_commitr  r  s     r+   commitTransactionalConnection.commit'
  sB     

(9(9

:C


C
 C
{>>r.   c           	      0   U R                  5         U R                  [        R                  :w  a  [        R
                  " S5      e[        R                  U l        U R                  nUc  [        R                  U l        gU R                  [        :X  GaF  [        R                  " 5       nX#l        [        R                  XR                  5      (       a  U R!                  U5        U R"                  R%                  5        H8  nUR&                  R)                  5       nUR*                  R-                  U5        M:     U R.                  R%                  5        H8  nUR&                  R)                  5       nUR0                  R-                  U5        M:     U R"                  R3                  5         U R.                  R3                  5         [        R4                  " 5       nOUn[6        R4                  " 5       nU R9                  USX7U R:                  U R                  S9$ )zAsynchronous Commit operation.

Args:
  config: A Configuration object or None.  Defaults are taken from
    the connection's default configuration.

Returns:
  A MultiRpc object.
z Transaction is already finished.Nr  r  )r  ra  r   r   r	   r  COMMIT_IN_FLIGHTr  CLOSEDr  r  r   r  r   r>  r"  _TransactionalConnection__forcer&  r  r  r  r  r  r'  r  clearr  r   r  %_TransactionalConnection__commit_hook)rE   r   r  r4  r   r  ri   rG  s           r+   rN  $TransactionalConnection.async_commit6
  s    	""${{-222,,-OPP)::DK""K+22dk//))+c#o		#	#FMM	:	:S --446&==$$&  ( 7 **113#==$$&  % 4
 %%'
%%'++-dc((*dvx/3/A/A,0,=,=  ? ?r.   c                 0    UR                  5         [        R                  U l        SU l        g! [
        R                   aR  n[        R                  U l        UR                  [        R                  R                  :X  a   SnAg[        U5      eSnAff = f)z3Internal method used as get_result_hook for Commit.NTF)r  r   rS  ra  r%  r   r  FAILEDapplication_errorr   ErrorCONCURRENT_TRANSACTIONr  r  s      r+   __commit_hook%TransactionalConnection.__commit_hookf
  sz    	+22dkd  ++ %+22dk			,"4"4"K"K	K$$%s   ,/ B=BBBc                 L    U R                  S5      nUc  gUR                  5       $ )zSynchronous Rollback operation.N)async_rollbackr  r  s     r+   rollback TransactionalConnection.rollbackw
  s'    


d
#C
{>>r.   c           	      $   U R                  5         U R                  [        R                  :X  d4  U R                  [        R                  :X  d  [
        R                  " S5      eU R                  nUc  g[        R                  U l        SU l	        U R                  [        :X  a1  [        R                  " 5       nX#l        [        R                  " 5       nOUn[        R                   " 5       nU R#                  USX4U R$                  U R                  S9$ )zAsynchronous Rollback operation.

Args:
  config: A Configuration object or None.  Defaults are taken from
    the connection's default configuration.

 Returns:
  A MultiRpc object.
zACannot rollback transaction that is neither OPEN or FAILED state.NRollbackr  )r  ra  r   r   rY  r	   r  r  rS  r%  r  r  r   r1  RollbackResponser   	VoidProtor  '_TransactionalConnection__rollback_hook)rE   r   r  r4  rG  s        r+   r`  &TransactionalConnection.async_rollback~
  s     	""$KK2777{{5<<<,,
MO O ""K)00DKD//++-c#o--/dc""$dvz3/3/C/C,0,=,=  ? ?r.   c                 &    U R                  U5        g)z5Internal method used as get_result_hook for Rollback.N)r  r  s     r+   __rollback_hook'TransactionalConnection.__rollback_hook
  s    3r.   )r  r  __pending_v1_deletes__pending_v1_upserts__transaction__transaction_rpcra  r@   )r%   r   r   r   r   r   rR  rY  rS  r4   rZ  r   r  rG   r  r,  r  r  r  r7  r<  r  rG  rO  rN  rV  ra  r`  rg  r   r   r   s   @r+   r   r   &	  s     
$&&q>Dd)#++5# 5#n 7 7  &T(:T5%R";H.?`""?H   r.   r   DATASTORE_APP_IDDATASTORE_PROJECT_IDDATASTORE_ADDITIONAL_APP_IDS"DATASTORE_USE_PROJECT_ID_AS_APP_IDc                    [         R                  R                  [        S5      n[         R                  R                  [        S5      nU(       d  U(       Ga-  [        [         R                  R                  [        S5      5      nU(       d'  U(       d   [        SU< S[        < S[        < S35      eU(       av  U(       a(  [        SU< S[        < S	[        < S
[        < S3	5      eU(       a@  [        R                  " U/5      nUUR                  U5      :w  a  [        SU< SU< S35      eU=(       d    Un[         R                  R                  [        S5      nS UR                  S5       5       n[        U UUU5      $ U " S0 UD6$ )aG  Creates a new connection to Datastore.

Uses environment variables to determine if the connection should be made
to Cloud Datastore v1 or to Datastore's private App Engine API.
If DATASTORE_PROJECT_ID exists, connect to Cloud Datastore v1. In this case,
either DATASTORE_APP_ID or DATASTORE_USE_PROJECT_ID_AS_APP_ID must be set to
indicate what the environment's application should be.

Args:
  connection_fn: The function to use to create the connection.
  **kwargs: Addition arguments to pass to the connection_fn.

Raises:
  ValueError: If DATASTORE_PROJECT_ID is set but DATASTORE_APP_ID or
     DATASTORE_USE_PROJECT_ID_AS_APP_ID is not. If DATASTORE_APP_ID doesn't
     resolve to DATASTORE_PROJECT_ID. If DATASTORE_APP_ID doesn't match
     an existing APPLICATION_ID.

Returns:
  the connection object returned from connection_fn.
NFz/Could not determine app id. To use project id (z) instead, set z=true. This will affect the serialized form of entities and should not be used if serialized entities will be shared between code running on App Engine and code running off App Engine. Alternatively, set z
=<app id>.zApp id was provided (z) but z& was set to true. Please unset either z or .zApp id "z" does not match project id "z".r    c              3   @   #    U  H  oR                  5       v   M     g 7fr@   )strip).0r:   s     r+   	<genexpr>+_CreateDefaultConnection.<locals>.<genexpr>
  s     L.Ksyy{{.Ks   ,r3   )osenvironr   _DATASTORE_APP_ID_ENV_DATASTORE_PROJECT_ID_ENVrj   '_DATASTORE_USE_PROJECT_ID_AS_APP_ID_ENVr3  r   
IdResolverresolve_project_id!_DATASTORE_ADDITIONAL_APP_IDS_ENVsplit_CreateCloudDatastoreConnection)connection_fnr   datastore_app_iddatastore_project_idapp_id_overriderF   additional_app_stradditional_appss           r+   _CreateDefaultConnectionr  
  sL   , ZZ^^$94@(A4H-2::>>/8 9OO /A/1 2 2 
	*A/AC D 	D  #..0@/AB **+;<=.0DF G G (?+?(I2NL.@.F.Fs.KLO*=+;+:+13 3 
	 	  r.   c                    SSK Jn  [        R                  (       d$  [        R
                  " [        R                  5      e[        R                  R                  SS5      nU(       a  XQ:w  a  [        SU< SU< S35      eU[        R                  S'   [        R                  " U4[        U5      -   5      nUR                  U5      n[        R                  R!                  U5      n[        R"                  " U[        R                  R%                  5       S9n	[&        US	'   XcS
'   U " S0 UD6n
 UR)                  U	5      n[*        R,                  R/                  [&        U5         [*        R,                  R/                  S[1        5       5         [*        R,                  R/                  S[1        5       5        U
$ !    NX= f!    N6= f!    U
$ = f)a  Creates a new context to connect to a remote Cloud Datastore instance.

This should only be used outside of Google App Engine.

Args:
  connection_fn: A connection function which accepts both an _api_version
    and an _id_resolver argument.
  app_id: The application id to connect to. This differs from the project
    id as it may have an additional prefix, e.g. "s~" or "e~".
  external_app_ids: A list of apps that may be referenced by data in your
    application. For example, if you are connected to s~my-app and store keys
    for s~my-other-app, you should include s~my-other-app in the external_apps
    list.
  kwargs: The additional kwargs to pass to the connection_fn.

Raises:
  ValueError: if the app_id provided doesn't match the current environment's
      APPLICATION_ID.

Returns:
  An ndb.Context that can connect to a Remote Cloud Datastore. You can use
  this context by passing it to ndb.set_context.
r   )cloud_datastore_v1_remote_stubAPPLICATION_IDNzICannot create a Cloud Datastore context that connects to an application (z:) that differs from the application already connected to (z).)project_endpointcredentialsr  _id_resolvermemcache	taskqueuer3   )"googlecloudsdk.appengine.datastorer  r   r  r	   r   r  r|  r}  r   r3  r  r!  r  r   helperget_project_endpoint_from_env	Datastoreget_credentials_from_envr  CloudDatastoreV1RemoteStubr   r  RegisterStub_ThrowingStub)r  app_idexternal_app_idsr   r  current_app_idrF   
project_idendpoint	datastoreconnstubs               r+   r  r  
  s   : P		/	/

+
+557 7 ::>>"2D9.0 5;^M N N "("**((&U;K5L)LM+--f5*##AA*M(''!((AACE) /&&		 	 $	)DDYOD++,?,02	++JH	++KI 
+				+s$   -5F6 #(F= (G 6F:=GG	c                   $    \ rS rSrSrS rS rSrg)r  i<  z@A Stub implementation which always throws a NotImplementedError.c                 *    [        SU< SU< S35      e)NzIn order to use ru  z! you must install the Remote API.rP   )rE   servicecallr  r  s        r+   MakeSyncCall_ThrowingStub.MakeSyncCall@  s    
;BDJ K Kr.   c                 *    [         R                  " U S9$ )N)r  )r   r_  rJ   s    r+   rg  _ThrowingStub.CreateRPCE  s    &&r.   r3   N)r%   r   r   r   r   r  rg  r   r3   r.   r+   r  r  <  s    HK
'r.   r  c                 B    [        U R                  U R                  5      $ )zConverts an apiproxy.ApplicationError to an error in datastore_errors.

Args:
  err: An apiproxy.ApplicationError object.

Returns:
  An instance of a subclass of datastore_errors.Error.
))_DatastoreExceptionFromErrorCodeAndDetailrZ  error_detail)r   s    r+   r  r  M  s$     
333H3H363C3C
E Er.   c                 n    [         R                  U [        R                  5      nUc  U" 5       $ U" U5      $ )zConverts a datastore_pb.Error into a datastore_errors.Error.

Args:
  error: A member of the datastore_pb.Error enumeration.
  detail: A string providing extra details about the error.

Returns:
  An instance of a subclass of datastore_errors.Error.
)_DATASTORE_EXCEPTION_CLASSESr   r	   r[  r  detailexception_classs      r+   r  r  y  s;     144U5E5K5KM/ ^6""r.   c                 n    [         R                  U [        R                  5      nUc  U" 5       $ U" U5      $ )zConverts a canonical error code into a datastore_errors.Error.

Args:
  error: A canonical error code from google.rpc.code.
  detail: A string providing extra details about the error.

Returns:
  An instance of a subclass of datastore_errors.Error.
)"_CLOUD_DATASTORE_EXCEPTION_CLASSESr   r	   InternalErrorr  s      r+   2_DatastoreExceptionFromCanonicalErrorCodeAndDetailr    s;     7::++-/ ^6""r.   r@   )\r   
__future__r   r   r  r	  r/   r  r|  "googlecloudsdk.appengine._internalr   googlecloudsdk.appengine.apir   r   r   r	   r
   r  r   r   2googlecloudsdk.appengine.googlestorage.onestore.v3r    googlecloudsdk.appengine.runtimer   __all__r  0googlecloudsdk.appengine.datastore.datastore_pbsr   r  rZ  r  r4   r<   r   r   r   r   r   r   with_metaclassr   r   r   r  r_  rX  re  r   r   r   r   r   r   r~  r  r  r  r  r  r  r  r[  BAD_REQUESTr  r\  TransactionFailedErrorINTERNAL_ERRORr  
NEED_INDEXNeedIndexErrorTIMEOUTTimeoutBIGTABLE_ERRORCOMMITTED_BUT_STILL_APPLYINGCommittedButStillApplyingCAPABILITY_DISABLEDCapabilityDisabledErrorRESOURCE_EXHAUSTEDOverQuotaErrorr  r  code_pb2INVALID_ARGUMENTABORTEDFAILED_PRECONDITIONDEADLINE_EXCEEDEDPERMISSION_DENIEDUNAVAILABLERPCFailedErrorINTERNALr  r  r3   r.   r+   <module>r     s^    ' '
     	 9 4 5 : 9 8 ; < H < )AA N
 (  * (	3f#f f#Ro 416 1h!d !LE
112I28: EP>!, >!Ba% aJ '
-| 
-6 y:v y:x
f 
GV GT"m) m)`L L^~ n ~ B + 2 $B !*N '=!BJZ
'F 
'"
E ""$4$D$D--/?/V/V%%'7'E'E!!#3#B#B 0 8 8%%'7'?'?335E5_5_**O,S,S))?+I+I
   &( "//1A1Q1Q&&(8(O(O22

)
)002B2J2J002B2R2R**O,J,J11?3Q3Q''

(
(($ #&#r.   