Update a single item in a table

        This uses the older version of the DynamoDB API.
        See also: :meth:`~.update_item2`.

        Parameters
        ----------
        tablename : str
            Name of the table to update
        key : dict
            Primary key dict specifying the hash key and, if applicable, the
            range key of the item.
        updates : list
            List of :class:`~dynamo3.batch.ItemUpdate`
        returns : {NONE, ALL_OLD, UPDATED_OLD, ALL_NEW, UPDATED_NEW}, optional
            Return either the old or new values, either all attributes or just
            the ones that changed. (default NONE)
        return_capacity : {NONE, INDEXES, TOTAL}, optional
            INDEXES will return the consumed capacity for indexes, TOTAL will
            return the consumed capacity for the table and the indexes.
            (default NONE)
        expect_or : bool, optional
            If True, the updates conditionals will be OR'd together. If False,
            they will be AND'd. (default False).
        **kwargs : dict, optional
            Conditional filter on the PUT. Same format as the kwargs for
            :meth:`~.scan`.

        Notes
        -----
        There are two ways to specify the expected values of fields. The
        simplest is via the list of updates. Each updated field may specify a
        constraint on the current value of that field. You may pass additional
        constraints in via the **kwargs the same way you would for put_item.
        This is necessary if you have constraints on fields that are not being
        updated.

def update_item(self, tablename, key, updates, returns=NONE,
                    return_capacity=None, expect_or=False, **kwargs):
        """
        Update a single item in a table

        This uses the older version of the DynamoDB API.
        See also: :meth:`~.update_item2`.

        Parameters
        ----------
        tablename : str
            Name of the table to update
        key : dict
            Primary key dict specifying the hash key and, if applicable, the
            range key of the item.
        updates : list
            List of :class:`~dynamo3.batch.ItemUpdate`
        returns : {NONE, ALL_OLD, UPDATED_OLD, ALL_NEW, UPDATED_NEW}, optional
            Return either the old or new values, either all attributes or just
            the ones that changed. (default NONE)
        return_capacity : {NONE, INDEXES, TOTAL}, optional
            INDEXES will return the consumed capacity for indexes, TOTAL will
            return the consumed capacity for the table and the indexes.
            (default NONE)
        expect_or : bool, optional
            If True, the updates conditionals will be OR'd together. If False,
            they will be AND'd. (default False).
        **kwargs : dict, optional
            Conditional filter on the PUT. Same format as the kwargs for
            :meth:`~.scan`.

        Notes
        -----
        There are two ways to specify the expected values of fields. The
        simplest is via the list of updates. Each updated field may specify a
        constraint on the current value of that field. You may pass additional
        constraints in via the **kwargs the same way you would for put_item.
        This is necessary if you have constraints on fields that are not being
        updated.

        """
        key = self.dynamizer.encode_keys(key)
        attr_updates = {}
        expected = {}
        keywords = {
            'ReturnConsumedCapacity': self._default_capacity(return_capacity),
        }
        for update in updates:
            attr_updates.update(update.attrs(self.dynamizer))
            expected.update(update.expected(self.dynamizer))

        # Pull the 'expected' constraints from the kwargs
        for k, v in six.iteritems(encode_query_kwargs(self.dynamizer, kwargs)):
            if k in expected:
                raise ValueError("Cannot have more than one condition on a single field")
            expected[k] = v

        if expected:
            keywords['Expected'] = expected
            if len(expected) > 1:
                keywords['ConditionalOperator'] = 'OR' if expect_or else 'AND'

        result = self.call('update_item', TableName=tablename, Key=key,
                           AttributeUpdates=attr_updates,
                           ReturnValues=returns,
                           **keywords)
        if result:
            return Result(self.dynamizer, result, 'Attributes')