Skip to content

Commit

Permalink
Merge pull request #27 from HolmesNL/bugfix/deny-set-attribute
Browse files Browse the repository at this point in the history
Deny setting non-protected attributes
  • Loading branch information
akaIDIOT committed Jul 9, 2018
2 parents dd0a5ef + e20da08 commit d485a3a
Show file tree
Hide file tree
Showing 3 changed files with 51 additions and 0 deletions.
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ development (master)

- Enable escaping underscores in environment variables (``NAME_FOO__BAR`` results in ``config.foo_bar``)
- Use ``yaml.safe_load`` to avoid security issues with ``yaml.load``
- Raise ``AttributeError`` when attempting to set a non-protected attribute on a `Configuration` instance

0.3 (2018-05-24)
----------------
Expand Down
14 changes: 14 additions & 0 deletions confidence.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,20 @@ def __getattr__(self, attr):
"""
return self.get(attr, default=NotConfigured)

def __setattr__(self, name, value):
"""
Attempts to set a named attribute to this `.Configuration` instance.
Only protected / private style attribute names are accepted, anything
not starting with an underscore will raise an `AttributeError`.
:param name: name of the attribute to set
:param value: value to be associated to *name*
"""
if name.startswith('_'):
super().__setattr__(name, value)
else:
raise AttributeError('assignment not supported ({})'.format(name))

def __len__(self):
return len(self._source)

Expand Down
36 changes: 36 additions & 0 deletions tests/test_namespace.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from collections import Mapping

import pytest

from confidence import Configuration, NotConfigured


Expand Down Expand Up @@ -51,3 +53,37 @@ def test_dir():
assert 'key1' in dir(subject)
assert 'namespace' in dir(subject)
assert 'key3' in dir(subject.namespace)


def test_assignments():
subject = Configuration({'key1': 'value', 'key2': 5, 'namespace.key3': False})

subject._private = 42
subject.__very_private = 43

assert subject._private == 42
assert subject.__very_private == 43

with pytest.raises(AttributeError) as e:
subject.non_existent = True
assert 'assignment not supported' in str(e.value) and 'non_existent' in str(e.value)

with pytest.raises(AttributeError) as e:
subject.key1 = True
assert 'assignment not supported' in str(e.value) and 'key1' in str(e.value)

with pytest.raises(AttributeError) as e:
subject.namespace.key3 = True
assert 'assignment not supported' in str(e.value) and 'key3' in str(e.value)

with pytest.raises(AttributeError) as e:
subject.namespace.key4 = True
assert 'assignment not supported' in str(e.value) and 'key4' in str(e.value)

with pytest.raises(AttributeError) as e:
subject.non_existent.key6 = True
assert 'assignment not supported' in str(e.value) and 'key6' in str(e.value)

with pytest.raises(AttributeError) as e:
subject.we.must.go.deeper = True
assert 'assignment not supported' in str(e.value) and 'deeper' in str(e.value)

0 comments on commit d485a3a

Please sign in to comment.