summaryrefslogtreecommitdiff
path: root/pystache/locator.py
blob: 2ef2fc569b46117a79863009fab6d9f98d1362eb (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
95
96
97
98
99
# coding: utf-8

"""
This module provides a Locator class for finding template files.

"""

import os
import re
import sys


DEFAULT_EXTENSION = 'mustache'


class Locator(object):

    def __init__(self, extension=None):
        """
        Construct a template locator.

        Arguments:

          extension: the template file extension.  Defaults to "mustache".
            Pass False for no extension (i.e. extensionless template files).

        """
        if extension is None:
            extension = DEFAULT_EXTENSION

        self.template_extension = extension


    def _find_path(self, file_name, search_dirs):
        """
        Search for the given file, and return the path.

        Returns None if the file is not found.

        """
        for dir_path in search_dirs:
            file_path = os.path.join(dir_path, file_name)
            if os.path.exists(file_path):
                return file_path

        return None

    def make_file_name(self, template_name):
        file_name = template_name
        if self.template_extension is not False:
            file_name += os.path.extsep + self.template_extension

        return file_name

    def make_template_name(self, obj):
        """
        Return the canonical template name for an object instance.

        This method converts Python-style class names (PEP 8's recommended
        CamelCase, aka CapWords) to lower_case_with_underscords.  Here
        is an example with code:

        >>> class HelloWorld(object):
        ...     pass
        >>> hi = HelloWorld()
        >>>
        >>> locator = Locator()
        >>> locator.make_template_name(hi)
        'hello_world'

        """
        template_name = obj.__class__.__name__

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

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

    def locate_path(self, template_name, search_dirs):
        """
        Find and return the path to the template with the given name.

        Raises an IOError if the template cannot be found.

        Arguments:

          search_dirs: the list of directories in which to search for templates.

        """
        file_name = self.make_file_name(template_name)

        path = self._find_path(file_name, search_dirs)

        if path is not None:
            return path

        # TODO: we should probably raise an exception of our own type.
        raise IOError('Template %s not found in directories: %s' %
                      (repr(template_name), repr(search_dirs)))