PNG  IHDRxsBIT|d pHYs+tEXtSoftwarewww.inkscape.org<,tEXtComment File Manager

File Manager

Path: /opt/alt/python311/lib/python3.11/site-packages/boto3/dynamodb/

Viewing File: transform.py

# Copyright 2015 Amazon.com, Inc. or its affiliates. All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"). You
# may not use this file except in compliance with the License. A copy of
# the License is located at
#
# https://aws.amazon.com/apache2.0/
#
# or in the "license" file accompanying this file. This file is
# distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF
# ANY KIND, either express or implied. See the License for the specific
# language governing permissions and limitations under the License.
import copy

from boto3.compat import collections_abc
from boto3.docs.utils import DocumentModifiedShape
from boto3.dynamodb.conditions import ConditionBase, ConditionExpressionBuilder
from boto3.dynamodb.types import TypeDeserializer, TypeSerializer


def register_high_level_interface(base_classes, **kwargs):
    base_classes.insert(0, DynamoDBHighLevelResource)


class _ForgetfulDict(dict):
    """A dictionary that discards any items set on it. For use as `memo` in
    `copy.deepcopy()` when every instance of a repeated object in the deepcopied
    data structure should result in a separate copy.
    """

    def __setitem__(self, key, value):
        pass


def copy_dynamodb_params(params, **kwargs):
    return copy.deepcopy(params, memo=_ForgetfulDict())


class DynamoDBHighLevelResource:
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

        # Apply handler that creates a copy of the user provided dynamodb
        # item such that it can be modified.
        self.meta.client.meta.events.register(
            'provide-client-params.dynamodb',
            copy_dynamodb_params,
            unique_id='dynamodb-create-params-copy',
        )

        self._injector = TransformationInjector()
        # Apply the handler that generates condition expressions including
        # placeholders.
        self.meta.client.meta.events.register(
            'before-parameter-build.dynamodb',
            self._injector.inject_condition_expressions,
            unique_id='dynamodb-condition-expression',
        )

        # Apply the handler that serializes the request from python
        # types to dynamodb types.
        self.meta.client.meta.events.register(
            'before-parameter-build.dynamodb',
            self._injector.inject_attribute_value_input,
            unique_id='dynamodb-attr-value-input',
        )

        # Apply the handler that deserializes the response from dynamodb
        # types to python types.
        self.meta.client.meta.events.register(
            'after-call.dynamodb',
            self._injector.inject_attribute_value_output,
            unique_id='dynamodb-attr-value-output',
        )

        # Apply the documentation customizations to account for
        # the transformations.
        attr_value_shape_docs = DocumentModifiedShape(
            'AttributeValue',
            new_type='valid DynamoDB type',
            new_description=(
                '- The value of the attribute. The valid value types are '
                'listed in the '
                ':ref:`DynamoDB Reference Guide<ref_valid_dynamodb_types>`.'
            ),
            new_example_value=(
                '\'string\'|123|Binary(b\'bytes\')|True|None|set([\'string\'])'
                '|set([123])|set([Binary(b\'bytes\')])|[]|{}'
            ),
        )

        key_expression_shape_docs = DocumentModifiedShape(
            'KeyExpression',
            new_type=(
                'condition from :py:class:`boto3.dynamodb.conditions.Key` '
                'method'
            ),
            new_description=(
                'The condition(s) a key(s) must meet. Valid conditions are '
                'listed in the '
                ':ref:`DynamoDB Reference Guide<ref_dynamodb_conditions>`.'
            ),
            new_example_value='Key(\'mykey\').eq(\'myvalue\')',
        )

        con_expression_shape_docs = DocumentModifiedShape(
            'ConditionExpression',
            new_type=(
                'condition from :py:class:`boto3.dynamodb.conditions.Attr` '
                'method'
            ),
            new_description=(
                'The condition(s) an attribute(s) must meet. Valid conditions '
                'are listed in the '
                ':ref:`DynamoDB Reference Guide<ref_dynamodb_conditions>`.'
            ),
            new_example_value='Attr(\'myattribute\').eq(\'myvalue\')',
        )

        self.meta.client.meta.events.register(
            'docs.*.dynamodb.*.complete-section',
            attr_value_shape_docs.replace_documentation_for_matching_shape,
            unique_id='dynamodb-attr-value-docs',
        )

        self.meta.client.meta.events.register(
            'docs.*.dynamodb.*.complete-section',
            key_expression_shape_docs.replace_documentation_for_matching_shape,
            unique_id='dynamodb-key-expression-docs',
        )

        self.meta.client.meta.events.register(
            'docs.*.dynamodb.*.complete-section',
            con_expression_shape_docs.replace_documentation_for_matching_shape,
            unique_id='dynamodb-cond-expression-docs',
        )


