language: create and use Integer and PreValue generics

This commit is contained in:
Aldo Cortesi 2015-05-02 21:42:09 +12:00
parent 0ffd14372a
commit fffee660e5
4 changed files with 65 additions and 79 deletions

View File

@ -11,6 +11,9 @@ from . import generators, exceptions
TRUNCATE = 1024
Sep = pp.Optional(pp.Literal(":")).suppress()
v_integer = pp.Word(pp.nums)\
.setName("integer")\
.setParseAction(lambda toks: int(toks[0]))
@ -318,28 +321,6 @@ class ShortcutUserAgent(_Header):
return ShortcutUserAgent(self.value.freeze(settings))
class Body(_Component):
def __init__(self, value):
self.value = value
@classmethod
def expr(klass):
e = pp.Literal("b").suppress()
e = e + Value
return e.setParseAction(lambda x: klass(*x))
def values(self, settings):
return [
self.value.get_generator(settings),
]
def spec(self):
return "b%s"%(self.value.spec())
def freeze(self, settings):
return Body(self.value.freeze(settings))
class PathodSpec(_Token):
def __init__(self, value):
self.value = value
@ -457,9 +438,9 @@ class OptionsOrValue(_Component):
return self.__class__(self.value.freeze(settings))
class Code(_Component):
def __init__(self, code):
self.code = str(code)
class Integer(_Component):
def __init__(self, value):
self.value = str(value)
@classmethod
def expr(klass):
@ -467,22 +448,25 @@ class Code(_Component):
return e.setParseAction(lambda x: klass(*x))
def values(self, settings):
return [generators.LiteralGenerator(self.code)]
return [generators.LiteralGenerator(self.value)]
def spec(self):
return "%s"%(self.code)
return "%s"%(self.value)
def freeze(self, settings):
return self
class Reason(_Component):
class PreValue(_Component):
"""
A value lead by self.preamble.
"""
def __init__(self, value):
self.value = value
@classmethod
def expr(klass):
e = pp.Literal("m").suppress()
e = pp.Literal(klass.preamble).suppress()
e = e + Value
return e.setParseAction(lambda x: klass(*x))
@ -490,10 +474,10 @@ class Reason(_Component):
return [self.value.get_generator(settings)]
def spec(self):
return "m%s"%(self.value.spec())
return "%s%s"%(self.preamble, self.value.spec())
def freeze(self, settings):
return Reason(self.value.freeze(settings))
return self.__class__(self.value.freeze(settings))
class _Action(_Token):
@ -633,10 +617,6 @@ class _Message(object):
def actions(self):
return self.toks(_Action)
@property
def body(self):
return self.tok(Body)
@property
def headers(self):
return self.toks(_Header)
@ -695,6 +675,3 @@ class _Message(object):
def __repr__(self):
return self.spec()
Sep = pp.Optional(pp.Literal(":")).suppress()

View File

