1 #!/usr/bin/env python 2 3 from os import listdir 4 from os.path import abspath, split 5 import sys 6 7 # Locate and import the moinformat package. 8 9 dirname = split(abspath(sys.argv[0]))[0] 10 parent = split(dirname)[0] 11 12 try: 13 import moinformat 14 except ImportError: 15 if "moinformat" in listdir(parent): 16 sys.path.append(parent) 17 18 # Import specific objects. 19 20 from moinformat import Metadata, make_input, make_output, make_parser, \ 21 make_serialiser, parse, serialise 22 from moinformat.tree.moin import Container 23 24 def test_input(d, s): 25 26 "Compare serialised output from 'd' with its original form 's'." 27 28 metadata = Metadata() 29 30 output = make_output(metadata) 31 expected = output.encode(s) 32 33 result = serialise(d, make_serialiser(metadata)) 34 identical = result == expected 35 36 if quiet: 37 return identical 38 39 # Show output versus input comparison result. 40 41 print identical 42 print "-" * 60 43 print result 44 if not identical: 45 print "-" * 60 46 print expected 47 print "-" * 60 48 49 # Show HTML serialisation. 50 51 metadata.set("output_format", "html") 52 53 print serialise(d, make_serialiser(metadata)) 54 print "-" * 60 55 print 56 57 return identical 58 59 def test_tree(d, t, ts): 60 61 "Compare tree structure 'd' with simplified, expected form 't' from 'ts'." 62 63 failing = t.test(d) 64 65 if quiet: 66 return not failing 67 68 # Show tree versus expected forms. 69 70 print not failing 71 print "-" * 60 72 print d.prettyprint() 73 if failing: 74 print "-" * 60 75 print ts 76 simple, tree, error = failing 77 print "-" * 60 78 print error 79 print repr(simple) 80 print repr(tree) 81 print "-" * 60 82 print tree.prettyprint() 83 print "-" * 60 84 print simple.prettyprint() 85 print "-" * 60 86 print 87 88 return not failing 89 90 class Node: 91 92 "A simplified tree node representation." 93 94 def __init__(self, name): 95 self.name = name 96 self.nodes = [] 97 98 def __repr__(self): 99 return "Node(%r, %r)" % (self.name, self.nodes) 100 101 def prettyprint(self, indent=""): 102 l = [] 103 l.append("%s%s%s" % (indent, self.name, len(self.nodes) and " nodes=%d" % len(self.nodes) or "")) 104 for node in self.nodes: 105 l.append(node.prettyprint(indent + " ")) 106 return "\n".join(l) 107 108 def append(self, node): 109 self.nodes.append(node) 110 111 def test(self, other): 112 113 """ 114 Test whether this node is considered equivalent to 'other', where 115 'other' is a moinparser.tree node. 116 117 Return any failing tree nodes or None. 118 """ 119 120 if other.__class__.__name__ != self.name: 121 return self, other, "name" 122 123 if isinstance(other, Container): 124 for node, other_node in map(None, self.nodes, other.nodes): 125 if node is None or other_node is None: 126 return self, other, node is None and "simple" or "document" 127 t = node.test(other_node) 128 if t: 129 return t 130 elif self.nodes: 131 return self, other, "empty" 132 133 return None 134 135 def parse_tree(s): 136 137 "Parse the tree structure representation in 's'." 138 139 indent = 0 140 branches = [] 141 142 for line in s.split("\n"): 143 line = line.rstrip() 144 if not line: 145 continue 146 147 new_indent = line.rfind(" ") + 1 148 node = Node(line[new_indent:]) 149 150 # Establish a branch to add nodes to. 151 152 if not branches: 153 branches.append(node) 154 else: 155 # Note the current node as outermost branch. 156 157 if new_indent > indent: 158 branches.append(node) 159 else: 160 # Reduced indent involves obtaining an inner branch again. 161 162 while indent > new_indent: 163 del branches[-1] 164 indent -= 2 165 166 # Note the current node as outermost branch. 167 168 branches[-1] = node 169 170 # Append the current node to the parent branch. 171 172 branches[-2].append(node) 173 174 indent = new_indent 175 176 return branches[0] 177 178 def get_filename(filename): 179 180 "Using 'filename', return the core text filename and any encoding." 181 182 t = filename.split(".") 183 if len(t) > 2: 184 text_filename = ".".join(t[:2]) 185 encoding = t[2] 186 else: 187 text_filename = filename 188 encoding = None 189 190 return text_filename, encoding 191 192 def get_tree(input, tree_filename): 193 194 "Using 'input', return (text, tree) for 'tree_filename'." 195 196 if input.dir.exists(tree_filename): 197 ts = input.readfile(tree_filename) 198 return ts, parse_tree(ts) 199 else: 200 return None, None 201 202 if __name__ == "__main__": 203 args = sys.argv[1:] 204 205 quiet = "-q" in args 206 if quiet: 207 del args[args.index("-q")] 208 209 metadata = Metadata({ 210 "input_context" : "directory", 211 "input_filename" : dirname, 212 }) 213 214 # Make an input context. 215 216 input = make_input(metadata) 217 218 # Obtain input filenames. 219 220 filenames = args or input.dir.select_files("test*.txt*") 221 filenames.sort() 222 223 # Process each filename, obtaining a corresponding tree definition. 224 225 for filename in filenames: 226 text_filename, encoding = get_filename(filename) 227 228 # Identify any tree-related filenames. 229 230 basename = text_filename.rsplit(".", 1)[0] 231 tree_filename = "%s.tree" % basename 232 tree_exp_filename = "%s.tree-exp" % basename 233 234 # Read and parse the input. 235 236 s = input.readfile(text_filename, encoding) 237 p = make_parser(metadata) 238 d = parse(s, p) 239 240 # Read and parse any tree definitions. 241 242 ts, t = get_tree(input, tree_filename) 243 tsexp, texp = get_tree(input, tree_exp_filename) 244 245 # Report the test results. 246 247 if not quiet: 248 print filename 249 250 identical = test_input(d, s) 251 tree_identical = ts and test_tree(d, t, ts) 252 253 if tsexp: 254 p.evaluate_macros() 255 tree_exp_identical = test_tree(d, texp, tsexp) 256 else: 257 tree_exp_identical = None 258 259 if quiet: 260 print "%s %s %s: %s" % (identical, tree_identical, tree_exp_identical, filename) 261 262 # vim: tabstop=4 expandtab shiftwidth=4