Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(302)

Unified Diff: boto/sdb/db/manager/sdbmanager.py

Issue 8386013: Merging in latest boto. (Closed) Base URL: svn://svn.chromium.org/boto
Patch Set: Redoing vendor drop by deleting and then merging. Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « boto/sdb/db/manager/pgmanager.py ('k') | boto/sdb/db/manager/xmlmanager.py » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: boto/sdb/db/manager/sdbmanager.py
diff --git a/boto/sdb/db/manager/sdbmanager.py b/boto/sdb/db/manager/sdbmanager.py
index 6aac5686f737046e4e40509f0241db6cfd53ffe7..8218f8162c43a40f93984ff458e2c54394f12873 100644
--- a/boto/sdb/db/manager/sdbmanager.py
+++ b/boto/sdb/db/manager/sdbmanager.py
@@ -27,13 +27,15 @@ from boto.sdb.db.key import Key
from boto.sdb.db.model import Model
from boto.sdb.db.blob import Blob
from boto.sdb.db.property import ListProperty, MapProperty
-from datetime import datetime, date
-from boto.exception import SDBPersistenceError
+from datetime import datetime, date, time
+from boto.exception import SDBPersistenceError, S3ResponseError
ISO8601 = '%Y-%m-%dT%H:%M:%SZ'
+class TimeDecodeError(Exception):
+ pass
-class SDBConverter:
+class SDBConverter(object):
"""
Responsible for converting base Python types to format compatible with underlying
database. For SimpleDB, that means everything needs to be converted to a string
@@ -55,7 +57,9 @@ class SDBConverter:
Key : (self.encode_reference, self.decode_reference),
datetime : (self.encode_datetime, self.decode_datetime),
date : (self.encode_date, self.decode_date),
+ time : (self.encode_time, self.decode_time),
Blob: (self.encode_blob, self.decode_blob),
+ str: (self.encode_string, self.decode_string),
}
def encode(self, item_type, value):
@@ -93,6 +97,7 @@ class SDBConverter:
return self.encode_map(prop, values)
def encode_map(self, prop, value):
+ import urllib
if value == None:
return None
if not isinstance(value, dict):
@@ -104,7 +109,7 @@ class SDBConverter:
item_type = Model
encoded_value = self.encode(item_type, value[key])
if encoded_value != None:
- new_value.append('%s:%s' % (key, encoded_value))
+ new_value.append('%s:%s' % (urllib.quote(key), encoded_value))
return new_value
def encode_prop(self, prop, value):
@@ -144,9 +149,11 @@ class SDBConverter:
def decode_map_element(self, item_type, value):
"""Decode a single element for a map"""
+ import urllib
key = value
if ":" in value:
key, value = value.split(':',1)
+ key = urllib.unquote(key)
if Model in item_type.mro():
value = item_type(id=value)
else:
@@ -270,6 +277,25 @@ class SDBConverter:
except:
return None
+ encode_time = encode_date
+
+ def decode_time(self, value):
+ """ converts strings in the form of HH:MM:SS.mmmmmm
+ (created by datetime.time.isoformat()) to
+ datetime.time objects.
+
+ Timzone-aware strings ("HH:MM:SS.mmmmmm+HH:MM") won't
+ be handled right now and will raise TimeDecodeError.
+ """
+ if '-' in value or '+' in value:
+ # TODO: Handle tzinfo
+ raise TimeDecodeError("Can't handle timezone aware objects: %r" % value)
+ tmp = value.split('.')
+ arg = map(int, tmp[0].split(':'))
+ if len(tmp) == 2:
+ arg.append(int(tmp[1]))
+ return time(*arg)
+
def encode_reference(self, value):
if value in (None, 'None', '', ' '):
return None
@@ -314,7 +340,12 @@ class SDBConverter:
if match:
s3 = self.manager.get_s3_connection()
bucket = s3.get_bucket(match.group(1), validate=False)
- key = bucket.get_key(match.group(2))
+ try:
+ key = bucket.get_key(match.group(2))
+ except S3ResponseError, e:
+ if e.reason != "Forbidden":
+ raise
+ return None
else:
return None
if key:
@@ -322,6 +353,24 @@ class SDBConverter:
else:
return None
+ def encode_string(self, value):
+ """Convert ASCII, Latin-1 or UTF-8 to pure Unicode"""
+ if not isinstance(value, str): return value
+ try:
+ return unicode(value, 'utf-8')
+ except: # really, this should throw an exception.
+ # in the interest of not breaking current
+ # systems, however:
+ arr = []
+ for ch in value:
+ arr.append(unichr(ord(ch)))
+ return u"".join(arr)
+
+ def decode_string(self, value):
+ """Decoding a string is really nothing, just
+ return the value as-is"""
+ return value
+
class SDBManager(object):
def __init__(self, cls, db_name, db_user, db_passwd,
@@ -357,9 +406,15 @@ class SDBManager(object):
return self._domain
def _connect(self):
- self._sdb = boto.connect_sdb(aws_access_key_id=self.db_user,
- aws_secret_access_key=self.db_passwd,
- is_secure=self.enable_ssl)
+ args = dict(aws_access_key_id=self.db_user,
+ aws_secret_access_key=self.db_passwd,
+ is_secure=self.enable_ssl)
+ try:
+ region = [x for x in boto.sdb.regions() if x.endpoint == self.db_host][0]
+ args['region'] = region
+ except IndexError:
+ pass
+ self._sdb = boto.connect_sdb(**args)
# This assumes that the domain has already been created
# It's much more efficient to do it this way rather than
# having this make a roundtrip each time to validate.
@@ -486,16 +541,26 @@ class SDBManager(object):
"""
import types
query_parts = []
+
order_by_filtered = False
+
if order_by:
if order_by[0] == "-":
order_by_method = "DESC";
order_by = order_by[1:]
else:
order_by_method = "ASC";
+
+ if select:
+ if order_by and order_by in select:
+ order_by_filtered = True
+ query_parts.append("(%s)" % select)
+
if isinstance(filters, str) or isinstance(filters, unicode):
- query = "WHERE `__type__` = '%s' AND %s" % (cls.__name__, filters)
- if order_by != None:
+ query = "WHERE %s AND `__type__` = '%s'" % (filters, cls.__name__)
+ if order_by in ["__id__", "itemName()"]:
+ query += " ORDER BY itemName() %s" % order_by_method
+ elif order_by != None:
query += " ORDER BY `%s` %s" % (order_by, order_by_method)
return query
@@ -537,13 +602,14 @@ class SDBManager(object):
query_parts.append(type_query)
order_by_query = ""
+
if order_by:
if not order_by_filtered:
query_parts.append("`%s` LIKE '%%'" % order_by)
- order_by_query = " ORDER BY `%s` %s" % (order_by, order_by_method)
-
- if select:
- query_parts.append("(%s)" % select)
+ if order_by in ["__id__", "itemName()"]:
+ order_by_query = " ORDER BY itemName() %s" % order_by_method
+ else:
+ order_by_query = " ORDER BY `%s` %s" % (order_by, order_by_method)
if len(query_parts) > 0:
return "WHERE %s %s" % (" AND ".join(query_parts), order_by_query)
@@ -562,7 +628,7 @@ class SDBManager(object):
def query_gql(self, query_string, *args, **kwds):
raise NotImplementedError, "GQL queries not supported in SimpleDB"
- def save_object(self, obj):
+ def save_object(self, obj, expected_value=None):
if not obj.id:
obj.id = str(uuid.uuid4())
@@ -588,7 +654,14 @@ class SDBManager(object):
raise SDBPersistenceError("Error: %s must be unique!" % property.name)
except(StopIteration):
pass
- self.domain.put_attributes(obj.id, attrs, replace=True)
+ # Convert the Expected value to SDB format
+ if expected_value:
+ prop = obj.find_property(expected_value[0])
+ v = expected_value[1]
+ if v is not None and not type(v) == bool:
+ v = self.encode_value(prop, v)
+ expected_value[1] = v
+ self.domain.put_attributes(obj.id, attrs, replace=True, expected_value=expected_value)
if len(del_attrs) > 0:
self.domain.delete_attributes(obj.id, del_attrs)
return obj
@@ -597,6 +670,7 @@ class SDBManager(object):
self.domain.delete_attributes(obj.id)
def set_property(self, prop, obj, name, value):
+ setattr(obj, name, value)
value = prop.get_value_for_datastore(obj)
value = self.encode_value(prop, value)
if prop.unique:
« no previous file with comments | « boto/sdb/db/manager/pgmanager.py ('k') | boto/sdb/db/manager/xmlmanager.py » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698