annotate upmana/xmltramp.py @ 39:ed322725b928 ornery-orc tip

Traipse 'OpenRPG' {110114-00} Traipse is a distribution of OpenRPG that is designed to be easy to setup and go. Traipse also makes it easy for developers to work on code without fear of sacrifice. 'Ornery-Orc' continues the trend of 'Grumpy' and adds fixes to the code. 'Ornery-Orc's main goal is to offer more advanced features and enhance the productivity of the user. Update Summary (Closed) New Features: New to Map, can re-order Grid, Miniatures, and Whiteboard layer draw order New to Server GUI, can now clear log New Earthdawn Dieroller New IronClaw roller, sheet, and image New ShapeShifter PC Sheet Updates: Update to Warhammer PC Sheet. Rollers set as macros. Should work with little maintanence. Update to Browser Server window. Display rooms with ' " & cleaner Update to Server. Handles ' " & cleaner Update to Dieroller. Cleaner, more effecient expression system Update to Hidden Die plugin, allows for non standard dice rolls Update to location.py, allows for more portable references when starting Traipse Update to the Features node Fixes: Fix to InterParse that was causing an Infernal Loop with Namespace Internal Fix to XML data, removed old Minidom and switched to Element Tree Fix to Server that was causing eternal attempt to find a Server ID, in Register Rooms thread Fix to Server, removing wxPython dependencies where not needed Fix to metaservers.xml file not being created Fix to Single and Double quotes in Whiteboard text Fix to Background images not showing when using the Image Server Fix to Duplicate chat names appearing Fix to Server GUI's logging output Fix to FNB.COLORFUL_TABS bug Fix to Gametree for XSLT Sheets Fix to Gametree for locating gametree files Fix to Send to Chat from Gametree Fix to Gametree, renaming and remapping operates correctly Fix to aliaslib, prevents error caused when SafeHTML is sent None
author sirebral
date Fri, 14 Jan 2011 05:24:52 -0600
parents e8260c6cb309
children
rev   line source
14
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
1 """xmltramp: Make XML documents easily accessible."""
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
2
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
3 __version__ = "2.16"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
4 __author__ = "Aaron Swartz"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
5 __credits__ = "Many thanks to pjz, bitsko, and DanC."
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
6 __copyright__ = "(C) 2003 Aaron Swartz. GNU GPL 2."
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
7
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
8 if not hasattr(__builtins__, 'True'): True, False = 1, 0
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
9 def isstr(f): return isinstance(f, type('')) or isinstance(f, type(u''))
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
10 def islst(f): return isinstance(f, type(())) or isinstance(f, type([]))
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
11
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
12 empty = {'http://www.w3.org/1999/xhtml': ['img', 'br', 'hr', 'meta', 'link', 'base', 'param', 'input', 'col', 'area']}
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
13
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
14 def quote(x, elt=True):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
15 if elt and '<' in x and len(x) > 24 and x.find(']]>') == -1: return "<![CDATA["+x+"]]>"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
16 else: x = x.replace('&', '&amp;').replace('<', '&lt;').replace(']]>', ']]&gt;')
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
17 if not elt: x = x.replace('"', '&quot;')
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
18 return x
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
19
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
20 class Element:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
21 def __init__(self, name, attrs=None, children=None, prefixes=None):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
22 if islst(name) and name[0] == None: name = name[1]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
23 if attrs:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
24 na = {}
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
25 for k in attrs.keys():
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
26 if islst(k) and k[0] == None: na[k[1]] = attrs[k]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
27 else: na[k] = attrs[k]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
28 attrs = na
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
29 self._name = name
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
30 self._attrs = attrs or {}
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
31 self._dir = children or []
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
32 prefixes = prefixes or {}
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
33 self._prefixes = dict(zip(prefixes.values(), prefixes.keys()))
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
34 if prefixes: self._dNS = prefixes.get(None, None)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
35 else: self._dNS = None
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
36
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
37 def __repr__(self, recursive=0, multiline=0, inprefixes=None):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
38 def qname(name, inprefixes):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
39 if islst(name):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
40 if inprefixes[name[0]] is not None: return inprefixes[name[0]]+':'+name[1]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
41 else: return name[1]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
42 else: return name
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
43
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
44 def arep(a, inprefixes, addns=1):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
45 out = ''
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
46 for p in self._prefixes.keys():
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
47 if not p in inprefixes.keys():
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
48 if addns: out += ' xmlns'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
49 if addns and self._prefixes[p]: out += ':'+self._prefixes[p]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
50 if addns: out += '="'+quote(p, False)+'"'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
51 inprefixes[p] = self._prefixes[p]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
52 for k in a.keys():
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
53 out += ' ' + qname(k, inprefixes)+ '="' + quote(a[k], False) + '"'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
54 return out
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
55 inprefixes = inprefixes or {u'http://www.w3.org/XML/1998/namespace':'xml'}
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
56
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
57 # need to call first to set inprefixes:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
58 attributes = arep(self._attrs, inprefixes, recursive)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
59 out = '<' + qname(self._name, inprefixes) + attributes
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
60 if not self._dir and (self._name[0] in empty.keys()
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
61 and self._name[1] in empty[self._name[0]]):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
62 out += ' />'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
63 return out
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
64 out += '>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
65 if recursive:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
66 content = 0
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
67 for x in self._dir:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
68 if isinstance(x, Element): content = 1
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
69 pad = '\n' + ('\t' * recursive)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
70 for x in self._dir:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
71 if multiline and content: out += pad
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
72 if isstr(x): out += quote(x)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
73 elif isinstance(x, Element): out += x.__repr__(recursive+1, multiline, inprefixes.copy())
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
74 else: raise TypeError, "I wasn't expecting "+`x`+"."
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
75 if multiline and content: out += '\n' + ('\t' * (recursive-1))
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
76 else:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
77 if self._dir: out += '...'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
78 out += '</'+qname(self._name, inprefixes)+'>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
79 return out
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
80
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
81 def __unicode__(self):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
82 text = ''
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
83 for x in self._dir: text += unicode(x)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
84 return ' '.join(text.split())
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
85
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
86 def __str__(self):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
87 return self.__unicode__().encode('utf-8')
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
88
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
89 def __getattr__(self, n):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
90 if n[0] == '_': raise AttributeError, "Use foo['"+n+"'] to access the child element."
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
91 if self._dNS: n = (self._dNS, n)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
92 for x in self._dir:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
93 if isinstance(x, Element) and x._name == n: return x
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
94 raise AttributeError, 'No child element named \''+n+"'"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
95
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
96 def __hasattr__(self, n):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
97 for x in self._dir:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
98 if isinstance(x, Element) and x._name == n: return True
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
99 return False
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
100
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
101 def __setattr__(self, n, v):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
102 if n[0] == '_': self.__dict__[n] = v
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
103 else: self[n] = v
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
104
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
105 def __getitem__(self, n):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
106 if isinstance(n, type(0)): # d[1] == d._dir[1]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
107 return self._dir[n]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
108 elif isinstance(n, slice(0).__class__):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
109 # numerical slices
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
110 if isinstance(n.start, type(0)): return self._dir[n.start:n.stop]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
111 # d['foo':] == all <foo>s
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
112 n = n.start
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
113 if self._dNS and not islst(n): n = (self._dNS, n)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
114 out = []
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
115 for x in self._dir:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
116 if isinstance(x, Element) and x._name == n: out.append(x)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
117 return out
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
118 else: # d['foo'] == first <foo>
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
119 if self._dNS and not islst(n): n = (self._dNS, n)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
120 for x in self._dir:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
121 if isinstance(x, Element) and x._name == n: return x
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
122 raise KeyError
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
123
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
124 def __setitem__(self, n, v):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
125 if isinstance(n, type(0)): # d[1]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
126 self._dir[n] = v
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
127 elif isinstance(n, slice(0).__class__):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
128 # d['foo':] adds a new foo
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
129 n = n.start
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
130 if self._dNS and not islst(n): n = (self._dNS, n)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
131 nv = Element(n)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
132 self._dir.append(nv)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
133
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
134 else: # d["foo"] replaces first <foo> and dels rest
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
135 if self._dNS and not islst(n): n = (self._dNS, n)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
136 nv = Element(n); nv._dir.append(v)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
137 replaced = False
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
138 todel = []
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
139 for i in range(len(self)):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
140 if self[i]._name == n:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
141 if replaced:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
142 todel.append(i)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
143 else:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
144 self[i] = nv
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
145 replaced = True
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
146 if not replaced: self._dir.append(nv)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
147 for i in todel: del self[i]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
148
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
149 def __delitem__(self, n):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
150 if isinstance(n, type(0)): del self._dir[n]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
151 elif isinstance(n, slice(0).__class__):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
152 # delete all <foo>s
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
153 n = n.start
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
154 if self._dNS and not islst(n): n = (self._dNS, n)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
155 for i in range(len(self)):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
156 if self[i]._name == n: del self[i]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
157 else:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
158 # delete first foo
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
159 for i in range(len(self)):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
160 if self[i]._name == n: del self[i]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
161 break
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
162
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
163 def __call__(self, *_pos, **_set):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
164 if _set:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
165 for k in _set.keys(): self._attrs[k] = _set[k]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
166 if len(_pos) > 1:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
167 for i in range(0, len(_pos), 2): self._attrs[_pos[i]] = _pos[i+1]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
168 if len(_pos) == 1 is not None: return self._attrs[_pos[0]]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
169 if len(_pos) == 0: return self._attrs
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
170
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
171 def __len__(self): return len(self._dir)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
172
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
173 class Namespace:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
174 def __init__(self, uri): self.__uri = uri
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
175 def __getattr__(self, n): return (self.__uri, n)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
176 def __getitem__(self, n): return (self.__uri, n)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
177
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
178 from xml.sax.handler import EntityResolver, DTDHandler, ContentHandler, ErrorHandler
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
179
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
180 class Seeder(EntityResolver, DTDHandler, ContentHandler, ErrorHandler):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
181 def __init__(self):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
182 self.stack = []
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
183 self.ch = ''
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
184 self.prefixes = {}
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
185 ContentHandler.__init__(self)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
186
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
187 def startPrefixMapping(self, prefix, uri):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
188 if not self.prefixes.has_key(prefix): self.prefixes[prefix] = []
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
189 self.prefixes[prefix].append(uri)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
190 def endPrefixMapping(self, prefix):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
191 self.prefixes[prefix].pop()
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
192
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
193 def startElementNS(self, name, qname, attrs):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
194 ch = self.ch; self.ch = ''
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
195 if ch and not ch.isspace(): self.stack[-1]._dir.append(ch)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
196 attrs = dict(attrs)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
197 newprefixes = {}
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
198 for k in self.prefixes.keys(): newprefixes[k] = self.prefixes[k][-1]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
199 self.stack.append(Element(name, attrs, prefixes=newprefixes.copy()))
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
200
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
201 def characters(self, ch):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
202 self.ch += ch
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
203
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
204 def endElementNS(self, name, qname):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
205 ch = self.ch; self.ch = ''
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
206 if ch and not ch.isspace(): self.stack[-1]._dir.append(ch)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
207 element = self.stack.pop()
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
208 if self.stack: self.stack[-1]._dir.append(element)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
209 else: self.result = element
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
210
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
211 from xml.sax import make_parser
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
212 from xml.sax.handler import feature_namespaces
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
213
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
214 def seed(fileobj):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
215 seeder = Seeder()
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
216 parser = make_parser()
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
217 parser.setFeature(feature_namespaces, 1)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
218 parser.setContentHandler(seeder)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
219 parser.parse(fileobj)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
220 return seeder.result
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
221
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
222 def parse(text):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
223 from StringIO import StringIO
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
224 return seed(StringIO(text))
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
225
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
226 def load(url):
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
227 import urllib
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
228 return seed(urllib.urlopen(url))
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
229
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
230 def unittest():
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
231 parse('<doc>a<baz>f<b>o</b>ob<b>a</b>r</baz>a</doc>').__repr__(1,1) == \
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
232 '<doc>\n\ta<baz>\n\t\tf<b>o</b>ob<b>a</b>r\n\t</baz>a\n</doc>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
233 assert str(parse("<doc />")) == ""
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
234 assert str(parse("<doc>I <b>love</b> you.</doc>")) == "I love you."
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
235 assert parse("<doc>\nmom\nwow\n</doc>")[0].strip() == "mom\nwow"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
236 assert str(parse('<bing> <bang> <bong>center</bong> </bang> </bing>')) == "center"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
237 assert str(parse('<doc>\xcf\x80</doc>')) == '\xcf\x80'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
238 d = Element('foo', attrs={'foo':'bar'}, children=['hit with a', Element('bar'), Element('bar')])
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
239
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
240 try:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
241 d._doesnotexist
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
242 raise "ExpectedError", "but found success. Damn."
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
243 except AttributeError: pass
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
244 assert d.bar._name == 'bar'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
245 try:
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
246 d.doesnotexist
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
247 raise "ExpectedError", "but found success. Damn."
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
248 except AttributeError: pass
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
249 assert hasattr(d, 'bar') == True
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
250 assert d('foo') == 'bar'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
251 d(silly='yes')
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
252 assert d('silly') == 'yes'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
253 assert d() == d._attrs
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
254 assert d[0] == 'hit with a'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
255 d[0] = 'ice cream'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
256 assert d[0] == 'ice cream'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
257 del d[0]
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
258 assert d[0]._name == "bar"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
259 assert len(d[:]) == len(d._dir)
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
260 assert len(d[1:]) == len(d._dir) - 1
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
261 assert len(d['bar':]) == 2
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
262 d['bar':] = 'baz'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
263 assert len(d['bar':]) == 3
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
264 assert d['bar']._name == 'bar'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
265 d = Element('foo')
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
266 doc = Namespace("http://example.org/bar")
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
267 bbc = Namespace("http://example.org/bbc")
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
268 dc = Namespace("http://purl.org/dc/elements/1.1/")
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
269 d = parse("""<doc version="2.7182818284590451"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
270 xmlns="http://example.org/bar"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
271 xmlns:dc="http://purl.org/dc/elements/1.1/"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
272 xmlns:bbc="http://example.org/bbc">
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
273 <author>John Polk and John Palfrey</author>
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
274 <dc:creator>John Polk</dc:creator>
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
275 <dc:creator>John Palfrey</dc:creator>
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
276 <bbc:show bbc:station="4">Buffy</bbc:show>
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
277 </doc>""")
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
278 assert repr(d) == '<doc version="2.7182818284590451">...</doc>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
279 assert d.__repr__(1) == '<doc xmlns:bbc="http://example.org/bbc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://example.org/bar" version="2.7182818284590451"><author>John Polk and John Palfrey</author><dc:creator>John Polk</dc:creator><dc:creator>John Palfrey</dc:creator><bbc:show bbc:station="4">Buffy</bbc:show></doc>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
280 assert d.__repr__(1,1) == '<doc xmlns:bbc="http://example.org/bbc" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns="http://example.org/bar" version="2.7182818284590451">\n\t<author>John Polk and John Palfrey</author>\n\t<dc:creator>John Polk</dc:creator>\n\t<dc:creator>John Palfrey</dc:creator>\n\t<bbc:show bbc:station="4">Buffy</bbc:show>\n</doc>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
281 assert repr(parse("<doc xml:lang='en' />")) == '<doc xml:lang="en"></doc>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
282 assert str(d.author) == str(d['author']) == "John Polk and John Palfrey"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
283 assert d.author._name == doc.author
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
284 assert str(d[dc.creator]) == "John Polk"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
285 assert d[dc.creator]._name == dc.creator
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
286 assert str(d[dc.creator:][1]) == "John Palfrey"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
287 d[dc.creator] = "Me!!!"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
288 assert str(d[dc.creator]) == "Me!!!"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
289 assert len(d[dc.creator:]) == 1
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
290 d[dc.creator:] = "You!!!"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
291 assert len(d[dc.creator:]) == 2
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
292 assert d[bbc.show](bbc.station) == "4"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
293 d[bbc.show](bbc.station, "5")
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
294 assert d[bbc.show](bbc.station) == "5"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
295 e = Element('e')
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
296 e.c = '<img src="foo">'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
297 assert e.__repr__(1) == '<e><c>&lt;img src="foo"></c></e>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
298 e.c = '2 > 4'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
299 assert e.__repr__(1) == '<e><c>2 > 4</c></e>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
300 e.c = 'CDATA sections are <em>closed</em> with ]]>.'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
301 assert e.__repr__(1) == '<e><c>CDATA sections are &lt;em>closed&lt;/em> with ]]&gt;.</c></e>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
302 e.c = parse('<div xmlns="http://www.w3.org/1999/xhtml">i<br /><span></span>love<br />you</div>')
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
303 assert e.__repr__(1) == '<e><c><div xmlns="http://www.w3.org/1999/xhtml">i<br /><span></span>love<br />you</div></c></e>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
304 e = Element('e')
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
305 e('c', 'that "sucks"')
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
306 assert e.__repr__(1) == '<e c="that &quot;sucks&quot;"></e>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
307 assert quote("]]>") == "]]&gt;"
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
308 assert quote('< dkdkdsd dkd sksdksdfsd fsdfdsf]]> kfdfkg >') == '&lt; dkdkdsd dkd sksdksdfsd fsdfdsf]]&gt; kfdfkg >'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
309 assert parse('<x a="&lt;"></x>').__repr__(1) == '<x a="&lt;"></x>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
310 assert parse('<a xmlns="http://a"><b xmlns="http://b"/></a>').__repr__(1) == '<a xmlns="http://a"><b xmlns="http://b"></b></a>'
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
311
e8260c6cb309 Traipse 'OpenRPG' {090806-00}
sirebral
parents:
diff changeset
312 if __name__ == '__main__': unittest()