context.py

A MutableMapping subclass for use as a request-local context object.

Imports

from __future__ import unicode_literals

from collections import MutableMapping

Mapping Class

An attribute access dictionary, of a kind.

This utility class is used to cooperatively construct the ApplicationContext (and subsequent RequestContext) from the contributions of multiple extensions. The concept of "promotion to a class" is needed in order to enable the use of descriptor protocol attributes; without promotion the protocol would not be utilized.

class Context(MutableMapping):
	

M-Morty! We're, belch, gonna have to go in deep, Morty! Elbow deep!

Create a new subclass of Context which incorporates instance attributes and new descriptors.

This promotes an instance and its instance attributes up to being a class with class attributes, then returns an instance of that class.

	def _promote(self, name, instantiate=True):
		
		metaclass = type(self.__class__)
		contents = self.__dict__.copy()
		cls = metaclass(str(name), (self.__class__, ), contents)
		
		if instantiate:
			return cls()
		
		return cls
	

Construct a new Context instance.

All keyword arguments are applied to the instance as attributes through direct assignment to __dict__.

	def __init__(self, **kw):
		self.__dict__.update(kw)
		super(Context, self).__init__()
	

Get a list of the public data attributes.

	def __len__(self):
		return len([i for i in (set(dir(self)) - self._STANDARD_ATTRS) if i[0] != '_'])
	

Iterate all valid (public) attributes/keys.

	def __iter__(self):
		return (i for i in (set(dir(self)) - self._STANDARD_ATTRS) if i[0] != '_')
	

Retrieve an attribute through dictionary access.

	def __getitem__(self, name):
		try:
			return getattr(self, name)
		except AttributeError:
			pass
		

We do this here to avoid Python 3's nested exception support.

		raise KeyError(name)
	

Assign an attribute through dictionary access.

	def __setitem__(self, name, value):
		setattr(self, name, value)
	

Delete an attribute through dictionary access.

	def __delitem__(self, name):
		try:
			return delattr(self, name)
		except AttributeError:
			pass
		

We do this here to avoid Python 3's nested exception support.

		raise KeyError(name)

We generally want to exclude "default object attributes" from the context's list of attributes. This auto-detects the basic set of them for exclusion from iteration in the above methods.

Context._STANDARD_ATTRS = set(dir(Context()))