diff options
author | Jamie Lennox <jamielennox@gmail.com> | 2016-07-13 10:37:09 +1000 |
---|---|---|
committer | Jamie Lennox <jamielennox@gmail.com> | 2016-07-13 10:37:09 +1000 |
commit | 3a118faa83d807de3469e35236569a48261b34de (patch) | |
tree | 05eea6a440f039ee6fe5c20f9bad40dc9c20411e /oslo_context | |
parent | 9feb9db8d667bc5bc9ca43e2073227c1e8e44bbb (diff) | |
download | oslo-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.py | 27 | ||||
-rw-r--r-- | oslo_context/tests/test_context.py | 19 |
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) |