diff options
| author | jaypipes@gmail.com <> | 2010-08-10 14:20:15 -0400 |
|---|---|---|
| committer | jaypipes@gmail.com <> | 2010-08-10 14:20:15 -0400 |
| commit | 1d414f6bddbae33bcbec799e29ab904d86811869 (patch) | |
| tree | b27f06c13282e25b55fa57cc77bcad19317ad616 | |
| parent | e1199140315e7cc85249820e92ab8b7998e50ae2 (diff) | |
pylint fixes for nova/objectstore/handler.py
| -rw-r--r-- | nova/objectstore/handler.py | 133 |
1 files changed, 100 insertions, 33 deletions
diff --git a/nova/objectstore/handler.py b/nova/objectstore/handler.py index f625a2aa1..cb38c89f2 100644 --- a/nova/objectstore/handler.py +++ b/nova/objectstore/handler.py @@ -19,6 +19,10 @@ # License for the specific language governing permissions and limitations # under the License. +# Disabling pylint's R0201 (Method could be a function) because +# the API of render_GET, render_PUT, etc is Twisted's, not ours. +# pylint: disable-msg=R0201 + """ Implementation of an S3-like storage server based on local files. @@ -61,6 +65,7 @@ from nova.objectstore import image FLAGS = flags.FLAGS def render_xml(request, value): + """Writes value as XML string to request""" assert isinstance(value, dict) and len(value) == 1 request.setHeader("Content-Type", "application/xml; charset=UTF-8") @@ -73,11 +78,13 @@ def render_xml(request, value): request.finish() def finish(request, content=None): + """Finalizer method for request""" if content: request.write(content) request.finish() def _render_parts(value, write_cb): + """Helper method to render different Python objects to XML""" if isinstance(value, basestring): write_cb(escape.xhtml_escape(value)) elif isinstance(value, int) or isinstance(value, long): @@ -96,35 +103,47 @@ def _render_parts(value, write_cb): raise Exception("Unknown S3 value type %r", value) def get_argument(request, key, default_value): + """Returns the request's value at key, or default_value + if not found + """ if key in request.args: return request.args[key][0] return default_value def get_context(request): + """Returns the supplied request's context object""" try: # Authorization Header format: 'AWS <access>:<secret>' authorization_header = request.getHeader('Authorization') if not authorization_header: raise exception.NotAuthorized - access, sep, secret = authorization_header.split(' ')[1].rpartition(':') - (user, project) = manager.AuthManager().authenticate(access, - secret, - {}, - request.method, - request.getRequestHostname(), - request.uri, - headers=request.getAllHeaders(), - check_type='s3') + auth_header_value = authorization_header.split(' ')[1] + access, _ignored, secret = auth_header_value.rpartition(':') + am = manager.AuthManager() + (user, project) = am.authenticate(access, + secret, + {}, + request.method, + request.getRequestHostname(), + request.uri, + headers=request.getAllHeaders(), + check_type='s3') return api.APIRequestContext(None, user, project) except exception.Error as ex: - logging.debug("Authentication Failure: %s" % ex) + logging.debug("Authentication Failure: %s", ex) raise exception.NotAuthorized class ErrorHandlingResource(Resource): - """Maps exceptions to 404 / 401 codes. Won't work for exceptions thrown after NOT_DONE_YET is returned.""" - # TODO(unassigned) (calling-all-twisted-experts): This needs to be plugged in to the right place in twisted... - # This doesn't look like it's the right place (consider exceptions in getChild; or after NOT_DONE_YET is returned + """Maps exceptions to 404 / 401 codes. Won't work for + exceptions thrown after NOT_DONE_YET is returned. + """ + # TODO(unassigned) (calling-all-twisted-experts): This needs to be + # plugged in to the right place in twisted... + # This doesn't look like it's the right place + # (consider exceptions in getChild; or after + # NOT_DONE_YET is returned def render(self, request): + """Renders the response as XML""" try: return Resource.render(self, request) except exception.NotFound: @@ -136,7 +155,11 @@ class ErrorHandlingResource(Resource): class S3(ErrorHandlingResource): """Implementation of an S3-like storage server based on local files.""" - def getChild(self, name, request): + def __init__(self): + ErrorHandlingResource.__init__(self) + + def getChild(self, name, request): # pylint: disable-msg=C0103 + """Returns either the image or bucket resource""" request.context = get_context(request) if name == '': return self @@ -146,8 +169,10 @@ class S3(ErrorHandlingResource): return BucketResource(name) def render_GET(self, request): + """Renders the GET request for a list of buckets as XML""" logging.debug('List of buckets requested') - buckets = [b for b in bucket.Bucket.all() if b.is_authorized(request.context)] + buckets = [b for b in bucket.Bucket.all() \ + if b.is_authorized(request.context)] render_xml(request, {"ListAllMyBucketsResult": { "Buckets": {"Bucket": [b.metadata for b in buckets]}, @@ -155,22 +180,27 @@ class S3(ErrorHandlingResource): return server.NOT_DONE_YET class BucketResource(ErrorHandlingResource): + """A web resource containing an S3-like bucket""" def __init__(self, name): - Resource.__init__(self) + ErrorHandlingResource.__init__(self) self.name = name def getChild(self, name, request): + """Returns the bucket resource itself, or the object resource + the bucket contains if a name is supplied + """ if name == '': return self else: return ObjectResource(bucket.Bucket(self.name), name) def render_GET(self, request): - logging.debug("List keys for bucket %s" % (self.name)) + "Returns the keys for the bucket resource""" + logging.debug("List keys for bucket %s", self.name) try: bucket_object = bucket.Bucket(self.name) - except exception.NotFound, e: + except exception.NotFound: return error.NoResource(message="No such bucket").render(request) if not bucket_object.is_authorized(request.context): @@ -181,19 +211,26 @@ class BucketResource(ErrorHandlingResource): max_keys = int(get_argument(request, "max-keys", 1000)) terse = int(get_argument(request, "terse", 0)) - results = bucket_object.list_keys(prefix=prefix, marker=marker, max_keys=max_keys, terse=terse) + results = bucket_object.list_keys(prefix=prefix, + marker=marker, + max_keys=max_keys, + terse=terse) render_xml(request, {"ListBucketResult": results}) return server.NOT_DONE_YET def render_PUT(self, request): - logging.debug("Creating bucket %s" % (self.name)) - logging.debug("calling bucket.Bucket.create(%r, %r)" % (self.name, request.context)) + "Creates the bucket resource""" + logging.debug("Creating bucket %s", self.name) + logging.debug("calling bucket.Bucket.create(%r, %r)", + self.name, + request.context) bucket.Bucket.create(self.name, request.context) request.finish() return server.NOT_DONE_YET def render_DELETE(self, request): - logging.debug("Deleting bucket %s" % (self.name)) + """Deletes the bucket resource""" + logging.debug("Deleting bucket %s", self.name) bucket_object = bucket.Bucket(self.name) if not bucket_object.is_authorized(request.context): @@ -205,25 +242,37 @@ class BucketResource(ErrorHandlingResource): class ObjectResource(ErrorHandlingResource): - def __init__(self, bucket, name): - Resource.__init__(self) - self.bucket = bucket + """The resource returned from a bucket""" + def __init__(self, bucket_name, name): + ErrorHandlingResource.__init__(self) + self.bucket = bucket_name self.name = name def render_GET(self, request): - logging.debug("Getting object: %s / %s" % (self.bucket.name, self.name)) + """Returns the object + + Raises NotAuthorized if user in request context is not + authorized to delete the object. + """ + logging.debug("Getting object: %s / %s", self.bucket.name, self.name) if not self.bucket.is_authorized(request.context): raise exception.NotAuthorized obj = self.bucket[urllib.unquote(self.name)] request.setHeader("Content-Type", "application/unknown") - request.setHeader("Last-Modified", datetime.datetime.utcfromtimestamp(obj.mtime)) + request.setHeader("Last-Modified", + datetime.datetime.utcfromtimestamp(obj.mtime)) request.setHeader("Etag", '"' + obj.md5 + '"') return static.File(obj.path).render_GET(request) def render_PUT(self, request): - logging.debug("Putting object: %s / %s" % (self.bucket.name, self.name)) + """Modifies/inserts the object and returns a result code + + Raises NotAuthorized if user in request context is not + authorized to delete the object. + """ + logging.debug("Putting object: %s / %s", self.bucket.name, self.name) if not self.bucket.is_authorized(request.context): raise exception.NotAuthorized @@ -236,7 +285,15 @@ class ObjectResource(ErrorHandlingResource): return server.NOT_DONE_YET def render_DELETE(self, request): - logging.debug("Deleting object: %s / %s" % (self.bucket.name, self.name)) + """Deletes the object and returns a result code + + Raises NotAuthorized if user in request context is not + authorized to delete the object. + """ + + logging.debug("Deleting object: %s / %s", + self.bucket.name, + self.name) if not self.bucket.is_authorized(request.context): raise exception.NotAuthorized @@ -246,17 +303,23 @@ class ObjectResource(ErrorHandlingResource): return '' class ImageResource(ErrorHandlingResource): + """A web resource representing a single image""" isLeaf = True def __init__(self, name): - Resource.__init__(self) + ErrorHandlingResource.__init__(self) self.img = image.Image(name) def render_GET(self, request): - return static.File(self.img.image_path, defaultType='application/octet-stream').render_GET(request) + """Returns the image file""" + return static.File(self.img.image_path, + defaultType='application/octet-stream' + ).render_GET(request) class ImagesResource(Resource): - def getChild(self, name, request): + """A web resource representing a list of images""" + def getChild(self, name, _request): + """Returns itself or an ImageResource if no name given""" if name == '': return self else: @@ -285,7 +348,6 @@ class ImagesResource(Resource): raise exception.NotAuthorized bucket_object = bucket.Bucket(image_location.split("/")[0]) - manifest = image_location[len(image_location.split('/')[0])+1:] if not bucket_object.is_authorized(request.context): raise exception.NotAuthorized @@ -324,13 +386,18 @@ class ImagesResource(Resource): return '' def get_site(): + """Support for WSGI-like interfaces""" root = S3() site = server.Site(root) return site def get_application(): + """Support WSGI-like interfaces""" factory = get_site() application = service.Application("objectstore") + # Disabled because of lack of proper introspection in Twisted + # or possibly different versions of twisted? + # pylint: disable-msg=E1101 objectStoreService = internet.TCPServer(FLAGS.s3_port, factory) objectStoreService.setServiceParent(application) return application |
