def testParser(self): p2 = Parser({"START_TAG": r"\[\*", "END_TAG": r"\*\]", "ANYCASE": 1, "PRE_CHOMP": 1, "V1DOLLAR": 1}) # Test new/old styles. s1 = p2.new_style({"TAG_STYLE": "metatext", "PRE_CHOMP": 0, "POST_CHOMP": 1}) self.assert_(s1) self.assertEquals(r"%%", s1["START_TAG"]) self.assertEquals(0, s1["PRE_CHOMP"]) self.assertEquals(1, s1["POST_CHOMP"]) s2 = p2.old_style() self.assert_(s2) self.assertEquals(r"\[\*", s2["START_TAG"]) self.assertEquals(1, s2["PRE_CHOMP"]) self.assertEquals(0, s2["POST_CHOMP"]) p3 = Config.parser( {"TAG_STYLE": "html", "POST_CHOMP": 1, "ANYCASE": 1, "INTERPOLATE": 1}) p4 = Config.parser({"ANYCASE": 0}) tt = (("tt1", Template({"ANYCASE": 1})), ("tt2", Template({"PARSER": p2})), ("tt3", Template({"PARSER": p3})), ("tt4", Template({"PARSER": p4}))) replace = self._callsign() replace["alist"] = ["foo", 0, "bar", 0] replace["wintxt"] = "foo\r\n\r\nbar\r\n\r\nbaz" self.Expect(DATA, tt, replace)
def testConstants(self): n = [0] def counter(): n[0] += 1 return n[0] - 1 constants = { "author": "Andy 'Da Man' Wardley", "single": "foo'bar", "double": 'foo"bar', "joint": ", ", "col": { "back": "#ffffff", "text": "#000000" }, "counter": counter } namespace = Constants(constants) self.assertEqual('"Andy \'Da Man\' Wardley"', namespace.ident(["constants", 0, "'author'", 0])) self.assertEqual('"foo\'bar"', namespace.ident(["constants", 0, "'single'", 0])) self.assertEqual("'foo\"bar'", namespace.ident(["constants", 0, "'double'", 0])) self.assertEqual( "'#ffffff'", namespace.ident(["constants", 0, "'col'", 0, "'back'", 0])) self.assertEqual( "'#000000'", namespace.ident(["constants", 0, "'col'", 0, "'text'", 0])) factory = Directive({"NAMESPACE": {"const": namespace}}) parser1 = Parser({"FACTORY": factory}) parser2 = Parser({"NAMESPACE": {"const": namespace}}) for parser in parser1, parser2: parsed = parser.parse('hello [% const.author %]\n' '[% "back is $const.col.back" %]' ' and text is {% const.col.text %]\n' 'but a col is still a [% col.user %]\n') text = parsed["BLOCK"] self.assertNotEqual(-1, text.find('"Andy \'Da Man\' Wardley"')) self.assertNotEqual(-1, text.find("'back is ', '#ffffff'")) self.assertNotEqual(-1, text.find("stash.get(['col', 0, 'user', 0])")) tt1 = Template({"NAMESPACE": {"const": namespace}}) const2 = { "author": "abw", "joint": " is the new ", "col": { "back": "orange", "text": "black" }, "fave": "back" } tt2 = Template({"CONSTANTS": const2}) tt3 = Template({"CONSTANTS": const2, "CONSTANTS_NAMESPACE": "const"}) engines = (("tt1", tt1), ("tt2", tt2), ("tt3", tt3)) vars = {"col": {"user": "******", "luza": "blue"}, "constants": constants} self.Expect(DATA, engines, vars)
def extract_tt(fileobj, keywords, comment_tags, options): """Extract messages from TemplateToolkit files. :param fileobj: the file-like object the messages should be extracted from :param keywords: a list of keywords (i.e. function names) that should be recognized as translation functions :param comment_tags: a list of translator tags to search for and include in the results :param options: a dictionary of additional options (optional) :return: an iterator over ``(lineno, funcname, message, comments)`` tuples :rtype ``iterator`` """ # TODO: Extract comments, contexts etc. from template.parser import Parser parser = Parser({}) lines = fileobj.readlines() # We are doing our own parsing, since it makes extracting line numbers easier for (line, string) in extract_tt_strings(lines): parsed = parser.split_text(string) if parsed: parsed = parsed[0][2] message_plural = "" # '-7' because it the minimal list length in which a l() function can appear # '[8:-2]' removes "scalar()" from the string for i in xrange(0, len(parsed) - 7): # Scan for 'IDENT', 'l', '(', '(', 'LITERAL' (l('some text')) if parsed[i] == "IDENT" and parsed[ i + 1] in keywords and parsed[i + 2:i + 5] == ["(", "(", "LITERAL"]: message = parsed[i + 5][8:-2].decode("string_escape") if parsed[i + 6:i + 9] == ['COMMA', ',', 'LITERAL']: message_plural = parsed[i + 9][8:-2] yield (line, parsed[i + 1], (message, message_plural), comment_tags and comments or [])
def extract_tt(fileobj, keywords, comment_tags, options): """Extract messages from TemplateToolkit files. :param fileobj: the file-like object the messages should be extracted from :param keywords: a list of keywords (i.e. function names) that should be recognized as translation functions :param comment_tags: a list of translator tags to search for and include in the results :param options: a dictionary of additional options (optional) :return: an iterator over ``(lineno, funcname, message, comments)`` tuples :rtype ``iterator`` """ # TODO: Extract comments, contexts etc. from template.parser import Parser parser = Parser({}) lines = fileobj.readlines() # We are doing our own parsing, since it makes extracting line numbers easier for (line,string) in extract_tt_strings(lines): parsed = parser.split_text(string) if parsed: parsed = parsed[0][2] message_plural = "" # '-7' because it the minimal list length in which a l() function can appear # '[8:-2]' removes "scalar()" from the string for i in xrange(0, len(parsed)-7): # Scan for 'IDENT', 'l', '(', '(', 'LITERAL' (l('some text')) if parsed[i] == "IDENT" and parsed[i+1] in keywords and parsed[i+2:i+5] == ["(", "(", "LITERAL"]: message = parsed[i+5][8:-2].decode("string_escape") if parsed[i+6:i+9] == ['COMMA', ',', 'LITERAL']: message_plural = parsed[i+9][8:-2] yield (line, parsed[i+1], (message.decode("utf-8"), message_plural.decode("utf-8")), comment_tags and comments or [])
def testParser(self): p2 = Parser({ "START_TAG": r"\[\*", "END_TAG": r"\*\]", "ANYCASE": 1, "PRE_CHOMP": 1, "V1DOLLAR": 1 }) # Test new/old styles. s1 = p2.new_style({ "TAG_STYLE": "metatext", "PRE_CHOMP": 0, "POST_CHOMP": 1 }) self.assert_(s1) self.assertEquals(r"%%", s1["START_TAG"]) self.assertEquals(0, s1["PRE_CHOMP"]) self.assertEquals(1, s1["POST_CHOMP"]) s2 = p2.old_style() self.assert_(s2) self.assertEquals(r"\[\*", s2["START_TAG"]) self.assertEquals(1, s2["PRE_CHOMP"]) self.assertEquals(0, s2["POST_CHOMP"]) p3 = Config.parser({ "TAG_STYLE": "html", "POST_CHOMP": 1, "ANYCASE": 1, "INTERPOLATE": 1 }) p4 = Config.parser({"ANYCASE": 0}) tt = (("tt1", Template({"ANYCASE": 1})), ("tt2", Template({"PARSER": p2})), ("tt3", Template({"PARSER": p3})), ("tt4", Template({"PARSER": p4}))) replace = self._callsign() replace["alist"] = ["foo", 0, "bar", 0] replace["wintxt"] = "foo\r\n\r\nbar\r\n\r\nbaz" self.Expect(DATA, tt, replace)