Skip to content
This repository has been archived by the owner on Aug 2, 2023. It is now read-only.

Commit

Permalink
Merge pull request #44 from ericsnowcurrently/proto-messages
Browse files Browse the repository at this point in the history
Add all the protocol messages.
  • Loading branch information
ericsnowcurrently authored Feb 6, 2018
2 parents 49cfc12 + 87d7f8e commit 5dafa08
Show file tree
Hide file tree
Showing 12 changed files with 3,600 additions and 22 deletions.
67 changes: 67 additions & 0 deletions debugger_protocol/messages/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@


MESSAGE_TYPES = {}
MESSAGE_TYPE_KEYS = {}


def register(cls, msgtype=None, typekey=None, key=None):
"""Add the message class to the registry.
The class is also fixed up if necessary.
"""
if not isinstance(cls, type):
raise RuntimeError('may not be used as a decorator factory.')

if msgtype is None:
if cls.TYPE is None:
raise RuntimeError('class missing TYPE')
msgtype = cls.TYPE
if typekey is None:
if cls.TYPE_KEY is None:
raise RuntimeError('class missing TYPE_KEY')
typekey = cls.TYPE_KEY
if key is None:
key = getattr(cls, typekey,
getattr(cls, typekey.upper(), None))
if not key:
raise RuntimeError('missing type key attribute')

try:
registered = MESSAGE_TYPES[msgtype]
except KeyError:
registered = MESSAGE_TYPES[msgtype] = {}
MESSAGE_TYPE_KEYS[msgtype] = typekey
else:
if typekey != MESSAGE_TYPE_KEYS[msgtype]:
msg = 'mismatch on TYPE_KEY ({!r} != {!r})'
raise RuntimeError(
msg.format(typekey, MESSAGE_TYPE_KEYS[msgtype]))

if key in registered:
raise RuntimeError('{}:{} already registered'.format(msgtype, key))
registered[key] = cls

# XXX init args

return cls


class Message(object):
"""The API for register-able message types."""

TYPE = None
TYPE_KEY = None

@classmethod
def from_data(cls, **kwargs):
"""Return an instance based on the given raw data."""
raise NotImplementedError

def as_data(self):
"""Return serializable data for the instance."""
raise NotImplementedError


# Force registration.
from .requests import * # noqa
from .events import * # noqa
22 changes: 0 additions & 22 deletions debugger_protocol/messages/_base.py

This file was deleted.

49 changes: 49 additions & 0 deletions debugger_protocol/messages/_io.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import json

from . import MESSAGE_TYPES, MESSAGE_TYPE_KEYS


def read(stream):
"""Return an instance based on the given bytes."""
headers = {}
for line in stream:
if line == b'\r\n':
break
assert(line.endswith(b'\r\n'))
line = line[:-2].decode('ascii')
try:
name, value = line.split(': ', 1)
except ValueError:
raise RuntimeError('invalid header line: {}'.format(line))
headers[name] = value

size = int(headers['Content-Length'])
body = stream.read(size)

data = json.loads(body.decode('utf-8'))

msgtype = data['type']
typekey = MESSAGE_TYPE_KEYS[msgtype]
key = data[typekey]
cls = MESSAGE_TYPES[msgtype][key]

return cls.from_data(**data)


def as_bytes(msg):
"""Return the raw bytes for the message."""
headers, body = _as_http_data(msg)
headers = '\r\n'.join('{}: {}'.format(name, value)
for name, value in headers.items())
return headers.encode('ascii') + b'\r\n\r\n' + body.encode('utf-8')


def _as_http_data(msg):
payload = msg.as_data()
body = json.dumps(payload)

headers = {
'Content-Length': len(body),
'Content-Type': 'application/json',
}
return headers, body
Loading

0 comments on commit 5dafa08

Please sign in to comment.