class TransformationInjector:
    """Injects the transformations into the user provided parameters."""

    def __init__(
        self,
        transformer=None,
        condition_builder=None,
        serializer=None,
        deserializer=None,
    ):
        self._transformer = transformer
        if transformer is None:
            self._transformer = ParameterTransformer()

        self._condition_builder = condition_builder
        if condition_builder is None:
            self._condition_builder = ConditionExpressionBuilder()

        self._serializer = serializer
        if serializer is None:
            self._serializer = TypeSerializer()

        self._deserializer = deserializer
        if deserializer is None:
            self._deserializer = TypeDeserializer()

    def inject_condition_expressions(self, params, model, **kwargs):
        """Injects the condition expression transformation into the parameters

        This injection includes transformations for ConditionExpression shapes
        and KeyExpression shapes. It also handles any placeholder names and
        values that are generated when transforming the condition expressions.
        """
        self._condition_builder.reset()
        generated_names = {}
        generated_values = {}

        # Create and apply the Condition Expression transformation.
        transformation = ConditionExpressionTransformation(
            self._condition_builder,
            placeholder_names=generated_names,
            placeholder_values=generated_values,
            is_key_condition=False,
        )
        self._transformer.transform(
            params, model.input_shape, transformation, 'ConditionExpression'
        )

        # Create and apply the Key Condition Expression transformation.
        transformation = ConditionExpressionTransformation(
            self._condition_builder,
            placeholder_names=generated_names,
            placeholder_values=generated_values,
            is_key_condition=True,
        )
        self._transformer.transform(
            params, model.input_shape, transformation, 'KeyExpression'
        )

        expr_attr_names_input = 'ExpressionAttributeNames'
        expr_attr_values_input = 'ExpressionAttributeValues'

        # Now that all of the condition expression transformation are done,
        # update the placeholder dictionaries in the request.
        if expr_attr_names_input in params:
            params[expr_attr_names_input].update(generated_names)
        else:
            if generated_names:
                params[expr_attr_names_input] = generated_names

        if expr_attr_values_input in params:
            params[expr_attr_values_input].update(generated_values)
        else:
            if generated_values:
                params[expr_attr_values_input] = generated_values

    def inject_attribute_value_input(self, params, model, **kwargs):
        """Injects DynamoDB serialization into parameter input"""
        self._transformer.transform(
            params,
            model.input_shape,
            self._serializer.serialize,
            'AttributeValue',
        )

    def inject_attribute_value_output(self, parsed, model, **kwargs):
        """Injects DynamoDB deserialization into responses"""
        if model.output_shape is not None:
            self._transformer.transform(
                parsed,
                model.output_shape,
                self._deserializer.deserialize,
                'AttributeValue',
            )


class ConditionExpressionTransformation:
    """Provides a transformation for condition expressions

    The ``ParameterTransformer`` class can call this class directly
    to transform the condition expressions in the parameters provided.
    """

    def __init__(
        self,
        condition_builder,
        placeholder_names,
        placeholder_values,
        is_key_condition=False,
    ):
        self._condition_builder = condition_builder
        self._placeholder_names = placeholder_names
        self._placeholder_values = placeholder_values
        self._is_key_condition = is_key_condition

    def __call__(self, value):
        if isinstance(value, ConditionBase):
            # Create a conditional expression string with placeholders
            # for the provided condition.
            built_expression = self._condition_builder.build_expression(
                value, is_key_condition=self._is_key_condition
            )

            self._placeholder_names.update(
                built_expression.attribute_name_placeholders
            )
            self._placeholder_values.update(
                built_expression.attribute_value_placeholders
            )

            return built_expression.condition_expression
        # Use the user provided value if it is not a ConditonBase object.
        return value


