mirror of
https://github.com/valitydev/salt.git
synced 2024-11-07 08:58:59 +00:00
No more proxied immutables. Add test for nested immutables.
This commit is contained in:
parent
a87d4eeb68
commit
49bdbefb66
@ -30,9 +30,8 @@ import salt.pillar
|
||||
import salt.fileclient
|
||||
import salt.utils.event
|
||||
import salt.syspaths as syspaths
|
||||
from salt.utils import context
|
||||
from salt.utils import context, immutabletypes
|
||||
from salt._compat import string_types
|
||||
from salt.utils.immutabletypes import ImmutableLazyProxy
|
||||
from salt.template import compile_template, compile_template_str
|
||||
from salt.exceptions import SaltRenderError, SaltReqTimeoutError, SaltException
|
||||
from salt.utils.odict import OrderedDict, DefaultOrderedDict
|
||||
@ -1335,9 +1334,9 @@ class State(object):
|
||||
# the current state dictionaries.
|
||||
# We pass deep copies here because we don't want any misbehaving
|
||||
# state module to change these at runtime.
|
||||
'__low__': ImmutableLazyProxy(low),
|
||||
'__running__': ImmutableLazyProxy(running) if running else {},
|
||||
'__lowstate__': ImmutableLazyProxy(chunks) if chunks else {}
|
||||
'__low__': immutabletypes.freeze(low),
|
||||
'__running__': immutabletypes.freeze(running) if running else {},
|
||||
'__lowstate__': immutabletypes.freeze(chunks) if chunks else {}
|
||||
}
|
||||
|
||||
if low.get('__prereq__'):
|
||||
|
@ -14,9 +14,6 @@
|
||||
# Import python libs
|
||||
import collections
|
||||
|
||||
# Import salt libs
|
||||
from salt.utils.lazyproxy import LazyLoadProxy
|
||||
|
||||
|
||||
class ImmutableDict(collections.Mapping):
|
||||
'''
|
||||
@ -33,7 +30,7 @@ class ImmutableDict(collections.Mapping):
|
||||
return iter(self.__obj)
|
||||
|
||||
def __getitem__(self, key):
|
||||
return ImmutableLazyProxy(self.__obj[key])
|
||||
return freeze(self.__obj[key])
|
||||
|
||||
def __repr__(self):
|
||||
return '<{0} {1}>'.format(self.__class__.__name__, repr(self.__obj))
|
||||
@ -60,7 +57,7 @@ class ImmutableList(collections.Sequence):
|
||||
return other + self.__obj
|
||||
|
||||
def __getitem__(self, key):
|
||||
return ImmutableLazyProxy(self.__obj[key])
|
||||
return freeze(self.__obj[key])
|
||||
|
||||
def __repr__(self):
|
||||
return '<{0} {1}>'.format(self.__class__.__name__, repr(self.__obj))
|
||||
@ -87,21 +84,14 @@ class ImmutableSet(collections.Set):
|
||||
return '<{0} {1}>'.format(self.__class__.__name__, repr(self.__obj))
|
||||
|
||||
|
||||
class ImmutableLazyProxy(LazyLoadProxy):
|
||||
def freeze(obj):
|
||||
'''
|
||||
LazyProxy which will return an immutable type when requested
|
||||
Freeze python types by turning them into immutable structures.
|
||||
'''
|
||||
|
||||
def __init__(self, obj):
|
||||
def __immutable_selection(obj):
|
||||
if isinstance(obj, dict):
|
||||
return ImmutableDict(obj)
|
||||
if isinstance(obj, list):
|
||||
return ImmutableList(obj)
|
||||
if isinstance(obj, set):
|
||||
return ImmutableSet(obj)
|
||||
return obj
|
||||
|
||||
super(ImmutableLazyProxy, self).__init__(
|
||||
lambda: __immutable_selection(obj)
|
||||
)
|
||||
if isinstance(obj, dict):
|
||||
return ImmutableDict(obj)
|
||||
if isinstance(obj, list):
|
||||
return ImmutableList(obj)
|
||||
if isinstance(obj, set):
|
||||
return ImmutableSet(obj)
|
||||
return obj
|
||||
|
@ -1,111 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
'''
|
||||
:copyright: © 2006 Tomer Filiba
|
||||
:copyright: © 2012 Cory Virok
|
||||
:copyright: © 2014 by the SaltStack Team, see AUTHORS for more details.
|
||||
:license: PSF
|
||||
|
||||
|
||||
salt.utils.lazyproxy
|
||||
~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Lazy object proxying, from the recipe found at:
|
||||
http://code.activestate.com/recipes/578014-lazy-load-object-proxying/
|
||||
'''
|
||||
|
||||
|
||||
class LazyLoadProxy(object):
|
||||
|
||||
__slots__ = ['_obj_fn', '__weakref__', '__proxy_storage']
|
||||
|
||||
def __init__(self, fn, storage=None):
|
||||
object.__setattr__(self, '_obj_fn', fn)
|
||||
object.__setattr__(self, '__proxy_storage', storage)
|
||||
|
||||
#
|
||||
# proxying (special cases)
|
||||
#
|
||||
def __getattribute__(self, name):
|
||||
return getattr(object.__getattribute__(self, '_obj_fn')(), name)
|
||||
|
||||
def __delattr__(self, name):
|
||||
delattr(object.__getattribute__(self, '_obj_fn')(), name)
|
||||
|
||||
def __setattr__(self, name, value):
|
||||
setattr(object.__getattribute__(self, '_obj_fn')(), name, value)
|
||||
|
||||
def __getitem__(self, index):
|
||||
return object.__getattribute__(self, '_obj_fn')().__getitem__(index)
|
||||
|
||||
def __nonzero__(self):
|
||||
return bool(object.__getattribute__(self, '_obj_fn')())
|
||||
|
||||
def __str__(self):
|
||||
return str(object.__getattribute__(self, '_obj_fn')())
|
||||
|
||||
def __repr__(self):
|
||||
return repr(object.__getattribute__(self, '_obj_fn')())
|
||||
|
||||
def __len__(self):
|
||||
return len(object.__getattribute__(self, '_obj_fn')())
|
||||
|
||||
#
|
||||
# factories
|
||||
#
|
||||
_special_names = [
|
||||
'__abs__', '__add__', '__and__', '__call__', '__cmp__', '__coerce__',
|
||||
'__contains__', '__delitem__', '__delslice__', '__div__', '__divmod__',
|
||||
'__eq__', '__float__', '__floordiv__', '__ge__', # '__getitem__',
|
||||
'__getslice__', '__gt__', '__hash__', '__hex__', '__iadd__', '__iand__',
|
||||
'__idiv__', '__idivmod__', '__ifloordiv__', '__ilshift__', '__imod__',
|
||||
'__imul__', '__int__', '__invert__', '__ior__', '__ipow__', '__irshift__',
|
||||
'__isub__', '__iter__', '__itruediv__', '__ixor__', '__le__', # '__len__',
|
||||
'__long__', '__lshift__', '__lt__', '__mod__', '__mul__', '__ne__',
|
||||
'__neg__', '__oct__', '__or__', '__pos__', '__pow__', '__radd__',
|
||||
'__rand__', '__rdiv__', '__rdivmod__', '__reduce__', '__reduce_ex__',
|
||||
'__repr__', '__reversed__', '__rfloorfiv__', '__rlshift__', '__rmod__',
|
||||
'__rmul__', '__ror__', '__rpow__', '__rrshift__', '__rshift__', '__rsub__',
|
||||
'__rtruediv__', '__rxor__', '__setitem__', '__setslice__', '__sub__',
|
||||
'__truediv__', '__xor__', 'next',
|
||||
]
|
||||
|
||||
@classmethod
|
||||
def _create_class_proxy(cls, theclass):
|
||||
'''creates a proxy for the given class'''
|
||||
|
||||
def make_method(name):
|
||||
def method(self, *args, **kw):
|
||||
return getattr(object.__getattribute__(self, '_obj_fn')(), name)(*args, **kw)
|
||||
return method
|
||||
|
||||
namespace = {}
|
||||
for name in cls._special_names:
|
||||
if hasattr(theclass, name):
|
||||
namespace[name] = make_method(name)
|
||||
return type('%s(%s)' % (cls.__name__, theclass.__name__), (cls,), namespace)
|
||||
|
||||
def __new__(cls, obj, *args, **kwargs):
|
||||
'''
|
||||
creates an proxy instance referencing `obj`. (obj, *args, **kwargs) are
|
||||
passed to this class' __init__, so deriving classes can define an
|
||||
__init__ method of their own.
|
||||
note: _class_proxy_cache is unique per deriving class (each deriving
|
||||
class must hold its own cache)
|
||||
'''
|
||||
try:
|
||||
cache = cls.__dict__['_class_proxy_cache']
|
||||
except KeyError:
|
||||
cls._class_proxy_cache = cache = {}
|
||||
try:
|
||||
theclass = cache[obj.__class__]
|
||||
except KeyError:
|
||||
cache[obj.__class__] = theclass = cls._create_class_proxy(obj.__class__)
|
||||
ins = object.__new__(theclass)
|
||||
theclass.__init__(ins, obj, *args, **kwargs)
|
||||
return ins
|
||||
|
||||
|
||||
class Proxy(LazyLoadProxy):
|
||||
|
||||
def __init__(self, obj):
|
||||
super(Proxy, self).__init__(lambda: obj)
|
@ -30,6 +30,56 @@ class ImmutableTypesTestCase(TestCase):
|
||||
__radd__ = lst + imt
|
||||
self.assertEqual(__radd__, [4, 5, 6, 1, 2, 3])
|
||||
|
||||
def test_freeze_list_sum(self):
|
||||
lst = [4, 5, 6]
|
||||
imt = immutabletypes.freeze([1, 2, 3])
|
||||
__add__ = imt + lst
|
||||
self.assertEqual(__add__, [1, 2, 3, 4, 5, 6])
|
||||
__radd__ = lst + imt
|
||||
self.assertEqual(__radd__, [4, 5, 6, 1, 2, 3])
|
||||
|
||||
def test_immutablelist_imutability(self):
|
||||
frozen = immutabletypes.freeze([1, 2, 3])
|
||||
with self.assertRaises(TypeError):
|
||||
frozen[1] = 2
|
||||
|
||||
def test_immutabledict_imutability(self):
|
||||
data = {
|
||||
1: 1,
|
||||
2: 2,
|
||||
3: {
|
||||
3.1: 3.1,
|
||||
3.2: 3.2,
|
||||
3.3: {
|
||||
3.31: 3.33,
|
||||
3.32: 3.34,
|
||||
3.33: [3.331, 3.332, 3.333]
|
||||
}
|
||||
},
|
||||
4: [4.1, 4.2, 4.3]
|
||||
}
|
||||
frozen = immutabletypes.freeze(data)
|
||||
with self.assertRaises(TypeError):
|
||||
frozen[1] = 2
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
fdict = frozen[3]
|
||||
fdict[3.1] = 5
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
fdict = frozen[3]
|
||||
fdict[3.4] = 3.4
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
frozen[3][3.3][3.32] = 3.99
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
frozen[3][3.3][3.33][0] = 5
|
||||
|
||||
with self.assertRaises(TypeError):
|
||||
flist = frozen[4]
|
||||
flist[0] = 5
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
from integration import run_tests
|
||||
|
Loading…
Reference in New Issue
Block a user