diff --git a/libpathod/language.py b/libpathod/language.py index 42fffcf82..e1f6820ff 100644 --- a/libpathod/language.py +++ b/libpathod/language.py @@ -14,6 +14,11 @@ import utils BLOCKSIZE = 1024 TRUNCATE = 1024 + +def escape_backslash(s): + return s.replace("\\", "\\\\") + + def quote(s): quotechar = s[0] s = s[1:-1] @@ -186,7 +191,7 @@ class LiteralGenerator: return self.s.__getslice__(a, b) def __repr__(self): - return '"%s"'%self.s + return "'%s'"%self.s class RandomGenerator: @@ -274,10 +279,16 @@ class ValueLiteral(_ValueLiteral): @classmethod def expr(klass): e = v_literal.copy() - return e.setParseAction(lambda x: klass(*x)) + return e.setParseAction(klass.parseAction) + + @classmethod + def parseAction(klass, x): + v = klass(*x) + return v def spec(self): - return quote("'%s'"%self.val.encode("string_escape")) + ret = "'%s'"%self.val.encode("string_escape") + return ret class ValueNakedLiteral(_ValueLiteral): @@ -361,7 +372,7 @@ class ValueFile(_Token): return FileGenerator(s) def spec(self): - return '<"%s"'%self.path.encode("string_escape") + return "<'%s'"%self.path.encode("string_escape") Value = pp.MatchFirst( @@ -561,8 +572,7 @@ class PathodSpec(_Token): def freeze(self, settings): f = self.parsed.freeze(settings).spec() - print [f] - return PathodSpec(ValueLiteral(f)) + return PathodSpec(ValueLiteral(f.encode("string_escape"))) class Path(_Component): diff --git a/test/test_language.py b/test/test_language.py index d8392404d..e2d5190f1 100644 --- a/test/test_language.py +++ b/test/test_language.py @@ -6,6 +6,10 @@ import tutils language.TESTING = True +def test_quote(): + assert language.quote("'\\\\'") + + def parse_request(s): return language.parse_requests(s)[0] @@ -29,7 +33,7 @@ class TestValueLiteral: assert v.expr() assert v.val == "foo" - v = language.ValueLiteral(r"foo\n") + v = language.ValueLiteral("foo\n") assert v.expr() assert v.val == "foo\n" assert repr(v) @@ -44,9 +48,20 @@ class TestValueLiteral: v = language.ValueLiteral("\"") assert v.spec() == repr(v) == '\'"\'' - def test_freeze(self): - v = language.ValueLiteral("foo") - assert v.freeze({}).val == v.val + def roundtrip(self, spec): + e = language.ValueLiteral.expr() + v = language.ValueLiteral(spec) + v2 = e.parseString(v.spec()) + assert v.val == v2[0].val + assert v.spec() == v2[0].spec() + + def test_roundtrip(self): + self.roundtrip("'") + self.roundtrip('\'') + self.roundtrip("a") + self.roundtrip("\"") + self.roundtrip(r"\\") + self.roundtrip("200:b'foo':i23,'\\''") class TestValueGenerate: @@ -242,13 +257,14 @@ class TestMisc: assert "@1" not in f.spec() def test_pathodspec_freeze(self): - spec = r'GET:"/foo":s"200:ir,\'\"\'"' - r = parse_request(spec) - assert r.freeze({}) - - spec = r'GET:"/foo":s"200:ir,\"\'\""' - r = parse_request(spec) - assert r.freeze({}) + e = language.PathodSpec( + language.ValueLiteral( + "200:b'foo':i10,'\\''".encode( + "string_escape" + ) + ) + ) + assert e.freeze({}) def test_code(self): e = language.Code.expr()