summaryrefslogtreecommitdiff
path: root/oslo_context
diff options
context:
space:
mode:
authorJamie Lennox <jamielennox@gmail.com>2016-07-13 10:37:09 +1000
committerJamie Lennox <jamielennox@gmail.com>2016-07-13 10:37:09 +1000
commit3a118faa83d807de3469e35236569a48261b34de (patch)
tree05eea6a440f039ee6fe5c20f9bad40dc9c20411e /oslo_context
parent9feb9db8d667bc5bc9ca43e2073227c1e8e44bbb (diff)
downloadoslo-context-3a118faa83d807de3469e35236569a48261b34de.tar.gz
Manually specify from_dict parameters
The way from_dict is structured today means that it is virtually impossible for a subclass to use it. The function looks only at its own __init__ variables and then creates a class with them. If a subclass is adding something to to_dict (they almost all do) then there is no way for that subclass to add anything to the from_dict so that it is correctly reconstructed. This problem is solvable by the pattern of passing keyword args through to the constructor and having from_dict add to these arguments if they are not already present. This pattern is already used by from_environ. This change also moves from an inspecting __init__ args to explicitly specifying the arguments supported by from_dict. This will be required to start doing debtcollector and parameter cleanup without breaking compatibility in the subclasses where the values returned by inspect may not be those we actually want to pass to __init__. Change-Id: Id5d78c2dbf76741338982e8d5ba08b6ad432ec42
Diffstat (limited to 'oslo_context')
-rw-r--r--oslo_context/context.py27
-rw-r--r--oslo_context/tests/test_context.py19
2 files changed, 40 insertions, 6 deletions
diff --git a/oslo_context/context.py b/oslo_context/context.py
index 0238533..b419f7e 100644
--- a/oslo_context/context.py
+++ b/oslo_context/context.py
@@ -26,7 +26,6 @@ context or provide additional information in their specific WSGI pipeline
or logging context.
"""
-import inspect
import itertools
import threading
import uuid
@@ -167,12 +166,28 @@ class RequestContext(object):
return values
@classmethod
- def from_dict(cls, values):
+ def from_dict(cls, values, **kwargs):
"""Construct a context object from a provided dictionary."""
- allowed = [arg for arg in
- inspect.getargspec(RequestContext.__init__).args
- if arg != 'self']
- kwargs = {k: v for (k, v) in values.items() if k in allowed}
+ kwargs.setdefault('auth_token', values.get('auth_token'))
+ kwargs.setdefault('user', values.get('user'))
+ kwargs.setdefault('tenant', values.get('tenant'))
+ kwargs.setdefault('domain', values.get('domain'))
+ kwargs.setdefault('user_domain', values.get('user_domain'))
+ kwargs.setdefault('project_domain', values.get('project_domain'))
+ kwargs.setdefault('is_admin', values.get('is_admin', False))
+ kwargs.setdefault('read_only', values.get('read_only', False))
+ kwargs.setdefault('show_deleted', values.get('show_deleted', False))
+ kwargs.setdefault('request_id', values.get('request_id'))
+ kwargs.setdefault('resource_uuid', values.get('resource_uuid'))
+ kwargs.setdefault('roles', values.get('roles'))
+ kwargs.setdefault('user_name', values.get('user_name'))
+ kwargs.setdefault('project_name', values.get('project_name'))
+ kwargs.setdefault('domain_name', values.get('domain_name'))
+ kwargs.setdefault('user_domain_name', values.get('user_domain_name'))
+ kwargs.setdefault('project_domain_name',
+ values.get('project_domain_name'))
+ kwargs.setdefault('is_admin_project',
+ values.get('is_admin_project', True))
return cls(**kwargs)
@classmethod
diff --git a/oslo_context/tests/test_context.py b/oslo_context/tests/test_context.py
index e50b99c..f8aa50c 100644
--- a/oslo_context/tests/test_context.py
+++ b/oslo_context/tests/test_context.py
@@ -137,6 +137,25 @@ class ContextTest(test_base.BaseTestCase):
self.assertTrue(ctx.read_only)
self.assertRaises(KeyError, lambda: ctx.__dict__['color'])
+ def test_from_dict_overrides(self):
+ dct = {
+ "auth_token": "token1",
+ "user": "user1",
+ "read_only": True,
+ "roles": "role1,role2,role3",
+ "color": "red",
+ "unknown": ""
+ }
+ ctx = context.RequestContext.from_dict(dct,
+ user="user2",
+ project_name="project1")
+ self.assertEqual("token1", ctx.auth_token)
+ self.assertEqual("user2", ctx.user)
+ self.assertEqual("project1", ctx.project_name)
+ self.assertIsNone(ctx.tenant)
+ self.assertFalse(ctx.is_admin)
+ self.assertTrue(ctx.read_only)
+
def test_is_user_context(self):
self.assertFalse(context.is_user_context(None))
ctx = context.RequestContext(is_admin=True)