2015-05-02 20:02:13 +00:00
|
|
|
import abc
|
|
|
|
import copy
|
|
|
|
import random
|
2016-06-01 13:15:09 +00:00
|
|
|
from functools import total_ordering
|
2015-05-02 22:11:51 +00:00
|
|
|
import pyparsing as pp
|
2015-05-02 20:02:13 +00:00
|
|
|
from . import base
|
|
|
|
|
|
|
|
|
2020-04-02 09:40:50 +00:00
|
|
|
@total_ordering # type: ignore
|
2015-05-02 20:02:13 +00:00
|
|
|
class _Action(base.Token):
|
2015-06-18 16:12:11 +00:00
|
|
|
|
2015-05-02 20:02:13 +00:00
|
|
|
"""
|
|
|
|
An action that operates on the raw data stream of the message. All
|
|
|
|
actions have one thing in common: an offset that specifies where the
|
|
|
|
action should take place.
|
|
|
|
"""
|
2015-05-30 00:03:13 +00:00
|
|
|
|
2015-05-02 20:02:13 +00:00
|
|
|
def __init__(self, offset):
|
|
|
|
self.offset = offset
|
|
|
|
|
|
|
|
def resolve(self, settings, msg):
|
|
|
|
"""
|
|
|
|
Resolves offset specifications to a numeric offset. Returns a copy
|
|
|
|
of the action object.
|
|
|
|
"""
|
|
|
|
c = copy.copy(self)
|
|
|
|
l = msg.length(settings)
|
|
|
|
if c.offset == "r":
|
|
|
|
c.offset = random.randrange(l)
|
|
|
|
elif c.offset == "a":
|
|
|
|
c.offset = l + 1
|
|
|
|
return c
|
|
|
|
|
2016-05-31 14:32:01 +00:00
|
|
|
def __lt__(self, other):
|
|
|
|
return self.offset < other.offset
|
|
|
|
|
|
|
|
def __eq__(self, other):
|
|
|
|
return self.offset == other.offset
|
2015-05-02 20:02:13 +00:00
|
|
|
|
|
|
|
def __repr__(self):
|
|
|
|
return self.spec()
|
|
|
|
|
|
|
|
@abc.abstractmethod
|
2015-05-30 00:03:13 +00:00
|
|
|
def spec(self): # pragma: no cover
|
2015-05-02 20:02:13 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
@abc.abstractmethod
|
2015-05-30 00:03:13 +00:00
|
|
|
def intermediate(self, settings): # pragma: no cover
|
2015-05-02 20:02:13 +00:00
|
|
|
pass
|
|
|
|
|
|
|
|
|
|
|
|
class PauseAt(_Action):
|
2017-05-26 14:14:20 +00:00
|
|
|
unique_name = None
|
2015-05-16 22:43:30 +00:00
|
|
|
|
2015-05-02 20:02:13 +00:00
|
|
|
def __init__(self, offset, seconds):
|
|
|
|
_Action.__init__(self, offset)
|
|
|
|
self.seconds = seconds
|
|
|
|
|
|
|
|
@classmethod
|
2015-06-18 09:07:33 +00:00
|
|
|
def expr(cls):
|
2015-05-02 20:02:13 +00:00
|
|
|
e = pp.Literal("p").suppress()
|
2015-05-03 00:53:28 +00:00
|
|
|
e += base.TokOffset
|
2015-05-02 20:02:13 +00:00
|
|
|
e += pp.Literal(",").suppress()
|
|
|
|
e += pp.MatchFirst(
|
|
|
|
[
|
|
|
|
base.v_integer,
|
|
|
|
pp.Literal("f")
|
|
|
|
]
|
|
|
|
)
|
2015-06-18 09:07:33 +00:00
|
|
|
return e.setParseAction(lambda x: cls(*x))
|
2015-05-02 20:02:13 +00:00
|
|
|
|
|
|
|
def spec(self):
|
2020-11-20 18:25:26 +00:00
|
|
|
return f"p{self.offset},{self.seconds}"
|
2015-05-02 20:02:13 +00:00
|
|
|
|
|
|
|
def intermediate(self, settings):
|
|
|
|
return (self.offset, "pause", self.seconds)
|
|
|
|
|
2015-06-18 16:05:09 +00:00
|
|
|
def freeze(self, settings_):
|
2015-05-02 20:02:13 +00:00
|
|
|
return self
|
|
|
|
|
|
|
|
|
|
|
|
class DisconnectAt(_Action):
|
2015-06-18 16:12:11 +00:00
|
|
|
|
2015-05-02 20:02:13 +00:00
|
|
|
def __init__(self, offset):
|
|
|
|
_Action.__init__(self, offset)
|
|
|
|
|
|
|
|
@classmethod
|
2015-06-18 09:07:33 +00:00
|
|
|
def expr(cls):
|
2015-05-02 20:02:13 +00:00
|
|
|
e = pp.Literal("d").suppress()
|
2015-05-03 00:53:28 +00:00
|
|
|
e += base.TokOffset
|
2015-06-18 09:07:33 +00:00
|
|
|
return e.setParseAction(lambda x: cls(*x))
|
2015-05-02 20:02:13 +00:00
|
|
|
|
|
|
|
def spec(self):
|
2015-05-30 00:03:13 +00:00
|
|
|
return "d%s" % self.offset
|
2015-05-02 20:02:13 +00:00
|
|
|
|
|
|
|
def intermediate(self, settings):
|
|
|
|
return (self.offset, "disconnect")
|
|
|
|
|
2015-06-18 16:05:09 +00:00
|
|
|
def freeze(self, settings_):
|
2015-05-02 20:02:13 +00:00
|
|
|
return self
|
|
|
|
|
|
|
|
|
|
|
|
class InjectAt(_Action):
|
2017-05-01 23:49:25 +00:00
|
|
|
unique_name = None # type: ignore
|
2015-05-16 22:43:30 +00:00
|
|
|
|
2015-05-02 20:02:13 +00:00
|
|
|
def __init__(self, offset, value):
|
|
|
|
_Action.__init__(self, offset)
|
|
|
|
self.value = value
|
|
|
|
|
|
|
|
@classmethod
|
2015-06-18 09:07:33 +00:00
|
|
|
def expr(cls):
|
2015-05-02 20:02:13 +00:00
|
|
|
e = pp.Literal("i").suppress()
|
2015-05-03 00:53:28 +00:00
|
|
|
e += base.TokOffset
|
2015-05-02 20:02:13 +00:00
|
|
|
e += pp.Literal(",").suppress()
|
2015-05-03 00:53:28 +00:00
|
|
|
e += base.TokValue
|
2015-06-18 09:07:33 +00:00
|
|
|
return e.setParseAction(lambda x: cls(*x))
|
2015-05-02 20:02:13 +00:00
|
|
|
|
|
|
|
def spec(self):
|
2020-11-20 18:25:26 +00:00
|
|
|
return f"i{self.offset},{self.value.spec()}"
|
2015-05-02 20:02:13 +00:00
|
|
|
|
|
|
|
def intermediate(self, settings):
|
|
|
|
return (
|
|
|
|
self.offset,
|
|
|
|
"inject",
|
|
|
|
self.value.get_generator(settings)
|
|
|
|
)
|
|
|
|
|
|
|
|
def freeze(self, settings):
|
|
|
|
return InjectAt(self.offset, self.value.freeze(settings))
|