summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xbottle.py26
-rwxr-xr-xdocs/recipes.rst2
-rw-r--r--test/test_configdict.py32
-rwxr-xr-xtest/test_environ.py2
4 files changed, 43 insertions, 19 deletions
diff --git a/bottle.py b/bottle.py
index ab75dc5..b68b781 100755
--- a/bottle.py
+++ b/bottle.py
@@ -926,7 +926,7 @@ class BaseRequest(DictMixin):
property holds the parsed content of the request body. Only requests
smaller than :attr:`MEMFILE_MAX` are processed to avoid memory
exhaustion. '''
- if self.environ.get('CONTENT_TYPE') == 'application/json' \
+ if 'application/json' in self.environ.get('CONTENT_TYPE', '') \
and 0 < self.content_length < self.MEMFILE_MAX:
return json_loads(self.body.read(self.MEMFILE_MAX))
return None
@@ -1637,11 +1637,22 @@ class WSGIHeaderDict(DictMixin):
class ConfigDict(dict):
- ''' Subclass of dict that adds attribute-like access to its values. As a
- bonus, attribute access to missing keys result in a new ConfigDict. '''
+ ''' A dict-subclass with some extras: You can access keys like attributes.
+ Uppercase attributes create new ConfigDicts and act as name-spaces.
+ Other missing attributes return None. Calling a ConfigDict updates its
+ values and returns itself.
+
+ >>> cfg = ConfigDict()
+ >>> cfg.Namespace.value = 5
+ >>> cfg.OtherNamespace(a=1, b=2)
+ >>> cfg
+ {'Namespace': {'value': 5}, 'OtherNamespace': {'a': 1, 'b': 2}}
+ '''
def __getattr__(self, key):
- return self[key] if key in self else self.setdefault(key, ConfigDict())
+ if key in self: return self[key]
+ if key[0].isupper(): return self.setdefault(key, ConfigDict())
+ return
def __setattr__(self, key, value):
if hasattr(dict, key):
@@ -1653,6 +1664,10 @@ class ConfigDict(dict):
def __delattr__(self, key):
if key in self: del self[key]
+ def __call__(self, *a, **ka):
+ for key, value in dict(*a, **ka).iteritems(): setattr(self, key, value)
+ return self
+
class AppStack(list):
""" A stack-like list. Calling it returns the head of the stack. """
@@ -2643,10 +2658,9 @@ class SimpleTemplate(BaseTemplate):
eval(self.co, env)
if '_rebase' in env:
subtpl, rargs = env['_rebase']
- subtpl = self.__class__(name=subtpl, lookup=self.lookup)
rargs['_base'] = _stdout[:] #copy stdout
del _stdout[:] # clear stdout
- return subtpl.execute(_stdout, rargs)
+ return self.subtemplate(subtpl,_stdout,rargs)
return env
def render(self, *args, **kwargs):
diff --git a/docs/recipes.rst b/docs/recipes.rst
index 64ffbc1..0ecf074 100755
--- a/docs/recipes.rst
+++ b/docs/recipes.rst
@@ -99,7 +99,7 @@ or add a WSGI middleware that strips trailing slashes from all URLs::
app = bottle.app()
myapp = StripPathMiddleware(app)
- bottle.run(app=appmy)
+ bottle.run(app=myapp)
.. rubric:: Footnotes
diff --git a/test/test_configdict.py b/test/test_configdict.py
index c58d373..0d3f365 100644
--- a/test/test_configdict.py
+++ b/test/test_configdict.py
@@ -33,24 +33,34 @@ class TestConfigDict(unittest.TestCase):
self.assertEqual(6, c['test'])
del c.test
self.assertTrue('test' not in c)
+ self.assertEqual(None, c.test)
def test_namespaces(self):
- """ Access to a non-existent attribute creates a new namespace. """
+ """ Access to a non-existent uppercase attribute creates a new namespace. """
c = ConfigDict()
- self.assertEqual(c.__class__, c.d.e.__class__)
- c.d.e.f = 5
- self.assertEqual(5, c.d.e.f)
- self.assertTrue('f' in c.d.e)
- self.assertTrue('e' in c.d)
- self.assertTrue('d' in c)
- self.assertTrue('f' not in c)
+ self.assertEqual(c.__class__, c.Name.Space.__class__)
+ c.Name.Space.value = 5
+ self.assertEqual(5, c.Name.Space.value)
+ self.assertTrue('value' in c.Name.Space)
+ self.assertTrue('Space' in c.Name)
+ self.assertTrue('Name' in c)
+ self.assertTrue('value' not in c)
# Overwriting namespaces is not allowed.
- self.assertRaises(AttributeError, lambda: setattr(c, 'd', 5))
+ self.assertRaises(AttributeError, lambda: setattr(c, 'Name', 5))
# Overwriting methods defined on dict is not allowed.
self.assertRaises(AttributeError, lambda: setattr(c, 'keys', 5))
# but not with the dict API:
- c['d'] = 5
- self.assertEquals(5, c.d)
+ c['Name'] = 5
+ self.assertEquals(5, c.Name)
+
+ def test_call(self):
+ """ Calling updates and returns the dict. """
+ c = ConfigDict()
+ self.assertEqual(c, c(a=1))
+ self.assertTrue('a' in c)
+ self.assertEqual(1, c.a)
+
+
diff --git a/test/test_environ.py b/test/test_environ.py
index 49c34ba..ca755c6 100755
--- a/test/test_environ.py
+++ b/test/test_environ.py
@@ -318,7 +318,7 @@ class TestRequest(unittest.TestCase):
def test_json_valid(self):
""" Environ: Request.json property. """
test = dict(a=5, b='test', c=[1,2,3])
- e = {'CONTENT_TYPE': 'application/json'}
+ e = {'CONTENT_TYPE': 'application/json; charset=UTF-8'}
wsgiref.util.setup_testing_defaults(e)
e['wsgi.input'].write(tob(json_dumps(test)))
e['wsgi.input'].seek(0)