Attachment 'header.py'
Download 1 """
2 MoinMoin header
3 ===============
4
5 Header represent wiki page header, which include comments, processing
6 instructions and pragmas. The header parse text and save all valid
7 header in the text. Headers are accessed like a dict.
8
9 If you want to add custom handling of certain headers, subclass and
10 add set_xxx methods. The method will be called by the parser for each
11 found header with that name. To change the default handling of headers,
12 override setHeader.
13
14 Usage
15 -----
16 ::
17 header = Header(request, text)
18 # This will triger parsing of text
19 language = header['language']
20
21 @copyright: 2005 Nir Soffer <nirs@freeshell.org>
22 @license: GNU GPL, see COPYING for details.
23 """
24
25 import re
26 from MoinMoin import i18n
27
28
29 class Header(object):
30 """ Immutable wiki page header
31
32 Header represent the wiki page header, using # to add comments,
33 processing instructinos and pragmas.
34
35 Header parsing is done lazily, on the first accessor call.
36 """
37 # -----------------------------------------------------------------
38 # Creation
39
40 def __init__(self, request, text):
41 self.request = request
42 self.text = text
43 self._headers = None
44 self._length = None
45
46 # -----------------------------------------------------------------
47 # Accessing
48
49 # Header is accessed like a dict - save a lot of getter methods.
50
51 def __getitem__(self, key):
52 """ dict style obj[key] handler """
53 return self.headers()[key]
54
55 def get(self, key, default=None):
56 """ dict style obj.get(key) handler """
57 return self.headers().get(key, default)
58
59 def __contains__(self, key):
60 """ in obj handler """
61 return key in self.headers()
62
63 def length(self):
64 """ Return length of page header - not number of headers
65
66 Calculate by looking for the first character of the body.
67
68 Used internally to do eficient parsing, and may be used by other
69 to get only the body part of a page text.
70 """
71 if self._length is None:
72 match = self.bodyPattern().search(self.text)
73 if match:
74 self._length = match.start()
75 else:
76 # No body, all header
77 self._length = len(self.text)
78 return self._length
79
80 # -----------------------------------------------------------------
81 # Private
82
83 # Methods here are private, but does not use the _convetion, becasue
84 # it is less readable.
85
86 def headers(self):
87 """ Return headers dict, trigger parsing """
88 if self._headers is None:
89 self.parse()
90 return self._headers
91
92 def parse(self):
93 """ Start parsing, triggered automatically """
94 self._headers = {}
95 for line in self.text[:self.length()].splitlines():
96 if line.startswith('##'):
97 continue
98 key, value = self.splitTokens(line[1:])
99 setter = getattr(self, 'set_' + key, None)
100 if setter:
101 setter(value)
102 else:
103 self.setHeader(key, value)
104
105 def set_acl(self, value):
106 """ Save all acl lines in a list """
107 try:
108 self._headers['acl'].append(value)
109 except KeyError:
110 self._headers['acl'] = [value]
111
112 def set_language(self, value):
113 """ Save known languages, ignore other """
114 if value in i18n.wikiLanguages():
115 self.setHeader('language', value)
116
117 def set_cite(self, value):
118 """ Save source for blockquote parser """
119 self.setHeader('cite', value)
120
121 def set_pragma(self, text):
122 """ Save pragmas, ignore invalid pragmas """
123 key, value = self.splitTokens(text)
124 if value:
125 try:
126 self._headers['pragma'][key] = value
127 except KeyError:
128 self._headers['pragma'] = {key: value}
129
130 def setHeader(self, key, value):
131 """ Set header value, last value override """
132 self._headers[key] = value
133
134 def splitTokens(self, text):
135 """ Split first two tokens in text by whitespace """
136 try:
137 key, value = text.split(None, 1)
138 value = value.rstrip()
139 return key, value
140 except ValueError:
141 return text, ''
142
143 def bodyPattern(self):
144 """ Return shared compiled regular expression """
145 myClass = self.__class__
146 if not getattr(myClass, '_bodyPattern', False):
147 # Does not starts with # or empty (invalid) pi
148 myClass._bodyPattern = re.compile(r"^[^\#]|^\#\s",
149 re.MULTILINE | re.UNICODE)
150 return myClass._bodyPattern
Attached Files
To refer to attachments on a page, use attachment:filename, as shown below in the list of files. Do NOT use the URL of the [get] link, since this is subject to change and can break easily.You are not allowed to attach a file to this page.