summaryrefslogtreecommitdiff
path: root/pystache/view.py
blob: 925998e2336ba3c1803c63bd01181e348b236519 (plain)
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
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
from pystache import Template
import os.path
import re
from types import *

def get_or_attr(context_list, name, default=None):
    if not context_list:
        return default

    for obj in context_list:
        try:
            return obj[name]
        except KeyError:
            pass
        except:
            try:
                return getattr(obj, name)
            except AttributeError:
                pass
    return default

class View(object):
    
    template_name = None
    template_path = None
    template = None
    template_encoding = None
    template_extension = 'mustache'
    
    def __init__(self, template=None, context=None, **kwargs):
        self.template = template
        context = context or {}
        context.update(**kwargs)

        self.context_list = [context]
        
    def get(self, attr, default=None):
        attr = get_or_attr(self.context_list, attr, getattr(self, attr, default))
        if hasattr(attr, '__call__') and type(attr) is UnboundMethodType:
            return attr()
        else:
            return attr
    
    def get_template(self, template_name):
        if not self.template:
            from pystache import Loader
            template_name = self._get_template_name(template_name)
            self.template = Loader().load_template(template_name, self.template_path, encoding=self.template_encoding, extension=self.template_extension)
        
        return self.template

    def _get_template_name(self, template_name=None):
        """TemplatePartial => template_partial
        Takes a string but defaults to using the current class' name or
        the `template_name` attribute
        """
        if template_name:
            return template_name

        template_name = self.__class__.__name__

        def repl(match):
            return '_' + match.group(0).lower()

        return re.sub('[A-Z]', repl, template_name)[1:]

    def _get_context(self):
        context = {}
        for item in self.context_list:
            if hasattr(item, 'keys') and hasattr(item, '__getitem__'):
                context.update(item)
        return context

    def render(self, encoding=None):
        return Template(self.get_template(self.template_name), self).render(encoding=encoding)

    def __contains__(self, needle):
        return needle in self.context or hasattr(self, needle)

    def __getitem__(self, attr):
        val = self.get(attr, None)

        if not val and val is not 0:
            raise KeyError("Key '%s' does not exist in View" % attr)
        return val

    def __getattr__(self, attr):
        if attr == 'context':
            return self._get_context()

        raise AttributeError("Attribute '%s' does not exist in View" % attr)

    def __str__(self):
        return self.render()