]> git.phdru.name Git - bookmarks_db.git/blob - bkmk_objects.py
Moved DEFAULT_CHARSET to bkmk_objects.py.
[bookmarks_db.git] / bkmk_objects.py
1 """Objects to represent bookmarks.html structure
2
3 This file is a part of Bookmarks database and Internet robot.
4 """
5
6 __version__ = "$Revision$"[11:-2]
7 __revision__ = "$Id$"[5:-2]
8 __date__ = "$Date$"[7:-2]
9 __author__ = "Oleg Broytman <phd@phdru.name>"
10 __copyright__ = "Copyright (C) 2000-2011 PhiloSoft Design"
11 __license__ = "GNU GPL"
12
13 __all__ = ['Folder', 'Bookmark', 'Ruler', 'Walker', 'Writer', 'Robot',
14     'InverseLinker', 'Linear', 'make_linear', 'make_tree', 'break_tree',
15     'quote_title', 'unquote_title',
16 ]
17
18
19 import os, cgi
20 from m_lib.defenc import default_encoding as DEFAULT_CHARSET
21
22 BKMK_FORMAT = os.environ.get("BKMK_FORMAT", "MOZILLA")
23
24 class Folder(list):
25    isFolder = 1
26    isBookmark = 0
27
28    def __init__(self, add_date=None, comment='', last_modified=None):
29       super(Folder, self).__init__()
30       self.comment = comment
31       self.add_date = add_date
32       self.last_modified = last_modified
33
34    def walk_depth(self, walker, level=0):
35       if hasattr(self, "header"): # root folder
36          prune = 0
37          walker.root_folder(self)
38       else:
39          prune = walker.prune_folder(self)
40          if not prune:
41             walker.start_folder(self, level)
42
43       if not prune:
44          for object in self:
45             if object.isFolder:
46                object.walk_depth(walker, level+1)
47             elif object.isBookmark:
48                walker.bookmark(object, level)
49             else:
50                walker.ruler(object, level)
51
52          walker.end_folder(self, level)
53
54
55 class Bookmark:
56    isFolder = 0
57    isBookmark = 1
58
59    def __init__(self, href, add_date, last_visit=None, last_modified=None,
60          keyword=None, comment='', icon_href=None, icon=None, charset=None):
61       self.href = href
62       self.add_date = add_date
63       self.last_visit = last_visit
64       self.last_modified = last_modified
65       self.keyword = keyword
66       self.comment = comment
67       self.icon_href = icon_href
68       self.icon = icon
69       self.charset = charset
70
71
72 class Ruler:
73    isFolder = 0
74    isBookmark = 0
75
76
77 class Walker:
78    """
79       Interface class. Any instance that will be passed to Folder.walk_depth
80       may be derived from this class. It is not mandatory - unlike Java
81       Python does not require interface classes; but it is convenient to have
82       some methods predefined to no-op, in case you do not want to
83       provide end_folder etc.
84    """
85
86    def root_folder(self, r):
87       pass
88
89    def start_folder(self, f, level):
90       pass
91
92    def end_folder(self, f, level):
93       pass
94
95    def bookmark(self, b, level):
96       pass
97
98    def ruler(self, r, level):
99       pass
100
101    def prune_folder(self, folder):
102       return 0
103
104
105 class Writer(Walker):
106    def __init__(self, outfile, prune=None):
107       self.outfile = outfile
108       self.prune = prune
109
110    def prune_folder(self, folder):
111       return self.prune == folder.name
112
113
114 class Robot:
115    def __init__(self, log):
116       self.log = log
117
118    def stop(self):
119       pass # Nothing to do on cleanup
120
121
122 # Helper class to make inverese links (nodes linked to their parent)
123 class InverseLinker(Walker):
124    def root_folder(self, r):
125       self.parent_stack = [r]
126
127    def start_folder(self, f, level):
128       f.parent = self.parent_stack[-1]
129       self.parent_stack.append(f) # Push the folder onto the stack of parents
130
131    def end_folder(self, f, level):
132       del self.parent_stack[-1]   # Pop off the stack
133
134    def bookmark(self, b, level):
135       b.parent = self.parent_stack[-1]
136
137    def ruler(self, r, level):
138       r.parent = self.parent_stack[-1]
139
140
141 # Helper class to make linear represenatation of the tree
142 class Linear(Walker):
143    def root_folder(self, r):
144       r.linear = [r]
145       self.linear = r.linear
146
147    def add_object(self, object):
148       self.linear.append(object)
149
150    def start_folder(self, f, level):
151       self.add_object(f)
152
153    def bookmark(self, b, level):
154       self.add_object(b)
155
156    def ruler(self, r, level):
157       self.add_object(r)
158
159
160 # Helper - make linked linear represenatation of the tree, suitable to be stored in sequential storage
161 def make_linear(root_folder):
162    linker = InverseLinker()
163    root_folder.walk_depth(linker)
164
165    linear = Linear()
166    root_folder.walk_depth(linear)
167
168
169 # Helper, opposite of make_linear - make a tree from the linked linear representation
170 def make_tree(linear):
171    root_folder = linear[0]
172    del linear[0]
173
174    for object in linear:
175       object.parent.append(object)
176
177    return root_folder
178
179 def break_tree(linear):
180    del linear[0]
181
182    for object in linear:
183       del object.parent
184
185
186 def quote_title(title):
187    if BKMK_FORMAT == "MOZILLA":
188       title = title.replace("'", "&#39;")
189    return title
190
191 def unquote_title(title):
192    if BKMK_FORMAT == "MOZILLA":
193       from HTMLParser import HTMLParser
194       title = HTMLParser().unescape(title.replace("&amp;", '&'))
195       title = title.replace("&#39;", "'")
196    return title