class ParameterTransformer:
    """Transforms the input to and output from botocore based on shape"""

    def transform(self, params, model, transformation, target_shape):
        """Transforms the dynamodb input to or output from botocore

        It applies a specified transformation whenever a specific shape name
        is encountered while traversing the parameters in the dictionary.

        :param params: The parameters structure to transform.
        :param model: The operation model.
        :param transformation: The function to apply the parameter
        :param target_shape: The name of the shape to apply the
            transformation to
        """
        self._transform_parameters(model, params, transformation, target_shape)

    def _transform_parameters(
        self, model, params, transformation, target_shape
    ):
        type_name = model.type_name
        if type_name in ('structure', 'map', 'list'):
            getattr(self, f'_transform_{type_name}')(
                model, params, transformation, target_shape
            )

    def _transform_structure(
        self, model, params, transformation, target_shape
    ):
        if not isinstance(params, collections_abc.Mapping):
            return
        for param in params:
            if param in model.members:
                member_model = model.members[param]
                member_shape = member_model.name
                if member_shape == target_shape:
                    params[param] = transformation(params[param])
                else:
                    self._transform_parameters(
                        member_model,
                        params[param],
                        transformation,
                        target_shape,
                    )

    def _transform_map(self, model, params, transformation, target_shape):
        if not isinstance(params, collections_abc.Mapping):
            return
        value_model = model.value
        value_shape = value_model.name
        for key, value in params.items():
            if value_shape == target_shape:
                params[key] = transformation(value)
            else:
                self._transform_parameters(
                    value_model, params[key], transformation, target_shape
                )

    def _transform_list(self, model, params, transformation, target_shape):
        if not isinstance(params, collections_abc.MutableSequence):
            return
        member_model = model.member
        member_shape = member_model.name
        for i, item in enumerate(params):
            if member_shape == target_shape:
                params[i] = transformation(item)
            else:
                self._transform_parameters(
                    member_model, params[i], transformation, target_shape
                )
