Skip to content

Commit

Permalink
relax deserialization of Yandex requests
Browse files Browse the repository at this point in the history
  • Loading branch information
avidale committed Jan 9, 2021
1 parent 4f578ab commit 40aaa8f
Show file tree
Hide file tree
Showing 3 changed files with 56 additions and 19 deletions.
27 changes: 14 additions & 13 deletions tgalice/interfaces/yandex/request.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

import attr
from typing import Dict, List, Optional
from tgalice.utils.serialization import Serializeable, list_converter, dict_converter
from tgalice.utils.serialization import FreeSerializeable, list_converter, dict_converter


class ENTITY_TYPES:
Expand All @@ -17,7 +17,7 @@ class ENTITY_TYPES:


@attr.s
class Meta(Serializeable):
class Meta(FreeSerializeable):
locale: str = attr.ib()
timezone: str = attr.ib()
client_id: str = attr.ib()
Expand All @@ -33,27 +33,27 @@ def has_account_linking(self) -> bool:


@attr.s
class Span(Serializeable):
class Span(FreeSerializeable):
start: int = attr.ib()
end: int = attr.ib()


@attr.s
class Entity(Serializeable):
class Entity(FreeSerializeable):
type: str = attr.ib() # may be one of ENTITY_TYPES, but not only
tokens: Span = attr.ib(converter=Span.from_dict)
value = attr.ib()


@attr.s
class Slot(Serializeable):
class Slot(FreeSerializeable):
type: str = attr.ib()
tokens: Optional[Span] = attr.ib(converter=Span.from_dict, default=None)
value = attr.ib(default=None)


@attr.s
class Intent(Serializeable):
class Intent(FreeSerializeable):
slots: Dict[str, Slot] = attr.ib(converter=dict_converter(Slot))

def get_form(self) -> Dict[str, str]:
Expand All @@ -64,7 +64,7 @@ def get_form(self) -> Dict[str, str]:


@attr.s
class NLU(Serializeable):
class NLU(FreeSerializeable):
tokens: List[str] = attr.ib(factory=list)
entities: List[Entity] = attr.ib(converter=list_converter(Entity), factory=list)
intents: Dict[str, Intent] = attr.ib(converter=dict_converter(Intent), factory=dict)
Expand All @@ -77,26 +77,27 @@ def get_forms(self) -> Dict[str, Dict[str, str]]:


@attr.s
class Request(Serializeable):
class Request(FreeSerializeable):
command: str = attr.ib(default=None)
original_utterance: str = attr.ib(default=None)
type: str = attr.ib(default=None)
markup = attr.ib(factory=dict)
payload = attr.ib(factory=dict)
nlu: Optional[NLU] = attr.ib(converter=NLU.from_dict, default=None)
show_type: Optional[str] = attr.ib(default=None)


class User:
class User(FreeSerializeable):
user_id: str = attr.ib(default=None)
access_token: str = attr.ib(default=None)


class Application:
class Application(FreeSerializeable):
application_id: str = attr.ib(default=None)


@attr.s
class Session(Serializeable):
class Session(FreeSerializeable):
message_id: int = attr.ib()
session_id: str = attr.ib()
skill_id: str = attr.ib()
Expand All @@ -108,14 +109,14 @@ class Session(Serializeable):


@attr.s
class State(Serializeable):
class State(FreeSerializeable):
session: Optional[Dict] = attr.ib(default=None)
user: Optional[Dict] = attr.ib(default=None)
application: Optional[Dict] = attr.ib(default=None)


@attr.s
class YandexRequest(Serializeable):
class YandexRequest(FreeSerializeable):
meta: Meta = attr.ib(converter=Meta.from_dict)
request: Request = attr.ib(converter=Request.from_dict)
session: Optional[Session] = attr.ib(converter=Session.from_dict)
Expand Down
15 changes: 11 additions & 4 deletions tgalice/storage/message_logging.py
Original file line number Diff line number Diff line change
Expand Up @@ -121,17 +121,24 @@ def log_message(self, message, source, context=None, response=None, **kwargs):
return
if response is not None and response.label is not None:
msg.kwargs['label'] = response.label
if self.not_log_id is not None and msg.user_id in self.not_log_id:
# main reason: don't log pings from Yandex
return
if self.detect_pings and self.is_like_ping(context):
if self.should_ignore_message(result=msg, message=message, context=context, response=response):
return
self.save_a_message(msg.to_dict())

def is_like_ping(self, context=None):
return context is not None and context.source == SOURCES.ALICE \
and context.message_text == 'ping' and context.session_is_new()

def should_ignore_message(
self, result: LoggedMessage, message=None, context: Context = None, response: Response = None
) -> bool:
if self.not_log_id is not None and result.user_id in self.not_log_id:
# main reason: don't log pings from Yandex
return True
if self.detect_pings and self.is_like_ping(context):
return True
return False

def save_a_message(self, message_dict):
logger.info(message_dict)

Expand Down
33 changes: 31 additions & 2 deletions tgalice/utils/serialization.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
import inspect
from collections.abc import Mapping


def list_converter(cls):
Expand All @@ -22,9 +24,12 @@ class Serializeable:
""" This mixin is used for easy conversion of structured objects from and to json """

@classmethod
def from_dict(cls, data):
def from_dict(cls, data, from_none=False):
if data is None:
return None
if from_none:
data = {}
else:
return None
if isinstance(data, cls):
return data
# assume all the heavy lifting is done by converters in the cls.__init__
Expand All @@ -41,3 +46,27 @@ def to_dict(self):
field = try_serialize(field)
result[field_name] = field
return result


class FreeSerializeable(Serializeable):
""" A serializeable object that can accept and preserve arbitrary extra keys. """
@classmethod
def from_dict(cls, data, from_none=False):
if isinstance(data, Mapping) and not isinstance(data, cls):
arg_names = set(inspect.signature(cls.__init__).parameters)
args = {k: v for k, v in data.items() if k in arg_names}
other = {k: v for k, v in data.items() if k not in arg_names}
else:
args = data
other = None
result = super(FreeSerializeable, cls).from_dict(args, from_none=from_none)
if result is not None:
result._other = other
return result

def to_dict(self):
result = super(FreeSerializeable, self).to_dict()
del result['_other']
if hasattr(self, '_other') and self._other:
result.update(self._other)
return result

0 comments on commit 40aaa8f

Please sign in to comment.