diff env/lib/python3.7/site-packages/boto/dynamodb2/items.py @ 5:9b1c78e6ba9c draft default tip

"planemo upload commit 6c0a8142489327ece472c84e558c47da711a9142"
author shellac
date Mon, 01 Jun 2020 08:59:25 -0400
parents 79f47841a781
children
line wrap: on
line diff
--- a/env/lib/python3.7/site-packages/boto/dynamodb2/items.py	Thu May 14 16:47:39 2020 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,473 +0,0 @@
-from copy import deepcopy
-
-
-class NEWVALUE(object):
-    # A marker for new data added.
-    pass
-
-
-class Item(object):
-    """
-    An object representing the item data within a DynamoDB table.
-
-    An item is largely schema-free, meaning it can contain any data. The only
-    limitation is that it must have data for the fields in the ``Table``'s
-    schema.
-
-    This object presents a dictionary-like interface for accessing/storing
-    data. It also tries to intelligently track how data has changed throughout
-    the life of the instance, to be as efficient as possible about updates.
-
-    Empty items, or items that have no data, are considered falsey.
-
-    """
-    def __init__(self, table, data=None, loaded=False):
-        """
-        Constructs an (unsaved) ``Item`` instance.
-
-        To persist the data in DynamoDB, you'll need to call the ``Item.save``
-        (or ``Item.partial_save``) on the instance.
-
-        Requires a ``table`` parameter, which should be a ``Table`` instance.
-        This is required, as DynamoDB's API is focus around all operations
-        being table-level. It's also for persisting schema around many objects.
-
-        Optionally accepts a ``data`` parameter, which should be a dictionary
-        of the fields & values of the item. Alternatively, an ``Item`` instance
-        may be provided from which to extract the data.
-
-        Optionally accepts a ``loaded`` parameter, which should be a boolean.
-        ``True`` if it was preexisting data loaded from DynamoDB, ``False`` if
-        it's new data from the user. Default is ``False``.
-
-        Example::
-
-            >>> users = Table('users')
-            >>> user = Item(users, data={
-            ...     'username': 'johndoe',
-            ...     'first_name': 'John',
-            ...     'date_joined': 1248o61592,
-            ... })
-
-            # Change existing data.
-            >>> user['first_name'] = 'Johann'
-            # Add more data.
-            >>> user['last_name'] = 'Doe'
-            # Delete data.
-            >>> del user['date_joined']
-
-            # Iterate over all the data.
-            >>> for field, val in user.items():
-            ...     print "%s: %s" % (field, val)
-            username: johndoe
-            first_name: John
-            date_joined: 1248o61592
-
-        """
-        self.table = table
-        self._loaded = loaded
-        self._orig_data = {}
-        self._data = data
-        self._dynamizer = table._dynamizer
-
-        if isinstance(self._data, Item):
-            self._data = self._data._data
-        if self._data is None:
-            self._data = {}
-
-        if self._loaded:
-            self._orig_data = deepcopy(self._data)
-
-    def __getitem__(self, key):
-        return self._data.get(key, None)
-
-    def __setitem__(self, key, value):
-        self._data[key] = value
-
-    def __delitem__(self, key):
-        if not key in self._data:
-            return
-
-        del self._data[key]
-
-    def keys(self):
-        return self._data.keys()
-
-    def values(self):
-        return self._data.values()
-
-    def items(self):
-        return self._data.items()
-
-    def get(self, key, default=None):
-        return self._data.get(key, default)
-
-    def __iter__(self):
-        for key in self._data:
-            yield self._data[key]
-
-    def __contains__(self, key):
-        return key in self._data
-
-    def __bool__(self):
-        return bool(self._data)
-
-    __nonzero__ = __bool__
-
-    def _determine_alterations(self):
-        """
-        Checks the ``-orig_data`` against the ``_data`` to determine what
-        changes to the data are present.
-
-        Returns a dictionary containing the keys ``adds``, ``changes`` &
-        ``deletes``, containing the updated data.
-        """
-        alterations = {
-            'adds': {},
-            'changes': {},
-            'deletes': [],
-        }
-
-        orig_keys = set(self._orig_data.keys())
-        data_keys = set(self._data.keys())
-
-        # Run through keys we know are in both for changes.
-        for key in orig_keys.intersection(data_keys):
-            if self._data[key] != self._orig_data[key]:
-                if self._is_storable(self._data[key]):
-                    alterations['changes'][key] = self._data[key]
-                else:
-                    alterations['deletes'].append(key)
-
-        # Run through additions.
-        for key in data_keys.difference(orig_keys):
-            if self._is_storable(self._data[key]):
-                alterations['adds'][key] = self._data[key]
-
-        # Run through deletions.
-        for key in orig_keys.difference(data_keys):
-            alterations['deletes'].append(key)
-
-        return alterations
-
-    def needs_save(self, data=None):
-        """
-        Returns whether or not the data has changed on the ``Item``.
-
-        Optionally accepts a ``data`` argument, which accepts the output from
-        ``self._determine_alterations()`` if you've already called it. Typically
-        unnecessary to do. Default is ``None``.
-
-        Example:
-
-            >>> user.needs_save()
-            False
-            >>> user['first_name'] = 'Johann'
-            >>> user.needs_save()
-            True
-
-        """
-        if data is None:
-            data = self._determine_alterations()
-
-        needs_save = False
-
-        for kind in ['adds', 'changes', 'deletes']:
-            if len(data[kind]):
-                needs_save = True
-                break
-
-        return needs_save
-
-    def mark_clean(self):
-        """
-        Marks an ``Item`` instance as no longer needing to be saved.
-
-        Example:
-
-            >>> user.needs_save()
-            False
-            >>> user['first_name'] = 'Johann'
-            >>> user.needs_save()
-            True
-            >>> user.mark_clean()
-            >>> user.needs_save()
-            False
-
-        """
-        self._orig_data = deepcopy(self._data)
-
-    def mark_dirty(self):
-        """
-        DEPRECATED: Marks an ``Item`` instance as needing to be saved.
-
-        This method is no longer necessary, as the state tracking on ``Item``
-        has been improved to automatically detect proper state.
-        """
-        return
-
-    def load(self, data):
-        """
-        This is only useful when being handed raw data from DynamoDB directly.
-        If you have a Python datastructure already, use the ``__init__`` or
-        manually set the data instead.
-
-        Largely internal, unless you know what you're doing or are trying to
-        mix the low-level & high-level APIs.
-        """
-        self._data = {}
-
-        for field_name, field_value in data.get('Item', {}).items():
-            self[field_name] = self._dynamizer.decode(field_value)
-
-        self._loaded = True
-        self._orig_data = deepcopy(self._data)
-
-    def get_keys(self):
-        """
-        Returns a Python-style dict of the keys/values.
-
-        Largely internal.
-        """
-        key_fields = self.table.get_key_fields()
-        key_data = {}
-
-        for key in key_fields:
-            key_data[key] = self[key]
-
-        return key_data
-
-    def get_raw_keys(self):
-        """
-        Returns a DynamoDB-style dict of the keys/values.
-
-        Largely internal.
-        """
-        raw_key_data = {}
-
-        for key, value in self.get_keys().items():
-            raw_key_data[key] = self._dynamizer.encode(value)
-
-        return raw_key_data
-
-    def build_expects(self, fields=None):
-        """
-        Builds up a list of expecations to hand off to DynamoDB on save.
-
-        Largely internal.
-        """
-        expects = {}
-
-        if fields is None:
-            fields = list(self._data.keys()) + list(self._orig_data.keys())
-
-        # Only uniques.
-        fields = set(fields)
-
-        for key in fields:
-            expects[key] = {
-                'Exists': True,
-            }
-            value = None
-
-            # Check for invalid keys.
-            if not key in self._orig_data and not key in self._data:
-                raise ValueError("Unknown key %s provided." % key)
-
-            # States:
-            # * New field (only in _data)
-            # * Unchanged field (in both _data & _orig_data, same data)
-            # * Modified field (in both _data & _orig_data, different data)
-            # * Deleted field (only in _orig_data)
-            orig_value = self._orig_data.get(key, NEWVALUE)
-            current_value = self._data.get(key, NEWVALUE)
-
-            if orig_value == current_value:
-                # Existing field unchanged.
-                value = current_value
-            else:
-                if key in self._data:
-                    if not key in self._orig_data:
-                        # New field.
-                        expects[key]['Exists'] = False
-                    else:
-                        # Existing field modified.
-                        value = orig_value
-                else:
-                   # Existing field deleted.
-                    value = orig_value
-
-            if value is not None:
-                expects[key]['Value'] = self._dynamizer.encode(value)
-
-        return expects
-
-    def _is_storable(self, value):
-        # We need to prevent ``None``, empty string & empty set from
-        # heading to DDB, but allow false-y values like 0 & False make it.
-        if not value:
-            if not value in (0, 0.0, False):
-                return False
-
-        return True
-
-    def prepare_full(self):
-        """
-        Runs through all fields & encodes them to be handed off to DynamoDB
-        as part of an ``save`` (``put_item``) call.
-
-        Largely internal.
-        """
-        # This doesn't save on its own. Rather, we prepare the datastructure
-        # and hand-off to the table to handle creation/update.
-        final_data = {}
-
-        for key, value in self._data.items():
-            if not self._is_storable(value):
-                continue
-
-            final_data[key] = self._dynamizer.encode(value)
-
-        return final_data
-
-    def prepare_partial(self):
-        """
-        Runs through **ONLY** the changed/deleted fields & encodes them to be
-        handed off to DynamoDB as part of an ``partial_save`` (``update_item``)
-        call.
-
-        Largely internal.
-        """
-        # This doesn't save on its own. Rather, we prepare the datastructure
-        # and hand-off to the table to handle creation/update.
-        final_data = {}
-        fields = set()
-        alterations = self._determine_alterations()
-
-        for key, value in alterations['adds'].items():
-            final_data[key] = {
-                'Action': 'PUT',
-                'Value': self._dynamizer.encode(self._data[key])
-            }
-            fields.add(key)
-
-        for key, value in alterations['changes'].items():
-            final_data[key] = {
-                'Action': 'PUT',
-                'Value': self._dynamizer.encode(self._data[key])
-            }
-            fields.add(key)
-
-        for key in alterations['deletes']:
-            final_data[key] = {
-                'Action': 'DELETE',
-            }
-            fields.add(key)
-
-        return final_data, fields
-
-    def partial_save(self):
-        """
-        Saves only the changed data to DynamoDB.
-
-        Extremely useful for high-volume/high-write data sets, this allows
-        you to update only a handful of fields rather than having to push
-        entire items. This prevents many accidental overwrite situations as
-        well as saves on the amount of data to transfer over the wire.
-
-        Returns ``True`` on success, ``False`` if no save was performed or
-        the write failed.
-
-        Example::
-
-            >>> user['last_name'] = 'Doh!'
-            # Only the last name field will be sent to DynamoDB.
-            >>> user.partial_save()
-
-        """
-        key = self.get_keys()
-        # Build a new dict of only the data we're changing.
-        final_data, fields = self.prepare_partial()
-
-        if not final_data:
-            return False
-
-        # Remove the key(s) from the ``final_data`` if present.
-        # They should only be present if this is a new item, in which
-        # case we shouldn't be sending as part of the data to update.
-        for fieldname, value in key.items():
-            if fieldname in final_data:
-                del final_data[fieldname]
-
-                try:
-                    # It's likely also in ``fields``, so remove it there too.
-                    fields.remove(fieldname)
-                except KeyError:
-                    pass
-
-        # Build expectations of only the fields we're planning to update.
-        expects = self.build_expects(fields=fields)
-        returned = self.table._update_item(key, final_data, expects=expects)
-        # Mark the object as clean.
-        self.mark_clean()
-        return returned
-
-    def save(self, overwrite=False):
-        """
-        Saves all data to DynamoDB.
-
-        By default, this attempts to ensure that none of the underlying
-        data has changed. If any fields have changed in between when the
-        ``Item`` was constructed & when it is saved, this call will fail so
-        as not to cause any data loss.
-
-        If you're sure possibly overwriting data is acceptable, you can pass
-        an ``overwrite=True``. If that's not acceptable, you may be able to use
-        ``Item.partial_save`` to only write the changed field data.
-
-        Optionally accepts an ``overwrite`` parameter, which should be a
-        boolean. If you provide ``True``, the item will be forcibly overwritten
-        within DynamoDB, even if another process changed the data in the
-        meantime. (Default: ``False``)
-
-        Returns ``True`` on success, ``False`` if no save was performed.
-
-        Example::
-
-            >>> user['last_name'] = 'Doh!'
-            # All data on the Item is sent to DynamoDB.
-            >>> user.save()
-
-            # If it fails, you can overwrite.
-            >>> user.save(overwrite=True)
-
-        """
-        if not self.needs_save() and not overwrite:
-            return False
-
-        final_data = self.prepare_full()
-        expects = None
-
-        if overwrite is False:
-            # Build expectations about *all* of the data.
-            expects = self.build_expects()
-
-        returned = self.table._put_item(final_data, expects=expects)
-        # Mark the object as clean.
-        self.mark_clean()
-        return returned
-
-    def delete(self):
-        """
-        Deletes the item's data to DynamoDB.
-
-        Returns ``True`` on success.
-
-        Example::
-
-            # Buh-bye now.
-            >>> user.delete()
-
-        """
-        key_data = self.get_keys()
-        return self.table.delete_item(**key_data)