diff --git a/tools/packaging/monkeyYaml.py b/tools/packaging/monkeyYaml.py new file mode 100644 index 0000000000..2adbea7f6b --- /dev/null +++ b/tools/packaging/monkeyYaml.py @@ -0,0 +1,110 @@ +#!/usr/bin/env python +# Copyright 2014 by Sam Mikes. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +# This code provides a fallback parser that can handle the subset of +# YAML used in test262 frontmatter + +import re + +mYamlKV = re.compile(r"(.*?):(.*)") +mYamlIntDigits = re.compile(r"^[-0-9]*$") +mYamlFloatDigits = re.compile(r"^[-.0-9eE]*$") +mYamlListPattern = re.compile(r"^\[(.*)\]$") +mYamlMultilineList = re.compile(r"^ *- (.*)$") + +def load(str): + dict = None + + lines = str.split("\n") + while lines: + line = lines.pop(0) + if myIsAllSpaces(line): + continue + result = mYamlKV.match(line) + if result: + if not dict: + dict = {} + key = result.group(1).strip() + value = result.group(2).strip() + (lines, value) = myReadValue(lines, value) + dict[key] = value + else: + raise Exception("monkeyYaml is confused at " + line) + return dict + +def myReadValue(lines, value): + if value == ">": + (lines, value) = myMultiline(lines, value) + value = value + "\n" + return (lines, value) + if lines and not value and myMaybeList(lines[0]): + return myMultilineList(lines, value) + else: + return lines, myReadOneLine(value) + +def myMaybeList(value): + return mYamlMultilineList.match(value) + +def myMultilineList(lines, value): + # assume no explcit indentor (otherwise have to parse value) + value = [] + indent = None + while lines: + line = lines.pop(0) + leading = myLeadingSpaces(line) + if myIsAllSpaces(line): + pass + elif leading < indent: + lines.insert(0, line) + break; + else: + indent = indent or leading + value += [myReadOneLine(myRemoveListHeader(indent, line))] + return (lines, value) + +def myRemoveListHeader(indent, line): + line = line[indent:] + return mYamlMultilineList.match(line).group(1) + +def myReadOneLine(value): + if mYamlListPattern.match(value): + return myFlowList(value) + elif mYamlIntDigits.match(value): + try: + value = int(value) + except ValueError: + pass + elif mYamlFloatDigits.match(value): + try: + value = float(value) + except ValueError: + pass + return value + +def myFlowList(value): + result = mYamlListPattern.match(value) + values = result.group(1).split(",") + return [myReadOneLine(v.strip()) for v in values] + +def myMultiline(lines, value): + # assume no explcit indentor (otherwise have to parse value) + value = [] + indent = 1 + while lines: + line = lines.pop(0) + if myIsAllSpaces(line): + value += ["\n"] + elif myLeadingSpaces(line) < indent: + lines.insert(0, line) + break; + else: + value += [line[(indent):]] + value = " ".join(value) + return (lines, value) + +def myIsAllSpaces(line): + return len(line.strip()) == 0 + +def myLeadingSpaces(line): + return len(line) - len(line.lstrip(' ')) diff --git a/tools/packaging/parseTestRecord.py b/tools/packaging/parseTestRecord.py index 6671f84628..60590af005 100644 --- a/tools/packaging/parseTestRecord.py +++ b/tools/packaging/parseTestRecord.py @@ -17,8 +17,6 @@ import sys import tempfile import time -import yaml - # from TestCasePackagerConfig import * headerPatternStr = r"(?:(?:\s*\/\/.*)?\s*\n)*" @@ -39,6 +37,8 @@ atattrs = re.compile(r"\s*\n\s*\*\s*@") yamlPattern = re.compile(r"---((?:\s|\S)*)---") newlinePattern = re.compile(r"\n") +yamlLoad = None + def stripStars(text): return stars.sub('\n', text).strip() @@ -76,7 +76,8 @@ def oldAttrParser(testRecord, body, name): def yamlAttrParser(testRecord, attrs, name): match = yamlPattern.match(attrs) body = match.group(1) - parsed = yaml.load(body) + importYamlLoad() + parsed = yamlLoad(body) if (parsed is None): print "Failed to parse yaml in name %s"%(name) @@ -106,3 +107,14 @@ def parseTestRecord(src, name): oldAttrParser(testRecord, attrs, name) return testRecord + +def importYamlLoad(): + global yamlLoad + if yamlLoad: + return + try: + import yaml + yamlLoad = yaml.load + except ImportError: + import monkeyYaml + yamlLoad = monkeyYaml.load diff --git a/tools/packaging/test/test_monkeyYaml.py b/tools/packaging/test/test_monkeyYaml.py new file mode 100644 index 0000000000..edf7b939e9 --- /dev/null +++ b/tools/packaging/test/test_monkeyYaml.py @@ -0,0 +1,85 @@ +#!/usr/bin/env python + +# Copyright 2014 by Sam Mikes. All rights reserved. +# This code is governed by the BSD license found in the LICENSE file. + +import unittest + +import os +import yaml + +# add parent dir to search path +import sys +sys.path.insert(0, "..") + +import monkeyYaml + +class TestMonkeyYAMLParsing(unittest.TestCase): + + def test_empty(self): + self.assertEqual(monkeyYaml.load(""), yaml.load("")) + + def test_newline(self): + self.assertEqual(monkeyYaml.load("\n"), yaml.load("\n")) + + def test_oneline(self): + y = "foo: bar" + self.assertEqual(monkeyYaml.load(y), yaml.load(y)) + + def test_twolines(self): + y = "foo: bar\nbaz_bletch : blith:er" + self.assertEqual(monkeyYaml.load(y), yaml.load(y)) + + def test_multiLine(self): + y = "foo: >\n bar\nbaz: 3" + self.assertEqual(monkeyYaml.load(y), yaml.load(y)) + + def test_es5id(self): + y = "es5id: 15.2.3.6-4-102" + self.assertEqual(monkeyYaml.load(y), yaml.load(y)) + + def test_Multiline_1(self): + lines = [" foo"] + value = ">" + y = "\n".join([value] + lines) + (lines, value) = monkeyYaml.myMultiline(lines, value) + self.assertEqual(lines, []) + self.assertEqual(value, yaml.load(y)) + + def test_Multiline_1(self): + lines = [" foo", " bar"] + value = ">" + y = "\n".join([value] + lines) + (lines, value) = monkeyYaml.myMultiline(lines, value) + self.assertEqual(lines, []) + self.assertEqual(value, yaml.load(y)) + + def test_myLeading(self): + self.assertEqual(2, monkeyYaml.myLeadingSpaces(" foo")) + self.assertEqual(2, monkeyYaml.myLeadingSpaces(" ")) + self.assertEqual(0, monkeyYaml.myLeadingSpaces("\t ")) + + def test_includes_flow(self): + y = "includes: [a.js,b.js, c_with_wings.js]\n" + self.assertEqual(monkeyYaml.load(y), yaml.load(y)) + + def test_myFlowList_1(self): + y = "[a.js,b.js, c_with_wings.js, 3, 4.12]" + self.assertEqual(monkeyYaml.myFlowList(y), ['a.js', 'b.js', 'c_with_wings.js', 3, 4.12]) + + def test_multiline_list_1(self): + y = "foo:\n - bar\n - baz" + self.assertEqual(monkeyYaml.load(y), yaml.load(y)) + + def test_mulineline_list2(self): + self.assertEqual(monkeyYaml.myRemoveListHeader(2, " - foo"), "foo") + + def test_mulineline_list3(self): + (lines, value) = monkeyYaml.myMultilineList([" - foo", " - bar", "baz: bletch"], "") + self.assertEqual(lines, ["baz: bletch"]) + self.assertEqual(value, ["foo", "bar"]) + + + +if __name__ == '__main__': + unittest.main()