def test_idempotent(): q = Cls() p = frozen(q) r = frozen(p) assert p is not q assert p is r assert p.li is not q.li assert p.li is r.li
def test_nesting_mutable(): q = Cls() p = frozen(q) q.li.append(37) assert p.li == q.li q = [[0]] p = frozen(q) q[0][0] = 1 assert p == q
def test_nesting_immutable(): q = Cls() p = frozen(q) with raises(ImmutableError): p.li.append(37) q = [[0]] p = frozen(q) with raises(ImmutableError): p[0][0] = 1
def test_set_mutable(): q = {37,} p = frozen(q) q.add(42) q.remove(37) q &= {42} assert p == q
def test_list_mutable(): q = [37] p = frozen(q) q.append(42) q[0] = 0 assert len(p) == 2 assert q == p assert p[0] == 0
def test_instance_mutable(): q = Cls() p = frozen(q) q.attr += 37 assert q.attr == p.attr assert q.__dict__ == p.__dict__ del q.attr assert hasattr(p, 'attr') is False
def test_set_immutable(): q = {37,} p = frozen(q) with raises(ImmutableError): p.add(42) with raises(ImmutableError): p.remove(37) with raises(ImmutableError): p &= {42}
def test_dict_immutable(): q = {True: 37} p = frozen(q) with raises(ImmutableError): p[True] = 42 with raises(ImmutableError): p[False] = 42 with raises(ImmutableError): p.pop(True)
def test_list_immutable(): q = [37] p = frozen(q) with raises(ImmutableError): p[0] = 42 with raises(ImmutableError): p.append(42) with raises(ImmutableError): p.pop()
def test_simple_immutables_immutable(): for val in (42, 3.1415, 'hello', (1, 2, 3)): q = copy(val) p = frozen(q) try: p += val except ImmutableError: """ It may or may not raise an error (it probably doesn't); all that matters is that q is unchanged. """ assert q == val, 'type "" changed after becoming frozenobj'.format(type(q)) del p
def test_instance_immutable(): q = Cls() p = frozen(q) with raises(ImmutableError): p.attr += 37 with raises(ImmutableError): p.attr = 37 with raises(ImmutableError): del p.attr with raises(ImmutableError): p.mthd = lambda self: None
def test_dict_mutable(): q = {True: 37} p = frozen(q) q[False] = 42 q.pop(True) assert p == q == {False: 42}
def test_module(): p = frozen(sys) with raises(ImmutableError): p._random_test_value = 42
def load_actions(self, conf): """ Load actions like pretty much everything: pre-processors, parsers, tags, compilers, linkers, substitutions, post_processors and renderers). """ def instantiate_action(action, **kwargs): if isclass(action): try: action = action(self.config, **kwargs) except TypeError as err: raise InvalidPackageConfigError(( 'action {0:} for package {1:} did not accept the given arguments: ' 'config and kwargs {2:}; alternatively it might have raised a TypeError {3:}' ).format(action, self, kwargs, err)) if not hasattr(action, '__call__'): raise InvalidPackageConfigError(( 'action {0:} for package {1:} should be a class (and/)or a callable' ).format(action, self, kwargs)) return action #todo: better errors, also logging self._set_up_import_dir() if conf['config']: Config = Configuration if conf['config'] is True: Config = Configuration else: Config = self._import_from_package(conf['config']) self.config = Config(self.options, logger=frozen(self.logger), cache=frozen(self.cache), compile_conf=frozen(self.compile_conf), parser=frozen(self.packages.get_parser())) self.pre_processors = tuple( instantiate_action(self._import_from_package(obj_imp_path)) for obj_imp_path in conf['pre_processors']) if conf['parser']: Parser = self._import_from_package(conf['parser']) self.parser = Parser(self.config) # cache tags which are known under two names, for performance and so that they are identical _tag_alias_cache = {} for name, obj_imp_path in conf['tags'].items(): if obj_imp_path not in _tag_alias_cache: _tag_alias_cache[obj_imp_path] = instantiate_action( self._import_from_package(obj_imp_path)) self.tags[name] = _tag_alias_cache[obj_imp_path] self.compilers = tuple( instantiate_action(self._import_from_package(obj_imp_path)) for obj_imp_path in conf['compilers']) self.linkers = tuple( instantiate_action(self._import_from_package(obj_imp_path)) for obj_imp_path in conf['linkers']) if conf['substitutions']: #todo (maybe) raise NotImplementedError('substitutions') self.post_processors = tuple( instantiate_action(self._import_from_package(obj_imp_path)) for obj_imp_path in conf['post_processors']) if conf['renderer']: Renderer = self._import_from_package(conf['renderer']) self.renderer = Renderer(self.config)