| OLD | NEW |
| (Empty) | |
| 1 # Copyright (c) 2006,2007 Mitch Garnaat http://garnaat.org/ |
| 2 # |
| 3 # Permission is hereby granted, free of charge, to any person obtaining a |
| 4 # copy of this software and associated documentation files (the |
| 5 # "Software"), to deal in the Software without restriction, including |
| 6 # without limitation the rights to use, copy, modify, merge, publish, dis- |
| 7 # tribute, sublicense, and/or sell copies of the Software, and to permit |
| 8 # persons to whom the Software is furnished to do so, subject to the fol- |
| 9 # lowing conditions: |
| 10 # |
| 11 # The above copyright notice and this permission notice shall be included |
| 12 # in all copies or substantial portions of the Software. |
| 13 # |
| 14 # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS |
| 15 # OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABIL- |
| 16 # ITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT |
| 17 # SHALL THE AUTHOR BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, |
| 18 # WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
| 19 # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS |
| 20 # IN THE SOFTWARE. |
| 21 |
| 22 import base64 |
| 23 |
| 24 class Item(dict): |
| 25 """ |
| 26 A ``dict`` sub-class that serves as an object representation of a |
| 27 SimpleDB item. An item in SDB is similar to a row in a relational |
| 28 database. Items belong to a :py:class:`Domain <boto.sdb.domain.Domain>`, |
| 29 which is similar to a table in a relational database. |
| 30 |
| 31 The keys on instances of this object correspond to attributes that are |
| 32 stored on the SDB item. |
| 33 |
| 34 .. tip:: While it is possible to instantiate this class directly, you may |
| 35 want to use the convenience methods on :py:class:`boto.sdb.domain.Domain
` |
| 36 for that purpose. For example, :py:meth:`boto.sdb.domain.Domain.get_item
`. |
| 37 """ |
| 38 def __init__(self, domain, name='', active=False): |
| 39 """ |
| 40 :type domain: :py:class:`boto.sdb.domain.Domain` |
| 41 :param domain: The domain that this item belongs to. |
| 42 |
| 43 :param str name: The name of this item. This name will be used when |
| 44 querying for items using methods like |
| 45 :py:meth:`boto.sdb.domain.Domain.get_item` |
| 46 """ |
| 47 dict.__init__(self) |
| 48 self.domain = domain |
| 49 self.name = name |
| 50 self.active = active |
| 51 self.request_id = None |
| 52 self.encoding = None |
| 53 self.in_attribute = False |
| 54 self.converter = self.domain.connection.converter |
| 55 |
| 56 def startElement(self, name, attrs, connection): |
| 57 if name == 'Attribute': |
| 58 self.in_attribute = True |
| 59 self.encoding = attrs.get('encoding', None) |
| 60 return None |
| 61 |
| 62 def decode_value(self, value): |
| 63 if self.encoding == 'base64': |
| 64 self.encoding = None |
| 65 return base64.decodestring(value) |
| 66 else: |
| 67 return value |
| 68 |
| 69 def endElement(self, name, value, connection): |
| 70 if name == 'ItemName': |
| 71 self.name = self.decode_value(value) |
| 72 elif name == 'Name': |
| 73 if self.in_attribute: |
| 74 self.last_key = self.decode_value(value) |
| 75 else: |
| 76 self.name = self.decode_value(value) |
| 77 elif name == 'Value': |
| 78 if self.last_key in self: |
| 79 if not isinstance(self[self.last_key], list): |
| 80 self[self.last_key] = [self[self.last_key]] |
| 81 value = self.decode_value(value) |
| 82 if self.converter: |
| 83 value = self.converter.decode(value) |
| 84 self[self.last_key].append(value) |
| 85 else: |
| 86 value = self.decode_value(value) |
| 87 if self.converter: |
| 88 value = self.converter.decode(value) |
| 89 self[self.last_key] = value |
| 90 elif name == 'BoxUsage': |
| 91 try: |
| 92 connection.box_usage += float(value) |
| 93 except: |
| 94 pass |
| 95 elif name == 'RequestId': |
| 96 self.request_id = value |
| 97 elif name == 'Attribute': |
| 98 self.in_attribute = False |
| 99 else: |
| 100 setattr(self, name, value) |
| 101 |
| 102 def load(self): |
| 103 """ |
| 104 Loads or re-loads this item's attributes from SDB. |
| 105 |
| 106 .. warning:: |
| 107 If you have changed attribute values on an Item instance, |
| 108 this method will over-write the values if they are different in |
| 109 SDB. For any local attributes that don't yet exist in SDB, |
| 110 they will be safe. |
| 111 """ |
| 112 self.domain.get_attributes(self.name, item=self) |
| 113 |
| 114 def save(self, replace=True): |
| 115 """ |
| 116 Saves this item to SDB. |
| 117 |
| 118 :param bool replace: If ``True``, delete any attributes on the remote |
| 119 SDB item that have a ``None`` value on this object. |
| 120 """ |
| 121 self.domain.put_attributes(self.name, self, replace) |
| 122 # Delete any attributes set to "None" |
| 123 if replace: |
| 124 del_attrs = [] |
| 125 for name in self: |
| 126 if self[name] == None: |
| 127 del_attrs.append(name) |
| 128 if len(del_attrs) > 0: |
| 129 self.domain.delete_attributes(self.name, del_attrs) |
| 130 |
| 131 def add_value(self, key, value): |
| 132 """ |
| 133 Helps set or add to attributes on this item. If you are adding a new |
| 134 attribute that has yet to be set, it will simply create an attribute |
| 135 named ``key`` with your given ``value`` as its value. If you are |
| 136 adding a value to an existing attribute, this method will convert the |
| 137 attribute to a list (if it isn't already) and append your new value |
| 138 to said list. |
| 139 |
| 140 For clarification, consider the following interactive session: |
| 141 |
| 142 .. code-block:: python |
| 143 |
| 144 >>> item = some_domain.get_item('some_item') |
| 145 >>> item.has_key('some_attr') |
| 146 False |
| 147 >>> item.add_value('some_attr', 1) |
| 148 >>> item['some_attr'] |
| 149 1 |
| 150 >>> item.add_value('some_attr', 2) |
| 151 >>> item['some_attr'] |
| 152 [1, 2] |
| 153 |
| 154 :param str key: The attribute to add a value to. |
| 155 :param object value: The value to set or append to the attribute. |
| 156 """ |
| 157 if key in self: |
| 158 # We already have this key on the item. |
| 159 if not isinstance(self[key], list): |
| 160 # The key isn't already a list, take its current value and |
| 161 # convert it to a list with the only member being the |
| 162 # current value. |
| 163 self[key] = [self[key]] |
| 164 # Add the new value to the list. |
| 165 self[key].append(value) |
| 166 else: |
| 167 # This is a new attribute, just set it. |
| 168 self[key] = value |
| 169 |
| 170 def delete(self): |
| 171 """ |
| 172 Deletes this item in SDB. |
| 173 |
| 174 .. note:: This local Python object remains in its current state |
| 175 after deletion, this only deletes the remote item in SDB. |
| 176 """ |
| 177 self.domain.delete_item(self) |
| 178 |
| 179 |
| 180 |
| 181 |
| OLD | NEW |