@ -20,6 +20,18 @@ class Path(base.SimpleValue):
pass
class Code(base.Integer):
pass
class Reason(base.PreValue):
preamble = "m"
class Body(base.PreValue):
preamble = "b"
class Method(base.OptionsOrValue):
options = [
"get",
@ -47,10 +59,14 @@ def get_header(val, headers):
class _HTTPMessage(base._Message):
version = "HTTP/1.1"
@property
def raw(self):
return bool(self.tok(Raw))
@property
def body(self):
return self.tok(Body)
@abc.abstractmethod
def preamble(self, settings): # pragma: no cover
@ -69,7 +85,7 @@ class _HTTPMessage(base._Message):
class Response(_HTTPMessage):
comps = (
base.Body,
Body,
base.Header,
base.PauseAt,
base.DisconnectAt,
@ -77,7 +93,7 @@ class Response(_HTTPMessage):
base.ShortcutContentType,
base.ShortcutLocation,
Raw,
base.Reason
Reason
)
logattrs = ["code", "reason", "version", "body"]
@ -87,16 +103,16 @@ class Response(_HTTPMessage):
@property
def code(self):
return self.tok(base.Code)
return self.tok(Code)
@property
def reason(self):
return self.tok(base.Reason)
return self.tok(Reason)
def preamble(self, settings):
l = [self.version, " "]
l.extend(self.code.values(settings))
code = int(self.code.code)
code = int(self.code.value)
l.append(" ")
if self.reason:
l.extend(self.reason.values(settings))
@ -121,7 +137,7 @@ class Response(_HTTPMessage):
if not self.code:
tokens.insert(
1,
base.Code(101)
Code(101)
)
hdrs = netlib.websockets.server_handshake_headers(
settings.websocket_key
@ -159,9 +175,9 @@ class Response(_HTTPMessage):
pp.MatchFirst(
[
WS.expr() + pp.Optional(
base.Sep + base.Code.expr()
base.Sep + Code.expr()
),
base.Code.expr(),
Code.expr(),
]
),
pp.ZeroOrMore(base.Sep + atom)
@ -176,7 +192,7 @@ class Response(_HTTPMessage):
class Request(_HTTPMessage):
comps = (
base.Body,
Body,
base.Header,
base.PauseAt,
base.DisconnectAt,
@ -285,12 +301,12 @@ class PathodErrorResponse(Response):
def make_error_response(reason, body=None):
tokens = [
base.Code("800"),
Code("800"),
base.Header(
base.ValueLiteral("Content-Type"),
base.ValueLiteral("text/plain")
),
base.Reason(base.ValueLiteral(reason)),
base.Body(base.ValueLiteral("pathod error: " + (body or reason))),
Reason(base.ValueLiteral(reason)),
Body(base.ValueLiteral("pathod error: " + (body or reason))),
]
return PathodErrorResponse(tokens)

View File

@ -17,15 +17,23 @@ class WF(base.CaselessLiteral):
TOK = "wf"
class Body(base.PreValue):
preamble = "b"
class WebsocketFrame(base._Message):
comps = (
base.Body,
Body,
base.PauseAt,
base.DisconnectAt,
base.InjectAt
)
logattrs = ["body"]
@property
def body(self):
return self.tok(Body)
@classmethod
def expr(klass):
parts = [i.expr() for i in klass.comps]

View File

@ -183,24 +183,6 @@ class TestMisc:
s = v.spec()
assert s == v.expr().parseString(s)[0].spec()
def test_body(self):
e = base.Body.expr()
v = e.parseString("b'foo'")[0]
assert v.value.val == "foo"
v = e.parseString("b@100")[0]
assert str(v.value) == "@100"
v2 = v.freeze({})
v3 = v2.freeze({})
assert v2.value.val == v3.value.val
v = e.parseString("b@100g,digits", parseAll=True)[0]
assert v.value.datatype == "digits"
assert str(v.value) == "@100g,digits"
s = v.spec()
assert s == e.parseString(s)[0].spec()
def test_pathodspec(self):
e = base.PathodSpec.expr()
v = e.parseString("s'200'")[0]
@ -227,16 +209,10 @@ class TestMisc:
assert e.freeze({})
assert e.values({})
def test_code(self):
e = base.Code.expr()
v = e.parseString("200")[0]
assert v.string() == "200"
assert v.spec() == "200"
assert v.freeze({}).code == v.code
def test_reason(self):
e = base.Reason.expr()
def test_value(self):
class TT(base.PreValue):
preamble = "m"
e = TT.expr()
v = e.parseString("m'msg'")[0]
assert v.value.val == "msg"
@ -472,3 +448,12 @@ def test_options_or_value():
v2 = v.freeze({})
v3 = v2.freeze({})
assert v2.value.val == v3.value.val
def test_integer():
e = base.Integer.expr()
v = e.parseString("200")[0]
assert v.string() == "200"
assert v.spec() == "200"
assert v.freeze({}).value == v.value