b IDATxytVսϓ22 A@IR :hCiZ[v*E:WũZA ^dQeQ @ !jZ'>gsV仿$|?g)&x-EIENT ;@xT.i%-X}SvS5.r/UHz^_$-W"w)Ɗ/@Z &IoX P$K}JzX:;` &, ŋui,e6mX ԵrKb1ԗ)DADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADADA݀!I*]R;I2$eZ#ORZSrr6mteffu*((Pu'v{DIߔ4^pIm'77WEEE;vƎ4-$]'RI{\I&G :IHJ DWBB=\WR޽m o$K(V9ABB.}jѢv`^?IOȅ} ڶmG}T#FJ`56$-ھ}FI&v;0(h;Б38CӧOWf!;A i:F_m9s&|q%=#wZprrrla A &P\\СC[A#! {olF} `E2}MK/vV)i{4BffV\|ۭX`b@kɶ@%i$K z5zhmX[IXZ` 'b%$r5M4º/l ԃߖxhʔ)[@=} K6IM}^5k㏷݆z ΗÿO:gdGBmyT/@+Vɶ纽z񕏵l.y޴it뭷zV0[Y^>Wsqs}\/@$(T7f.InݺiR$푔n.~?H))\ZRW'Mo~v Ov6oԃxz! S,&xm/yɞԟ?'uaSѽb,8GלKboi&3t7Y,)JJ c[nzӳdE&KsZLӄ I?@&%ӟ۶mSMMњ0iؐSZ,|J+N ~,0A0!5%Q-YQQa3}$_vVrf9f?S8`zDADADADADADADADADAdqP,تmMmg1V?rSI꒟]u|l RCyEf٢9 jURbztѰ!m5~tGj2DhG*{H9)꒟ר3:(+3\?/;TUݭʴ~S6lڧUJ*i$d(#=Yݺd{,p|3B))q:vN0Y.jkק6;SɶVzHJJЀ-utѹսk>QUU\޲~]fFnK?&ߡ5b=z9)^|u_k-[y%ZNU6 7Mi:]ۦtk[n X(e6Bb."8cۭ|~teuuw|ήI-5"~Uk;ZicEmN/:]M> cQ^uiƞ??Ңpc#TUU3UakNwA`:Y_V-8.KKfRitv޲* 9S6ֿj,ՃNOMߤ]z^fOh|<>@Å5 _/Iu?{SY4hK/2]4%it5q]GGe2%iR| W&f*^]??vq[LgE_3f}Fxu~}qd-ږFxu~I N>\;͗O֊:̗WJ@BhW=y|GgwܷH_NY?)Tdi'?խwhlmQi !SUUsw4kӺe4rfxu-[nHtMFj}H_u~w>)oV}(T'ebʒv3_[+vn@Ȭ\S}ot}w=kHFnxg S 0eޢm~l}uqZfFoZuuEg `zt~? b;t%>WTkķh[2eG8LIWx,^\thrl^Ϊ{=dž<}qV@ ⠨Wy^LF_>0UkDuʫuCs$)Iv:IK;6ֲ4{^6եm+l3>݆uM 9u?>Zc }g~qhKwڭeFMM~pМuqǿz6Tb@8@Y|jx](^]gf}M"tG -w.@vOqh~/HII`S[l.6nØXL9vUcOoB\xoǤ'T&IǍQw_wpv[kmO{w~>#=P1Pɞa-we:iǏlHo׈꒟f9SzH?+shk%Fs:qVhqY`jvO'ρ?PyX3lх]˾uV{ݞ]1,MzYNW~̈́ joYn}ȚF߾׮mS]F z+EDxm/d{F{-W-4wY듏:??_gPf ^3ecg ҵs8R2מz@TANGj)}CNi/R~}c:5{!ZHӋӾ6}T]G]7W6^n 9*,YqOZj:P?Q DFL|?-^.Ɵ7}fFh׶xe2Pscz1&5\cn[=Vn[ĶE鎀uˌd3GII k;lNmشOuuRVfBE]ۣeӶu :X-[(er4~LHi6:Ѻ@ԅrST0trk%$Č0ez" *z"T/X9|8.C5Feg}CQ%͞ˣJvL/?j^h&9xF`њZ(&yF&Iݻfg#W;3^{Wo^4'vV[[K';+mӍִ]AC@W?1^{එyh +^]fm~iԵ]AB@WTk̏t uR?l.OIHiYyԶ]Aˀ7c:q}ힽaf6Z~қm(+sK4{^6}T*UUu]n.:kx{:2 _m=sAߤU@?Z-Vކеz왍Nэ{|5 pڶn b p-@sPg]0G7fy-M{GCF'%{4`=$-Ge\ eU:m+Zt'WjO!OAF@ik&t݆ϥ_ e}=]"Wz_.͜E3leWFih|t-wZۍ-uw=6YN{6|} |*={Ѽn.S.z1zjۻTH]흾 DuDvmvK.`V]yY~sI@t?/ϓ. m&["+P?MzovVЫG3-GRR[(!!\_,^%?v@ҵő m`Y)tem8GMx.))A]Y i`ViW`?^~!S#^+ѽGZj?Vģ0.))A꨷lzL*]OXrY`DBBLOj{-MH'ii-ϰ ok7^ )쭡b]UXSְmռY|5*cֽk0B7镹%ڽP#8nȎq}mJr23_>lE5$iwui+ H~F`IjƵ@q \ @#qG0".0" l`„.0! ,AQHN6qzkKJ#o;`Xv2>,tێJJ7Z/*A .@fفjMzkg @TvZH3Zxu6Ra'%O?/dQ5xYkU]Rֽkق@DaS^RSּ5|BeHNN͘p HvcYcC5:y #`οb;z2.!kr}gUWkyZn=f Pvsn3p~;4p˚=ē~NmI] ¾ 0lH[_L hsh_ғߤc_њec)g7VIZ5yrgk̞W#IjӪv>՞y睝M8[|]\շ8M6%|@PZڨI-m>=k='aiRo-x?>Q.}`Ȏ:Wsmu u > .@,&;+!!˱tﭧDQwRW\vF\~Q7>spYw$%A~;~}6¾ g&if_=j,v+UL1(tWake:@Ș>j$Gq2t7S?vL|]u/ .(0E6Mk6hiۺzښOrifޱxm/Gx> Lal%%~{lBsR4*}{0Z/tNIɚpV^#Lf:u@k#RSu =S^ZyuR/.@n&΃z~B=0eg뺆#,Þ[B/?H uUf7y Wy}Bwegל`Wh(||`l`.;Ws?V@"c:iɍL֯PGv6zctM̠':wuW;d=;EveD}9J@B(0iհ bvP1{\P&G7D޴Iy_$-Qjm~Yrr&]CDv%bh|Yzni_ˆR;kg}nJOIIwyuL}{ЌNj}:+3Y?:WJ/N+Rzd=hb;dj͒suݔ@NKMԄ jqzC5@y°hL m;*5ezᕏ=ep XL n?מ:r`۵tŤZ|1v`V뽧_csج'ߤ%oTuumk%%%h)uy]Nk[n 'b2 l.=͜E%gf$[c;s:V-͞WߤWh-j7]4=F-X]>ZLSi[Y*We;Zan(ӇW|e(HNNP5[= r4tP &0<pc#`vTNV GFqvTi*Tyam$ߏWyE*VJKMTfFw>'$-ؽ.Ho.8c"@DADADADADADADADADA~j*֘,N;Pi3599h=goضLgiJ5փy~}&Zd9p֚ e:|hL``b/d9p? fgg+%%hMgXosج, ΩOl0Zh=xdjLmhݻoO[g_l,8a]٭+ӧ0$I]c]:粹:Teꢢ"5a^Kgh,&= =՟^߶“ߢE ܹS J}I%:8 IDAT~,9/ʃPW'Mo}zNƍ쨓zPbNZ~^z=4mswg;5 Y~SVMRXUյڱRf?s:w ;6H:ºi5-maM&O3;1IKeamZh͛7+##v+c ~u~ca]GnF'ټL~PPPbn voC4R,ӟgg %hq}@#M4IÇ Oy^xMZx ) yOw@HkN˖-Sǎmb]X@n+i͖!++K3gd\$mt$^YfJ\8PRF)77Wא!Cl$i:@@_oG I{$# 8磌ŋ91A (Im7֭>}ߴJq7ޗt^ -[ԩSj*}%]&' -ɓ'ꫯVzzvB#;a 7@GxI{j޼ƌ.LÇWBB7`O"I$/@R @eee@۷>}0,ɒ2$53Xs|cS~rpTYYY} kHc %&k.], @ADADADADADADADADA@lT<%''*Lo^={رc5h %$+CnܸQ3fҥK}vUVVs9G R,_{xˇ3o߾;TTTd}馛]uuuG~iԩ@4bnvmvfϞ /Peeeq}}za I~,誫{UWW뮻}_~YƍSMMMYχ֝waw\ďcxꩧtEƍկ_?۷5@u?1kNׯWzz/wy>}zj3 k(ٺuq_Zvf̘:~ ABQ&r|!%KҥKgԞ={<_X-z !CyFUUz~ ABQIIIjݺW$UXXDٳZ~ ABQƍecW$<(~<RSSvZujjjԧOZQu@4 8m&&&jԩg$ď1h ͟?_{768@g =@`)))5o6m3)ѣƌJ;wҿUTT /KZR{~a=@0o<*狔iFɶ[ˎ;T]]OX@?K.ۈxN pppppppppppppppppPfl߾] ,{ァk۶mڿo5BTӦMӴiӴ|r DB2e|An!Dy'tkΝ[A $***t5' "!駟oaDnΝ:t֭[gDШQ06qD;@ x M6v(PiizmZ4ew"@̴ixf [~-Fٱc&IZ2|n!?$@{[HTɏ#@hȎI# _m(F /6Z3z'\r,r!;w2Z3j=~GY7"I$iI.p_"?pN`y DD?: _  Gÿab7J !Bx@0 Bo cG@`1C[@0G @`0C_u V1 aCX>W ` | `!<S `"<. `#c`?cAC4 ?c p#~@0?:08&_MQ1J h#?/`7;I  q 7a wQ A 1 Hp !#<8/#@1Ul7=S=K.4Z?E_$i@!1!E4?`P_  @Bă10#: "aU,xbFY1 [n|n #'vEH:`xb #vD4Y hi.i&EΖv#O H4IŶ}:Ikh @tZRF#(tXҙzZ ?I3l7q@õ|ۍ1,GpuY Ꮿ@hJv#xxk$ v#9 5 }_$c S#=+"K{F*m7`#%H:NRSp6I?sIՖ{Ap$I$I:QRv2$Z @UJ*$]<FO4IENDB`