~ubuntu-branches/ubuntu/precise/checkbox/precise

« back to all changes in this revision

Viewing changes to checkbox/lib/template.py

  • Committer: Bazaar Package Importer
  • Author(s): Marc Tardif
  • Date: 2009-01-20 16:46:15 UTC
  • Revision ID: james.westby@ubuntu.com-20090120164615-7iz6nmlef41h4vx2
Tags: 0.4
* Setup bzr-builddeb in native mode.
* Removed LGPL notice from the copyright file.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#
 
2
# Copyright (c) 2008 Canonical
 
3
#
 
4
# Written by Marc Tardif <marc@interunion.ca>
 
5
#
 
6
# This file is part of Checkbox.
 
7
#
 
8
# Checkbox is free software: you can redistribute it and/or modify
 
9
# it under the terms of the GNU General Public License as published by
 
10
# the Free Software Foundation, either version 3 of the License, or
 
11
# (at your option) any later version.
 
12
#
 
13
# Checkbox is distributed in the hope that it will be useful,
 
14
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
15
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
16
# GNU General Public License for more details.
 
17
#
 
18
# You should have received a copy of the GNU General Public License
 
19
# along with Checkbox.  If not, see <http://www.gnu.org/licenses/>.
 
20
#
 
21
import os
 
22
import re
 
23
import logging
 
24
import posixpath
 
25
 
 
26
 
 
27
class Template(object):
 
28
 
 
29
    def __init__(self, filename_field=None, unique_fields=[]):
 
30
        self._filename_field = filename_field
 
31
        self._unique_fields = unique_fields
 
32
 
 
33
    def _reader(self, file, size=4096, delimiter="\n\n"):
 
34
        buffer_old = ""
 
35
        while True:
 
36
            buffer_new = file.read(size)
 
37
            if not buffer_new:
 
38
                break
 
39
 
 
40
            lines = (buffer_old + buffer_new).split(delimiter)
 
41
            buffer_old = lines.pop(-1)
 
42
 
 
43
            for line in lines:
 
44
                yield line
 
45
 
 
46
        yield buffer_old
 
47
 
 
48
    def load_file(self, file, filename="<stream>"):
 
49
        elements = []
 
50
        for string in self._reader(file):
 
51
            if not string:
 
52
                break
 
53
 
 
54
            element = {}
 
55
 
 
56
            def _save(field, value, extended):
 
57
                extended = extended.rstrip("\n")
 
58
                if field:
 
59
                    if element.has_key(field):
 
60
                        raise Exception, \
 
61
                            "Template %s has a duplicate field '%s'" \
 
62
                            " with a new value '%s'." \
 
63
                                % (filename, field, value)
 
64
                    element[field] = value
 
65
                    if extended:
 
66
                        element["%s_extended" % field] = extended
 
67
 
 
68
            string = string.strip("\n")
 
69
            field = value = extended = ""
 
70
            for line in string.split("\n"):
 
71
                line.strip()
 
72
                match = re.search(r"^([-_.A-Za-z0-9]*):\s?(.*)", line)
 
73
                if match:
 
74
                    _save(field, value, extended)
 
75
                    field = match.groups()[0].lower()
 
76
                    value = match.groups()[1].rstrip()
 
77
                    extended = ""
 
78
                    continue
 
79
 
 
80
                if re.search(r"^\s\.$", line):
 
81
                    extended += "\n\n"
 
82
                    continue
 
83
 
 
84
                match = re.search(r"^\s(\s+.*)", line)
 
85
                if match:
 
86
                    bit = match.groups()[0].rstrip()
 
87
                    if len(extended) and not re.search(r"[\n ]$", extended):
 
88
                        extended += "\n"
 
89
 
 
90
                    extended += bit + "\n"
 
91
                    continue
 
92
 
 
93
                match = re.search(r"^\s(.*)", line)
 
94
                if match:
 
95
                    bit = match.groups()[0].rstrip()
 
96
                    if len(extended) and not re.search(r"[\n ]$", extended):
 
97
                        extended += " "
 
98
 
 
99
                    extended += bit
 
100
                    continue
 
101
 
 
102
                raise Exception, "Template %s parse error at: %s" \
 
103
                    % (filename, line)
 
104
 
 
105
            _save(field, value, extended)
 
106
 
 
107
            # Sanity checks
 
108
            if self._filename_field:
 
109
                if self._filename_field in element:
 
110
                    raise Exception, \
 
111
                        "Template %s already contains filename field: %s" \
 
112
                        % (filename, self._filename_field)
 
113
                element[self._filename_field] = posixpath.basename(filename)
 
114
 
 
115
            for unique_field in self._unique_fields:
 
116
                if [e for e in elements \
 
117
                   if e[unique_field] == element[unique_field]]:
 
118
                    raise Exception, \
 
119
                        "Template %s contains duplicate fields: %s" \
 
120
                        % (filename, unique_field)
 
121
 
 
122
            elements.append(element)
 
123
 
 
124
        return elements
 
125
 
 
126
    def load_filename(self, filename):
 
127
        logging.info("Loading elements from filename: %s", filename)
 
128
 
 
129
        file = open(filename, "r")
 
130
        return self.load_file(file, filename)
 
131
 
 
132
    def load_directory(self, directory, blacklist=[], whitelist=[]):
 
133
        logging.info("Loading filenames from directory: %s", directory)
 
134
 
 
135
        elements = []
 
136
        if whitelist:
 
137
            names = whitelist
 
138
        else:
 
139
            names = [n for n in os.listdir(directory) if n not in blacklist]
 
140
 
 
141
        for name in names:
 
142
            if name.startswith(".") or name.endswith("~"):
 
143
                logging.info("Ignoring filename: %s", name)
 
144
                continue
 
145
 
 
146
            filename = posixpath.join(directory, name)
 
147
            elements.extend(self.load_filename(filename))
 
148
 
 
149
        return elements
 
150
 
 
151
    def load_directories(self, directories, blacklist=[], whitelist=[]):
 
152
        elements = []
 
153
        for directory in directories:
 
154
            elements.extend(self.load_directory(directory, blacklist, whitelist))
 
155
 
 
156
        return elements