1
2
3
4
5
6
7
8
9
10
11 """
12 This module contains FileEntry class which is used to retrieve entries
13 from a file system. Since pulling data from the file system and parsing
14 it is expensive (especially when you have 100s of entries) we delay
15 fetching data until it's demanded.
16
17 The FileEntry calls EntryBase methods addToCache and getFromCache
18 to handle caching.
19 """
20
21 __revision__ = "$Revision: 913 $"
22
23 import time
24 import os
25 import re
26 from Pyblosxom import tools
27 from Pyblosxom.entries import base
28
29 -class FileEntry(base.EntryBase):
30 """
31 This class gets it's data and metadata from the file specified
32 by the filename argument.
33 """
34 - def __init__(self, request, filename, root, datadir=""):
35 """
36 @param request: the Request object
37 @type request: Request
38
39 @param filename: the complete filename for the file in question
40 including path
41 @type filename: string
42
43 @param root: i have no clue what this is
44 @type root: string
45
46 @param datadir: the datadir
47 @type datadir: string
48 """
49 base.EntryBase.__init__(self, request)
50 self._config = request.getConfiguration()
51 self._filename = filename.replace(os.sep, '/')
52 self._root = root.replace(os.sep, '/')
53
54 self._datadir = datadir or self._config["datadir"]
55 if self._datadir.endswith(os.sep):
56 self._datadir = self._datadir[:-1]
57
58 self._timetuple = tools.filestat(self._request, self._filename)
59 self._mtime = time.mktime(self._timetuple)
60 self._fulltime = time.strftime("%Y%m%d%H%M%S", self._timetuple)
61
62 self._populated_data = 0
63
65 """
66 Returns a representation of this instance with the filename
67 and root.
68 """
69 return "<fileentry f'%s' r'%s'>" % (self._filename, self._root)
70
71 - def setTimeLazy(self, timetuple):
72 """
73 Set the time without populating the entry.
74
75 @param timetuple: the mtime of the file (same as returned by
76 time.localtime(...))
77 @type timetuple: tuple of 9 ints
78 """
79 self._timetuple = timetuple
80 self._mtime = time.mktime(timetuple)
81 self._fulltime = time.strftime("%Y%m%d%H%M%S", timetuple)
82
84 """
85 Returns the id for this content item--in this case, it's the
86 filename.
87
88 @returns: the id of the fileentry (the filename)
89 @rtype: string
90 """
91 return self._filename
92
94 """
95 Returns the data for this file entry. The data is the parsed
96 (via the entryparser) content of the entry. We do this on-demand
97 by checking to see if we've gotten it and if we haven't then
98 we get it at that point.
99
100 @returns: the content for this entry
101 @rtype: string
102 """
103 if self._populated_data == 0:
104 self.__populatedata()
105 return self._data
106
108 """
109 This overrides the L{base.EntryBase} getMetadata method.
110
111 Note: We populate our metadata lazily--only when it's requested.
112 This delays parsing of the file as long as we can.
113
114 @param key: the key being sought
115 @type key: varies
116
117 @param default: the default to return if the key does not
118 exist
119 @type default: varies
120
121 @return: either the default (if the key did not exist) or the
122 value of the key in the metadata dict
123 @rtype: varies
124 """
125 if self._populated_data == 0:
126 self.__populatedata()
127
128 return self._metadata.get(key, default)
129
130 - def __populatedata(self):
131 """
132 Fills the metadata dict with metadata about the given file. This
133 metadata consists of things we pick up from an os.stat call as
134 well as knowledge of the filename and the root directory.
135 We then parse the file and fill in the rest of the information
136 that we know.
137 """
138 file_basename = os.path.basename(self._filename)
139
140 path = self._filename.replace(self._root, '')
141 path = path.replace(os.path.basename(self._filename), '')
142 path = path[:-1]
143
144 absolute_path = self._filename.replace(self._datadir, '')
145 absolute_path = self._filename.replace(self._datadir, '', 1)
146 absolute_path = absolute_path.replace(file_basename, '')
147 absolute_path = absolute_path[1:][:-1]
148
149 if absolute_path and absolute_path[-1] == "/":
150 absolute_path = absolute_path[0:-1]
151
152 filenamenoext = os.path.splitext(file_basename)[0]
153 if absolute_path == '':
154 file_path = filenamenoext
155 else:
156 file_path = '/'.join((absolute_path, filenamenoext))
157
158 tb_id = '%s/%s' % (absolute_path, filenamenoext)
159 tb_id = re.sub(r'[^A-Za-z0-9]', '_', tb_id)
160
161 self['path'] = path
162 self['tb_id'] = tb_id
163 self['absolute_path'] = absolute_path
164 self['file_path'] = file_path
165 self['fn'] = filenamenoext
166 self['filename'] = self._filename
167
168
169 self.setTime(self._timetuple)
170
171 data = self._request.getData()
172
173 entrydict = self.getFromCache(self._filename)
174 if not entrydict:
175 fileext = os.path.splitext(self._filename)
176 if fileext:
177 fileext = fileext[1][1:]
178
179 eparser = data['extensions'][fileext]
180 entrydict = eparser(self._filename, self._request)
181 self.addToCache(self._filename, entrydict)
182
183 self.update(entrydict)
184 self._populated_data = 1
185
186
187