summaryrefslogtreecommitdiff
path: root/keystoneclient/base.py
diff options
context:
space:
mode:
authorJamie Lennox <jlennox@redhat.com>2013-07-08 12:00:37 +1000
committerJamie Lennox <jamielennox@gmail.com>2013-07-29 13:50:50 +1000
commit50e405dfe6c567ecd87b646b956818d5e838f5fc (patch)
tree407aae0c6f46fdb8768aad4532677a81ae993609 /keystoneclient/base.py
parentc74401ab5686e438f006c58fcee7ba9217b6f746 (diff)
downloadpython-keystoneclient-50e405dfe6c567ecd87b646b956818d5e838f5fc.tar.gz
Reorganize url creation.
Make build_url extract used parameters from keyword arguments so they are not sent as the body to create, or as query parameters. Allow specifying a class level base_url that is used unless one is specifically provided. Break filtering function into a decorator as it seems the perfect usecase and it prevents a dictionary copy. Fixes: bug 1198772 Change-Id: I6d370ed504c300b9997199f351322e3083650c69
Diffstat (limited to 'keystoneclient/base.py')
-rw-r--r--keystoneclient/base.py97
1 files changed, 56 insertions, 41 deletions
diff --git a/keystoneclient/base.py b/keystoneclient/base.py
index d40c969..efc8bd0 100644
--- a/keystoneclient/base.py
+++ b/keystoneclient/base.py
@@ -19,6 +19,7 @@ Base utilities to build API operation managers and objects on top of.
"""
import abc
+import functools
import urllib
from keystoneclient import exceptions
@@ -50,6 +51,29 @@ def getid(obj):
return obj
+def filter_kwargs(f):
+ @functools.wraps(f)
+ def func(*args, **kwargs):
+ for key, ref in kwargs.items():
+ if ref is None:
+ # drop null values
+ del kwargs[key]
+ continue
+
+ id_value = getid(ref)
+ if id_value == ref:
+ continue
+
+ # if an object with an id was passed remove the object
+ # from params and replace it with just the id.
+ # e.g user: User(id=1) becomes user_id: 1
+ del kwargs[key]
+ kwargs['%s_id' % key] = id_value
+
+ return f(*args, **kwargs)
+ return func
+
+
class Manager(object):
"""
Managers interact with a particular type of API (servers, flavors, images,
@@ -178,8 +202,9 @@ class CrudManager(Manager):
"""
collection_key = None
key = None
+ base_url = None
- def build_url(self, base_url=None, **kwargs):
+ def build_url(self, dict_args_in_out=None):
"""Builds a resource URL for the given kwargs.
Given an example collection where `collection_key = 'entities'` and
@@ -197,89 +222,79 @@ class CrudManager(Manager):
If a `base_url` is provided, the generated URL will be appended to it.
"""
- url = base_url if base_url is not None else ''
+ if dict_args_in_out is None:
+ dict_args_in_out = {}
+ url = dict_args_in_out.pop('base_url', None) or self.base_url or ''
url += '/%s' % self.collection_key
# do we have a specific entity?
- entity_id = kwargs.get('%s_id' % self.key)
+ entity_id = dict_args_in_out.pop('%s_id' % self.key, None)
if entity_id is not None:
url += '/%s' % entity_id
return url
- def _filter_kwargs(self, kwargs):
- # drop null values
- for key, ref in kwargs.copy().iteritems():
- if ref is None:
- kwargs.pop(key)
- else:
- id_value = getid(ref)
- if id_value != ref:
- kwargs.pop(key)
- kwargs['%s_id' % key] = id_value
- return kwargs
-
+ @filter_kwargs
def create(self, **kwargs):
- kwargs = self._filter_kwargs(kwargs)
+ url = self.build_url(dict_args_in_out=kwargs)
return self._create(
- self.build_url(**kwargs),
+ url,
{self.key: kwargs},
self.key)
+ @filter_kwargs
def get(self, **kwargs):
- kwargs = self._filter_kwargs(kwargs)
return self._get(
- self.build_url(**kwargs),
+ self.build_url(dict_args_in_out=kwargs),
self.key)
+ @filter_kwargs
def head(self, **kwargs):
- kwargs = self._filter_kwargs(kwargs)
- return self._head(self.build_url(**kwargs))
+ return self._head(self.build_url(dict_args_in_out=kwargs))
- def list(self, base_url=None, **kwargs):
- kwargs = self._filter_kwargs(kwargs)
+ @filter_kwargs
+ def list(self, **kwargs):
+ url = self.build_url(dict_args_in_out=kwargs)
return self._list(
- '%(base_url)s%(query)s' % {
- 'base_url': self.build_url(base_url=base_url, **kwargs),
+ '%(url)s%(query)s' % {
+ 'url': url,
'query': '?%s' % urllib.urlencode(kwargs) if kwargs else '',
},
self.collection_key)
- def put(self, base_url=None, **kwargs):
- kwargs = self._filter_kwargs(kwargs)
-
+ @filter_kwargs
+ def put(self, **kwargs):
return self._update(
- self.build_url(base_url=base_url, **kwargs),
+ self.build_url(dict_args_in_out=kwargs),
method='PUT')
+ @filter_kwargs
def update(self, **kwargs):
- kwargs = self._filter_kwargs(kwargs)
- params = kwargs.copy()
- params.pop('%s_id' % self.key)
+ url = self.build_url(dict_args_in_out=kwargs)
return self._update(
- self.build_url(**kwargs),
- {self.key: params},
+ url,
+ {self.key: kwargs},
self.key,
method='PATCH')
+ @filter_kwargs
def delete(self, **kwargs):
- kwargs = self._filter_kwargs(kwargs)
-
return self._delete(
- self.build_url(**kwargs))
+ self.build_url(dict_args_in_out=kwargs))
- def find(self, base_url=None, **kwargs):
+ @filter_kwargs
+ def find(self, **kwargs):
"""
Find a single item with attributes matching ``**kwargs``.
"""
- kwargs = self._filter_kwargs(kwargs)
+ url = self.build_url(dict_args_in_out=kwargs)
rl = self._list(
- '%(base_url)s%(query)s' % {
- 'base_url': self.build_url(base_url=base_url, **kwargs),
+ '%(url)s%(query)s' % {
+ 'url': url,
'query': '?%s' % urllib.urlencode(kwargs) if kwargs else '',
},
self.collection_key)