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