Skip to content
Browse files

2008-04-29 Michal Ludvig <michal@logix.cz>

	* s3db, S3/SimpleDB.py: Initial support for Amazon SimpleDB. 
	  For now implements ListDomains() call and most of the 
	  infrastructure required for request creation.



git-svn-id: https://s3tools.svn.sourceforge.net/svnroot/s3tools/s3cmd/trunk@178 830e0280-6d2a-0410-9c65-932aecc39d9d
  • Loading branch information...
1 parent 6bb385f commit d2b144dfba0a2b32b04dde1b06bda18815b4c7cf @mludvig mludvig committed Apr 29, 2008
Showing with 138 additions and 0 deletions.
  1. +6 −0 ChangeLog
  2. +1 −0 S3/Config.py
  3. +102 −0 S3/SimpleDB.py
  4. +29 −0 s3db
View
6 ChangeLog
@@ -1,5 +1,11 @@
2008-04-29 Michal Ludvig <michal@logix.cz>
+ * s3db, S3/SimpleDB.py: Initial support for Amazon SimpleDB.
+ For now implements ListDomains() call and most of the
+ infrastructure required for request creation.
+
+2008-04-29 Michal Ludvig <michal@logix.cz>
+
* S3/Exceptions.py: Exceptions moved out of S3.S3
* S3/SortedDict.py: rewritten from scratch to preserve
case of keys while still sorting in case-ignore mode.
View
1 S3/Config.py
@@ -15,6 +15,7 @@ class Config(object):
secret_key = ""
host_base = "s3.amazonaws.com"
host_bucket = "%(bucket)s.s3.amazonaws.com"
+ simpledb_host = "sdb.amazonaws.com"
verbosity = logging.WARNING
send_chunk = 4096
recv_chunk = 4096
View
102 S3/SimpleDB.py
@@ -0,0 +1,102 @@
+## Amazon SimpleDB library
+## Author: Michal Ludvig <michal@logix.cz>
+## http://www.logix.cz/michal
+## License: GPL Version 2
+
+"""
+Low-level class for working with Amazon SimpleDB
+"""
+
+import time
+import urllib
+import base64
+import hmac
+import sha
+import httplib
+from logging import debug, info, warning, error
+
+from Utils import convertTupleListToDict
+from SortedDict import SortedDict
+from Exceptions import *
+
+class SimpleDB(object):
+ # API Version
+ # See http://docs.amazonwebservices.com/AmazonSimpleDB/2007-11-07/DeveloperGuide/
+ Version = "2007-11-07"
+ SignatureVersion = 1
+
+ def __init__(self, config):
+ self.config = config
+
+ def ListDomains(self, MaxNumberOfDomains = 100):
+ '''
+ Lists all domains associated with our Access Key. Returns
+ domain names up to the limit set by MaxNumberOfDomains.
+ '''
+ parameters = SortedDict()
+ parameters['MaxNumberOfDomains'] = MaxNumberOfDomains
+ response = self.send_request("ListDomains", domain = None, parameters = parameters)
+ return response
+
+ def send_request(self, *args, **kwargs):
+ request = self.create_request(*args, **kwargs)
+ debug("Request: %s" % repr(request))
+ conn = self.get_connection()
+ conn.request("GET", self.format_uri(request['uri_params']))
+ http_response = conn.getresponse()
+ response = {}
+ response["status"] = http_response.status
+ response["reason"] = http_response.reason
+ response["headers"] = convertTupleListToDict(http_response.getheaders())
+ response["data"] = http_response.read()
+ debug("Response: " + str(response))
+ conn.close()
+
+ if response["status"] < 200 or response["status"] > 299:
+ raise S3Error(response)
+
+ return response
+
+ def create_request(self, action, domain, parameters = None):
+ if not parameters:
+ parameters = SortedDict()
+ parameters['AWSAccessKeyId'] = self.config.access_key
+ parameters['Version'] = self.Version
+ parameters['SignatureVersion'] = self.SignatureVersion
+ parameters['Action'] = action
+ parameters['Timestamp'] = time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime())
+ if domain:
+ parameters['DomainName'] = domain
+ parameters['Signature'] = self.sign_request(parameters)
+ parameters.keys_return_lowercase = False
+ uri_params = urllib.urlencode(parameters)
+ request = {}
+ request['uri_params'] = uri_params
+ request['parameters'] = parameters
+ return request
+
+ def sign_request(self, parameters):
+ h = ""
+ parameters.keys_sort_lowercase = True
+ parameters.keys_return_lowercase = False
+ for key in parameters:
+ h += "%s%s" % (key, parameters[key])
+ debug("SignRequest: %s" % h)
+ return base64.encodestring(hmac.new(self.config.secret_key, h, sha).digest()).strip()
+
+ def get_connection(self):
+ if self.config.proxy_host != "":
+ return httplib.HTTPConnection(self.config.proxy_host, self.config.proxy_port)
+ else:
+ if self.config.use_https:
+ return httplib.HTTPSConnection(self.config.simpledb_host)
+ else:
+ return httplib.HTTPConnection(self.config.simpledb_host)
+
+ def format_uri(self, uri_params):
+ if self.config.proxy_host != "":
+ uri = "http://%s/?%s" % (self.config.simpledb_host, uri_params)
+ else:
+ uri = "/?%s" % uri_params
+ debug('format_uri(): ' + uri)
+ return uri
View
29 s3db
@@ -0,0 +1,29 @@
+#!/usr/bin/env python
+
+## Amazon S3 manager
+## Author: Michal Ludvig <michal@logix.cz>
+## http://www.logix.cz/michal
+## License: GPL Version 2
+
+import sys
+import os
+import logging
+
+from optparse import OptionParser, Option, OptionValueError, IndentedHelpFormatter
+from logging import debug, info, warning, error
+
+## Our modules
+from S3 import PkgInfo
+from S3.SimpleDB import SimpleDB
+from S3.Config import Config
+from S3.Exceptions import *
+
+
+if __name__ == '__main__':
+ if float("%d.%d" %(sys.version_info[0], sys.version_info[1])) < 2.4:
+ sys.stderr.write("ERROR: Python 2.4 or higher required, sorry.\n")
+ sys.exit(1)
+ logging.root.setLevel(logging.DEBUG)
+ cfg = Config(os.getenv("HOME")+"/.s3cfg")
+ sdb = SimpleDB(cfg)
+ print sdb.ListDomains()

0 comments on commit d2b144d

Please sign in to comment.
Something went wrong with that request. Please try again.