dirk / constrictor

Powerful Python web-development framework.

This URL has Read+Write access

constrictor / controller.py
100644 74 lines (71 sloc) 2.635 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
def Expose(func):
  """
This is to prevent methods that aren't supposed to be able to be
called from being called through wild-card method-name-based
routing systems.
"""
  # Checks to make sure that the method has not been previously prevented from
  # being exposed (Currently only a Filter would do this).
  if func.__dict__.has_key('Expose') and func.Expose is False:
    raise AttributeError, 'Method cannot be exposed _and_ be a filter at the same time!'
  func.Expose = True
  return func
class Filtering(object):
  """
Class for setting functions of controllers to be filters.
Priority defines their sort order. Filters are sorted by priority (With 0
being the lowest priority) and then alphabetically (With "A" coming first).
"""
  def filter(self, func):
    # Checks to make sure that the method has not been exposed, since filters
    # should not be exposed.
    if func.__dict__.has_key('Expose') and func.Expose is True:
      raise AttributeError, 'Method cannot be a filter _and_ be exposed at the same time!'
    func.Expose = False
  # Functions that handle the decorators.
  def Before(self, func):
    self.filter(func)
    func.Filter = 'Before'
    func.Priority = 0
    return func
  def After(self, func):
    self.filter(func)
    func.Filter = 'After'
    func.Priority = 0
    return func
# Initialize the Filtering class and put it in the namespace as Filter.
Filter = Filtering()
 
class Controller(object):
  """A controller for processing requests."""
  # Example of using the Before and After filters and exposing methods.
  # * The append() method is used because it's the easiest, clearest, and
  # simplest way of doing this, and avoids unnecessary abstraction.
  #@Filter.Before
  #def my_before_filter(self):
  # pass
  #my_before_filter.Priority = 5
  # ^ Optional priority definition, the higher numbered filters are executed first.
  #@Expose
  #def my_exposed_method(self):
  # pass
  
  def _filter_for(self, filter_type):
    """
Iterates through the methods of the Controller and finds methods with a
Filter attribute that is equal to filter_type.
"""
    filters = []
    for item in dir(self):
      if not item.startswith('__'):
        method = self.__getattribute__(item)
        try:
          if method.Filter is filter_type:
            filters.append(method)
          else: continue
        except AttributeError: continue
      else: continue
    filters.sort(key=lambda obj: (obj.Priority * -1))
    return filters
  def before_filters(self):
    return self._filter_for('Before')
  def after_filters(self):
    return self._filter_for('After')