Merge "Make QuotaImageTagsProxy deep-copyable"
This commit is contained in:
commit
fb2c2e7de1
|
@ -165,14 +165,15 @@ class QuotaImageTagsProxy(object):
|
||||||
return self.tags.__len__(*args, **kwargs)
|
return self.tags.__len__(*args, **kwargs)
|
||||||
|
|
||||||
def __getattr__(self, name):
|
def __getattr__(self, name):
|
||||||
# Use TypeError here, not AttributeError, as the latter is how we
|
# Protect against deepcopy, which calls getattr. __getattr__
|
||||||
# know a tag is not present. TypeError says "this object is not
|
# is only called when an attribute is not "normal", so when
|
||||||
# what it claims to be".
|
# self.tags is called, this is not.
|
||||||
try:
|
if name == 'tags':
|
||||||
tags = self.__getattribute__('tags')
|
try:
|
||||||
except AttributeError:
|
return self.__getattribute__('tags')
|
||||||
raise TypeError('QuotaImageTagsProxy has no tags.')
|
except AttributeError:
|
||||||
return getattr(tags, name)
|
return None
|
||||||
|
return getattr(self.tags, name)
|
||||||
|
|
||||||
|
|
||||||
class ImageMemberFactoryProxy(glance.domain.proxy.ImageMembershipFactory):
|
class ImageMemberFactoryProxy(glance.domain.proxy.ImageMembershipFactory):
|
||||||
|
|
|
@ -12,6 +12,7 @@
|
||||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
import copy
|
||||||
import uuid
|
import uuid
|
||||||
|
|
||||||
import mock
|
import mock
|
||||||
|
@ -596,15 +597,24 @@ class TestQuotaImageTagsProxy(test_utils.BaseTestCase):
|
||||||
items.remove(item)
|
items.remove(item)
|
||||||
self.assertEqual(0, len(items))
|
self.assertEqual(0, len(items))
|
||||||
|
|
||||||
def test_tags_attr_exception(self):
|
def test_tags_attr_no_loop(self):
|
||||||
proxy = glance.quota.QuotaImageTagsProxy(None)
|
proxy = glance.quota.QuotaImageTagsProxy(None)
|
||||||
self.assertRaises(AttributeError, lambda: proxy.foo)
|
self.assertEqual(set([]), proxy.tags)
|
||||||
|
|
||||||
# Remove tags to cause the object to be broken. If tags
|
def test_tags_deepcopy(self):
|
||||||
# is not there and we weren't raising TypeError, we'd
|
proxy = glance.quota.QuotaImageTagsProxy(set(['a', 'b']))
|
||||||
# get an infinite loop when calling 'proxy.foo'.
|
proxy_copy = copy.deepcopy(proxy)
|
||||||
|
self.assertEqual(set(['a', 'b']), proxy_copy.tags)
|
||||||
|
self.assertIn('a', proxy_copy)
|
||||||
|
# remove is a found via __getattr__
|
||||||
|
proxy_copy.remove('a')
|
||||||
|
self.assertNotIn('a', proxy_copy)
|
||||||
|
|
||||||
|
def test_tags_delete(self):
|
||||||
|
proxy = glance.quota.QuotaImageTagsProxy(set(['a', 'b']))
|
||||||
|
self.assertEqual(set(['a', 'b']), proxy.tags)
|
||||||
del proxy.tags
|
del proxy.tags
|
||||||
self.assertRaises(TypeError, lambda: proxy.foo)
|
self.assertIsNone(proxy.tags)
|
||||||
|
|
||||||
|
|
||||||
class TestImageMemberQuotas(test_utils.BaseTestCase):
|
class TestImageMemberQuotas(test_utils.BaseTestCase):
|
||||||
|
|
Loading…
Reference in New Issue