Added --create, which suppresses the 'do you want to create this file' question
[0publish.git] / validator.py
blobe74862f6a523ae5bf8c71ffff5206fbfdba16e7a
1 import os
2 from zeroinstall.injector import model, namespaces
3 from zeroinstall.injector.reader import InvalidInterface, update
4 from xml.dom import minidom, Node, XMLNS_NAMESPACE
5 import tempfile
6 from logging import warn, info, debug
8 known_elements = {
9 'interface' : ['uri', 'min-injector-version', 'main'], # (main is deprecated)
10 'name' : [],
11 'summary' : [],
12 'description' : [],
13 'homepage' : [],
14 'category' : ['type'],
15 'icon' : ['type', 'href'],
16 'feed' : ['src', 'arch'],
17 'feed-for' : ['interface'],
19 'group' : ['version', 'released', 'main', 'stability', 'arch', 'license'],
20 'implementation' : ['id', 'version', 'released', 'main', 'stability', 'arch', 'version-modifier', 'license'],
21 'archive' : ['href', 'size', 'extract', 'type', 'start-offset'],
22 'recipe' : [],
23 'requires' : ['interface'],
24 'version' : ['not-before', 'before'],
25 'environment' : ['name', 'insert', 'default'],
28 def checkElement(elem):
29 if elem.namespaceURI != namespaces.XMLNS_IFACE:
30 info("Note: Skipping unknown (but namespaced) element <%s>", elem.localName)
31 return # Namespaces elements are OK
33 if elem.localName not in known_elements:
34 warn("Unknown Zero Install element <%s>.\nNon Zero-Install elements should be namespaced.", elem.localName)
35 return
37 known_attrs = known_elements[elem.localName]
39 for (uri, name), value in elem.attributes.itemsNS():
40 if uri == XMLNS_NAMESPACE:
41 continue # Namespace declarations are fine
43 if uri:
44 info("Note: Skipping unknown (but namespaced) attribute '%s'", name)
45 continue
47 if name not in known_attrs:
48 warn("Unknown Zero Install attribute '%s' on <%s>.\nNon Zero-Install attributes should be namespaced.",
49 name, elem.localName)
51 for child in elem.childNodes:
52 if child.nodeType == Node.ELEMENT_NODE:
53 checkElement(child)
55 def check(data, warnings = True):
56 fd, tmp_name = tempfile.mkstemp(prefix = '0publish-validate-')
57 os.close(fd)
58 tmp_iface = model.Interface(tmp_name)
59 try:
60 tmp_file = file(tmp_name, 'w')
61 tmp_file.write(data)
62 tmp_file.close()
63 try:
64 update(tmp_iface, tmp_name, local = True)
65 except InvalidInterface, ex:
66 raise
67 except Exception, ex:
68 warn("Internal error", ex)
69 raise InvalidInterface(str(ex))
70 finally:
71 os.unlink(tmp_name)
73 if warnings:
74 doc = minidom.parseString(data)
75 checkElement(doc.documentElement)