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