Removed swap file.
[mime-editor.git] / type.py
blob84a557457fef00085efd5e7b39c793373534c377
1 import os
2 import rox
3 from xml.dom import minidom, Node, XML_NAMESPACE
4 try:
5 # The 4Suite parser is much faster, if present
6 from Ft.Xml.cDomlette import nonvalParse
7 from Ft.Xml.InputSource import InputSourceFactory
8 def parse(file):
9 isrc = InputSourceFactory()
10 return nonvalParse(isrc.fromUri(file))
11 except:
12 parse = minidom.parse
14 types = {}
16 home_mime = os.path.join(os.environ['HOME'], '.mime')
17 user_override = os.path.join(home_mime, 'packages', 'Override.xml')
19 FREE_NS='http://www.freedesktop.org/standards/shared-mime-info'
21 class Field:
22 def __init__(self, node):
23 self.node = node
25 def get(self):
26 return "<%s>" % self.node.localName
28 field_handlers = {}
30 def data(node):
31 """Return all the text directly inside this DOM Node."""
32 return ''.join([text.nodeValue for text in node.childNodes
33 if text.nodeType == Node.TEXT_NODE])
35 def get_type(name):
36 if name not in types:
37 types[name] = MIME_Type(name)
38 return types[name]
40 class MIME_Type:
41 def __init__(self, name):
42 assert name not in types
43 self.media, self.subtype = name.split('/')
44 self.sources = []
46 def add_from_node(self, file, node):
47 self.sources.append(Source(file, node))
49 def get_comment(self):
50 for src in self.sources:
51 comment = src.get_comment()
52 if comment:
53 return comment
54 return self.get_name()
56 def get_name(self):
57 return self.media + '/' + self.subtype
59 def add_user(self):
60 if self.sources and self.sources[-1].file == user_override:
61 return
62 self.sources.append(Source(user_override, None))
64 def get_comments(self): return self.merge('get_comments')
65 def get_globs(self): return self.merge('get_globs')
66 def get_magic(self): return self.merge('get_magic')
67 def get_xml(self): return self.merge('get_xml')
68 def get_others(self): return self.merge('get_others')
70 def merge(self, fn):
71 out = []
72 for s in self.sources:
73 out += getattr(s, fn)()
74 return out
76 class Field:
77 def __init__(self, node, src):
78 self.node = node
79 self.src = src
81 def __str__(self):
82 return "<%s>" % self.node.localName
84 def add_subtree(self, model, iter):
85 return
87 def __cmp__(self, b):
88 return cmp(str(self), str(b))
90 class Comment(Field):
91 def __str__(self):
92 lang = self.node.getAttributeNS(XML_NAMESPACE, 'lang')
93 if lang:
94 lang = '[' + lang + '] '
95 else:
96 lang = '(default) '
97 return lang + data(self.node)
99 class Glob(Field):
100 def __str__(self):
101 return "Match '%s'" % self.node.getAttributeNS(None, 'pattern')
103 class Magic(Field):
104 def __str__(self):
105 prio = self.node.getAttributeNS(None, 'priority') or '50'
106 return "Match with priority %s" % prio
108 def add_subtree(self, model, parent):
109 def build(node, parent):
110 for c in node.childNodes:
111 if c.nodeType != Node.ELEMENT_NODE: continue
112 text = '%s at %s = %s' % (c.getAttributeNS(None, 'type'),
113 c.getAttributeNS(None, 'offset'),
114 c.getAttributeNS(None, 'value'))
115 mask = c.getAttributeNS(None, 'mask')
116 if mask:
117 text += ' masked with ' + mask
118 iter = model.append(parent)
119 model.set(iter, 0, text)
120 build(c, iter)
121 build(self.node, parent)
123 def __cmp__(self, b):
124 ret = cmp(str(self), str(b))
125 if ret: return ret
126 return cmp(self.node, b.node)
128 class XML(Field):
129 def __str__(self):
130 ns = self.node.getAttributeNS(None, 'namespaceURI')
131 name = self.node.getAttributeNS(None, 'localName')
132 return "<%s> with namespace '%s'" % (name, ns)
134 class Others(Field): pass
136 class Source:
137 def __init__(self, file, node):
138 self.file = file
139 if not node:
140 newdoc = minidom.Document()
141 node = newdoc.createElementNS(FREE_NS, 'mime-type')
143 self.comments = []
144 self.globs = []
145 self.magic = []
146 self.xml = []
147 self.others = []
149 for c in node.childNodes:
150 if c.nodeType != Node.ELEMENT_NODE: continue
151 if c.namespaceURI == FREE_NS:
152 if c.localName == 'comment':
153 self.comments.append(c)
154 elif c.localName == 'glob':
155 self.globs.append(c)
156 elif c.localName == 'magic':
157 self.magic.append(c)
158 elif c.localName == 'root-XML':
159 self.xml.append(c)
160 else:
161 self.others.append(c)
162 else:
163 self.others.append(c)
165 def get_comment(self):
166 for field in self.comments:
167 return data(field)
169 def make(self, const, list):
170 return [const(node, self) for node in list]
172 def get_comments(self): return self.make(Comment, self.comments)
173 def get_globs(self): return self.make(Glob, self.globs)
174 def get_magic(self): return self.make(Magic, self.magic)
175 def get_xml(self): return self.make(XML, self.xml)
176 def get_others(self): return self.make(Others, self.others)
178 def init():
179 for mime_dir in ['/usr/share/mime', '/usr/local/share/mime', home_mime]:
180 packages_dir = os.path.join(mime_dir, 'packages')
181 if not os.path.isdir(packages_dir):
182 continue
183 for package in os.listdir(packages_dir):
184 if package == 'Override.xml' and mime_dir is home_mime: continue
185 scan_file(os.path.join(packages_dir, package))
186 scan_file(user_override)
188 for t in types.values():
189 t.add_user()
191 def scan_file(file):
192 if not file.endswith('.xml'): return
193 if not os.path.exists(file):
194 return
195 try:
196 doc = parse(file)
197 root = doc.documentElement
198 for node in root.childNodes:
199 if node.nodeType != Node.ELEMENT_NODE:
200 continue
201 type_name = node.getAttributeNS(None, 'type')
202 if type_name:
203 type = get_type(type_name)
204 type.add_from_node(file, node)
205 else:
206 print "Skipping", node
207 except:
208 rox.report_exception()