Build Resource from either existing object or id

Allow Resource objects to be built from either an existing object, or be
created from scratch with the given id. This is useful at the Proxy
level when creating interfaces that must work with a Resource in the
end, but will want to be able to either operate on string names or the
Resources returned from other APIs.

An example is that you may want to create an object in the object store
given a previously obtained container object and a string name for the
object. You may also have constructed the Resource for the object ahead
of time and may want to pass that instead of a string name.

Change-Id: I84c2101024849ceb78de677607f6a64bd8134ede
This commit is contained in:
Brian Curtin
2014-11-14 21:33:45 -06:00
parent 0d8be32a1e
commit a250d8893f
2 changed files with 36 additions and 0 deletions

View File

@@ -230,6 +230,22 @@ class Resource(collections.MutableMapping):
"""
return cls(kwargs, loaded=True)
@classmethod
def from_id(cls, value):
"""Create an instance from an ID or return an existing instance.
Instance creation is done via cls.new.
"""
# This method is useful in the higher level, in cases where operations
# need to depend on having Resource objects, but the API is flexible
# in taking text values which represent those objects.
if isinstance(value, cls):
return value
elif isinstance(value, six.string_types):
return cls.new(**{cls.id_attribute: value})
else:
raise ValueError("value must be %s instance or id" % cls.__name__)
##
# MUTABLE MAPPING IMPLEMENTATION
##

View File

@@ -370,6 +370,26 @@ class ResourceTests(base.TestTransportBase):
del t.id
self.assertTrue(Test.id_attribute not in t._attrs)
def test_from_id_with_name(self):
name = "Sandy Koufax"
obj = FakeResource.from_id(name)
self.assertEqual(obj.id, name)
def test_from_id_with_object(self):
name = "Mickey Mantle"
obj = FakeResource.new(name=name)
new_obj = FakeResource.from_id(obj)
self.assertIs(new_obj, obj)
self.assertEqual(new_obj.name, obj.name)
def test_from_id_with_bad_value(self):
def should_raise():
FakeResource.from_id(3.14)
self.assertThat(should_raise, matchers.raises(ValueError))
class FakeResponse:
def __init__(self, response):