1 """Objects to represent bookmarks.html structure
3 This file is a part of Bookmarks database and Internet robot.
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"
13 __all__ = ['Folder', 'Bookmark', 'Ruler', 'Walker', 'Writer', 'Robot',
14 'InverseLinker', 'Linear', 'make_linear', 'make_tree', 'break_tree',
15 'quote_title', 'unquote_title',
20 from m_lib.defenc import default_encoding as DEFAULT_CHARSET
22 BKMK_FORMAT = os.environ.get("BKMK_FORMAT", "MOZILLA")
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
34 def walk_depth(self, walker, level=0):
35 if hasattr(self, "header"): # root folder
37 walker.root_folder(self)
39 prune = walker.prune_folder(self)
41 walker.start_folder(self, level)
46 object.walk_depth(walker, level+1)
47 elif object.isBookmark:
48 walker.bookmark(object, level)
50 walker.ruler(object, level)
52 walker.end_folder(self, level)
59 def __init__(self, href, add_date, last_visit=None, last_modified=None,
60 keyword=None, comment='', icon_href=None, icon=None, charset=None):
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
69 self.charset = charset
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.
86 def root_folder(self, r):
89 def start_folder(self, f, level):
92 def end_folder(self, f, level):
95 def bookmark(self, b, level):
98 def ruler(self, r, level):
101 def prune_folder(self, folder):
105 class Writer(Walker):
106 def __init__(self, outfile, prune=None):
107 self.outfile = outfile
110 def prune_folder(self, folder):
111 return self.prune == folder.name
115 def __init__(self, log):
119 pass # Nothing to do on cleanup
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]
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
131 def end_folder(self, f, level):
132 del self.parent_stack[-1] # Pop off the stack
134 def bookmark(self, b, level):
135 b.parent = self.parent_stack[-1]
137 def ruler(self, r, level):
138 r.parent = self.parent_stack[-1]
141 # Helper class to make linear represenatation of the tree
142 class Linear(Walker):
143 def root_folder(self, r):
145 self.linear = r.linear
147 def add_object(self, object):
148 self.linear.append(object)
150 def start_folder(self, f, level):
153 def bookmark(self, b, level):
156 def ruler(self, r, level):
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)
166 root_folder.walk_depth(linear)
169 # Helper, opposite of make_linear - make a tree from the linked linear representation
170 def make_tree(linear):
171 root_folder = linear[0]
174 for object in linear:
175 object.parent.append(object)
179 def break_tree(linear):
182 for object in linear:
186 def quote_title(title):
187 if BKMK_FORMAT == "MOZILLA":
188 title = title.replace("'", "'")
191 def unquote_title(title):
192 if BKMK_FORMAT == "MOZILLA":
193 from HTMLParser import HTMLParser
194 title = HTMLParser().unescape(title.replace("&", '&'))
195 title = title.replace("'", "'")