diff --git a/package/MDAnalysis/lib/util.py b/package/MDAnalysis/lib/util.py index 3596be4518f..1d5b92ae203 100644 --- a/package/MDAnalysis/lib/util.py +++ b/package/MDAnalysis/lib/util.py @@ -1331,29 +1331,30 @@ def blocks_of(a, n, m): return np.lib.stride_tricks.as_strided(a, new_shape, new_strides) -class Namespace(object): +class Namespace(dict): """Class to allow storing attributes in new namespace. """ def __getattr__(self, key): # a.this causes a __getattr__ call for key = 'this' - return self.__dict__[key] + try: + return dict.__getitem__(self, key) + except KeyError: + raise AttributeError('"{}" is not known in the namespace.' + .format(key)) + def __setattr__(self, key, value): - # a.this = 10 causes a __setattr__ call for key='this' value=10 - self.__dict__[key] = value + dict.__setitem__(self, key, value) + def __delattr__(self, key): - del self.__dict__[key] + try: + dict.__delitem__(self, key) + except KeyError: + raise AttributeError('"{}" is not known in the namespace.' + .format(key)) + def __eq__(self, other): try: # this'll allow us to compare if we're storing arrays - assert_equal(self.__dict__, other.__dict__) + assert_equal(self, other) except AssertionError: return False return True - def __str__(self): - return str(self.__dict__) - def __len__(self): - return len(self.__dict__) - def __getitem__(self, key): - return self.__dict__[key] - def __iter__(self): - for i in self.__dict__: - yield i diff --git a/testsuite/MDAnalysisTests/coordinates/base.py b/testsuite/MDAnalysisTests/coordinates/base.py index 1c01aeac012..1f23f041f32 100644 --- a/testsuite/MDAnalysisTests/coordinates/base.py +++ b/testsuite/MDAnalysisTests/coordinates/base.py @@ -293,7 +293,7 @@ def test_add_same_auxname_raises_ValueError(self): def test_remove_auxiliary(self): self.reader.remove_auxiliary('lowf') assert_raises(AttributeError, getattr, self.reader._auxs, 'lowf') - assert_raises(KeyError, getattr, self.reader.ts.aux, 'lowf') + assert_raises(AttributeError, getattr, self.reader.ts.aux, 'lowf') @raises(ValueError) def test_remove_nonexistant_auxiliary_raises_ValueError(self): @@ -344,7 +344,7 @@ def test_rename_aux(self): assert_equal(self.reader.ts.aux.lowf_renamed, self.ref.aux_lowf_data[0]) # old name should be removed - assert_raises(KeyError, getattr, self.reader.ts.aux, 'lowf') + assert_raises(AttributeError, getattr, self.reader.ts.aux, 'lowf') # new name should be retained next(self.reader) assert_equal(self.reader.ts.aux.lowf_renamed, diff --git a/testsuite/MDAnalysisTests/test_util.py b/testsuite/MDAnalysisTests/lib/test_util.py similarity index 94% rename from testsuite/MDAnalysisTests/test_util.py rename to testsuite/MDAnalysisTests/lib/test_util.py index f1490f04242..bbd5e30fe42 100644 --- a/testsuite/MDAnalysisTests/test_util.py +++ b/testsuite/MDAnalysisTests/lib/test_util.py @@ -819,3 +819,80 @@ def test_blocks_of_VE(self): arr = np.arange(16).reshape(4, 4) assert_raises(ValueError, util.blocks_of, arr, 2, 1) + + +class TestNamespace(object): + def setUp(self): + self.ns = util.Namespace() + + def tearDown(self): + del self.ns + + def test_getitem(self): + self.ns.this = 42 + + assert_(self.ns['this'] == 42) + + def test_getitem_KE(self): + assert_raises(KeyError, dict.__getitem__, self.ns, 'this') + + def test_setitem(self): + self.ns['this'] = 42 + + assert_(self.ns['this'] == 42) + + def test_delitem(self): + self.ns['this'] = 42 + assert_('this' in self.ns) + del self.ns['this'] + assert_(not ('this' in self.ns)) + + def test_delitem_AE(self): + def deller(): + del self.ns.this + assert_raises(AttributeError, deller) + + def test_setattr(self): + self.ns.this = 42 + + assert_(self.ns.this == 42) + + def test_getattr(self): + self.ns['this'] = 42 + + assert_(self.ns.this == 42) + + def test_getattr_AE(self): + assert_raises(AttributeError, getattr, self.ns, 'this') + + def test_delattr(self): + self.ns['this'] = 42 + + assert_('this' in self.ns) + del self.ns.this + assert_(not ('this' in self.ns)) + + def test_eq(self): + self.ns['this'] = 42 + + ns2 = util.Namespace() + ns2['this'] = 42 + + assert_(self.ns == ns2) + + def test_len(self): + assert_(len(self.ns) == 0) + self.ns['this'] = 1 + self.ns['that'] = 2 + assert_(len(self.ns) == 2) + + def test_iter(self): + self.ns['this'] = 12 + self.ns['that'] = 24 + self.ns['other'] = 48 + + seen = [] + for val in self.ns: + seen.append(val) + for val in ['this', 'that', 'other']: + assert_(val in seen)