If the signature on the input is bad, but the user chooses to load it anyway, always...
[0publish.git] / create.py
blobd7e28e3eb8125bea8247175e54c2c89f780b0b0f
1 import os
2 from xml.dom import minidom, XMLNS_NAMESPACE, Node
3 from zeroinstall.injector.namespaces import XMLNS_IFACE
4 from zeroinstall.injector import model, reader
6 _local_template_start = """<?xml version="1.0" ?>
7 <?xml-stylesheet type='text/xsl'
8 href='http://0install.net/2006/stylesheets/interface.xsl'?>
9 """
11 _template = """<?xml version="1.0" ?>
12 <?xml-stylesheet type='text/xsl'
13 href='http://0install.net/2006/stylesheets/interface.xsl'?>
15 <interface xmlns="http://zero-install.sourceforge.net/2004/injector/interface">
16 <name>%s</name>
17 <summary>cures all ills</summary>
18 <description>
19 A longer, multi-line description of the behaviour of the
20 program goes here. State clearly what the program is for
21 (clearly enough that people who don't want it will
22 realise too).
24 Use a blank line to separate paragraphs.
25 </description>
27 <!-- Optionally, uncomment this to specify the program's homepage: -->
28 <!-- <homepage>http://site/prog</homepage> -->
30 <!-- Optionally, uncomment this to specify an icon: -->
31 <!-- <icon href='http://site/icon.png' type='image/png'/> -->
33 <!-- Optionally, uncomment this to give the address of
34 the signed master interface: -->
35 <!-- <feed-for interface='http://site/interface'/> -->
37 <!-- Set 'main' to the relative path of your default
38 executable within the implementation's directory.
39 E.g.: "myprog" or "bin/myprog" -->
40 <group main='myprog'>
41 <!-- List any libraries your program needs here -->
42 <!--
43 <requires interface="http://site/library">
44 <environment insert="python" name="PYTHONPATH"/>
45 </requires>
46 -->
48 <!-- List all implementations here.
49 For local interfaces, '.' is a relative path from this
50 interface file to the directory containing the program.
51 Usually, you can just leave it as '.'.
52 -->
53 <implementation id="." version="0.1" released='Snapshot'/>
54 </group>
55 </interface>
56 """
58 def create(f):
59 assert not os.path.exists(f)
60 name = os.path.basename(f)
61 return _template % (name.split('.', 1)[0])
63 def remove_with_preceding_comments(element):
64 root = element.ownerDocument.documentElement
65 to_remove = [element]
66 node = element
67 while node.previousSibling:
68 node = node.previousSibling
69 if node.nodeType == Node.COMMENT_NODE or \
70 (node.nodeType == Node.TEXT_NODE and node.nodeValue.strip() == ''):
71 to_remove.append(node)
72 else:
73 break
74 for x in to_remove:
75 root.removeChild(x)
77 def create_from_local(local):
78 iface = model.Interface(os.path.abspath(local))
79 reader.update(iface, local, local = True)
80 if not iface.feed_for:
81 raise Exception("No <feed-for> in '%s'; can't use it as a local feed." % local)
82 if len(iface.feed_for) != 1:
83 raise Exception("Multiple <feed-for> elements. Not supported, sorry!")
84 uri = iface.feed_for.keys()[0]
86 doc = minidom.parse(local)
87 root = doc.documentElement
88 root.setAttribute('uri', uri)
90 for element in root.getElementsByTagNameNS(XMLNS_IFACE, 'feed-for'):
91 if element.parentNode is root:
92 remove_with_preceding_comments(element)
94 root.appendChild(doc.createTextNode('\n'))
96 # minidom's writer loses the newline after the PI
97 return _local_template_start + root.toxml()