Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Wamp idl 3 #1434

Merged
merged 11 commits into from Dec 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
55 changes: 27 additions & 28 deletions .travis.yml
@@ -1,5 +1,5 @@
language: python
dist: xenial
dist: bionic
sudo: true

addons:
Expand Down Expand Up @@ -44,66 +44,66 @@ matrix:
- TOX_ENV=flake8

#
# CPython 3.5
# CPython 3.7
#
- python: "3.5"
- python: "3.7"
env:
- TOX_ENV=py35-tw189
- TOX_ENV=py37-tw189

- python: "3.5"
- python: "3.7"
env:
- TOX_ENV=py35-tw1910
- TOX_ENV=py37-tw1910

- python: "3.5"
- python: "3.7"
env:
- TOX_ENV=py35-twtrunk
- TOX_ENV=py37-twtrunk

- python: "3.5"
- python: "3.7"
env:
- TOX_ENV=py35-asyncio
- TOX_ENV=py37-asyncio

#
# CPython 3.8
# CPython 3.9
#
- python: "3.8"
- python: "3.9"
env:
- TOX_ENV=py38-tw189
- TOX_ENV=py39-tw189

- python: "3.8"
- python: "3.9"
env:
- TOX_ENV=py38-tw1910
- TOX_ENV=py39-tw1910

- python: "3.8"
- python: "3.9"
env:
- TOX_ENV=py38-twtrunk
- TOX_ENV=py39-twtrunk

- python: "3.8"
- python: "3.9"
env:
- TOX_ENV=py38-asyncio
- TOX_ENV=py39-asyncio

#
# PyPy3
#
- python: "pypy3.5"
- python: "pypy3.6-7.3.1"
env:
- TOX_ENV=pypy3-tw189

- python: "pypy3.5"
- python: "pypy3.6-7.3.1"
env:
- TOX_ENV=pypy3-tw1910

- python: "pypy3.5"
- python: "pypy3.6-7.3.1"
env:
- TOX_ENV=pypy3-twtrunk

- python: "pypy3.5"
- python: "pypy3.6-7.3.1"
env:
- TOX_ENV=pypy3-asyncio

#
# Coverage (run under CPython 3.5)
# Coverage (run under CPython 3.8)
#
- python: "3.5"
- python: "3.8"
skip_cleanup: true
env: TOX_ENV=coverage

Expand All @@ -123,9 +123,8 @@ matrix:
script: pwd && ls -la && sh .travis-deploy.sh

allow_failures:
- env: TOX_ENV=coverage
- os: osx
- python: "pypy3.5"
- env: TOX_ENV=py39-asyncio


# CI notifications
notifications:
Expand Down
2 changes: 1 addition & 1 deletion README.rst
Expand Up @@ -20,7 +20,7 @@ implementations of
- `The WebSocket Protocol <http://tools.ietf.org/html/rfc6455>`__
- `The Web Application Messaging Protocol (WAMP) <http://wamp-proto.org/>`__

for Python 3.5+ and running on `Twisted <http://twistedmatrix.com/>`__ and `asyncio <http://docs.python.org/3.4/library/asyncio.html>`__.
for Python 3.6+ and running on `Twisted <http://twistedmatrix.com/>`__ and `asyncio <http://docs.python.org/3.4/library/asyncio.html>`__.

You can use **Autobahn\|Python** to create clients and servers in Python speaking just plain WebSocket or WAMP.

Expand Down
2 changes: 1 addition & 1 deletion autobahn/xbr/__init__.py
Expand Up @@ -36,7 +36,7 @@
from autobahn.xbr._abi import XBR_TOKEN_ABI, XBR_NETWORK_ABI, XBR_MARKET_ABI, XBR_CATALOG_ABI, XBR_CHANNEL_ABI # noqa
from autobahn.xbr._abi import XBR_DEBUG_TOKEN_ADDR, XBR_DEBUG_NETWORK_ADDR, XBR_DEBUG_MARKET_ADDR, XBR_DEBUG_CATALOG_ADDR, XBR_DEBUG_CHANNEL_ADDR # noqa
from autobahn.xbr._abi import XBR_DEBUG_TOKEN_ADDR_SRC, XBR_DEBUG_NETWORK_ADDR_SRC, XBR_DEBUG_MARKET_ADDR_SRC, XBR_DEBUG_CATALOG_ADDR_SRC, XBR_DEBUG_CHANNEL_ADDR_SRC # noqa
from autobahn.xbr._interfaces import IMarketMaker, IProvider, IConsumer, ISeller, IBuyer # noqa
from autobahn.xbr._interfaces import IMarketMaker, IProvider, IConsumer, ISeller, IBuyer, IDelegate # noqa
from autobahn.xbr._util import make_w3, pack_uint256, unpack_uint256, with_0x, without_0x # noqa

from autobahn.xbr._eip712_member_register import sign_eip712_member_register, recover_eip712_member_register # noqa
Expand Down
12 changes: 9 additions & 3 deletions autobahn/xbr/_cli.py
Expand Up @@ -1019,13 +1019,19 @@ def _main():
# pprint(item.marshal())
metadata = item

# com.things.home.device.HomeDeviceVendor => com.things.home.device
# com.example.device.HomeDeviceVendor => com.example.device
modulename = '.'.join(metadata.name.split('.')[0:-1])
is_first = modulename not in code_modules
is_first_by_category = (modulename, category) not in is_first_by_category_modules
metadata.modulename = modulename

# com.example.device.HomeDeviceVendor => HomeDeviceVendor
metadata.classname = metadata.name.split('.')[-1].strip()

# com.example.device => device
metadata.module_relimport = modulename.split('.')[-1]

is_first = modulename not in code_modules
is_first_by_category = (modulename, category) not in is_first_by_category_modules

if is_first_by_category:
is_first_by_category_modules[(modulename, category)] = True

Expand Down
6 changes: 6 additions & 0 deletions autobahn/xbr/_interfaces.py
Expand Up @@ -180,3 +180,9 @@ async def unwrap(self, key_id, enc_ser, ciphertext):
:returns: The unwrapped application payload.
:rtype: object
"""


class IDelegate(ISeller, IBuyer):
"""
XBR Delegate interface.
"""
148 changes: 91 additions & 57 deletions autobahn/xbr/_schema.py
Expand Up @@ -354,10 +354,13 @@ def parse_fields(obj):
fields_by_id = {}
for j in range(obj.FieldsLength()):
fbs_field = obj.Fields(j)

field_name = fbs_field.Name()
if field_name:
field_name = field_name.decode('utf8')

field_id = int(fbs_field.Id())

fbs_field_type = fbs_field.Type()
field_type = FbsType(basetype=fbs_field_type.BaseType(),
element=fbs_field_type.Element(),
Expand All @@ -383,6 +386,79 @@ def parse_fields(obj):
return fields, fields_by_id


def parse_calls(svc_obj):
calls = {}
calls_by_id = {}
for j in range(svc_obj.CallsLength()):
fbs_call = svc_obj.Calls(j)

call_name = fbs_call.Name()
if call_name:
call_name = call_name.decode('utf8')

# FIXME: schema reflection.RPCCall lacks "Id" (!)
# call_id = int(fbs_call.Id())
call_id = j

fbs_call_req = fbs_call.Request()
call_req_name = fbs_call_req.Name()
if call_req_name:
call_req_name = call_req_name.decode('utf8')
call_req_is_struct = fbs_call_req.IsStruct()
call_req_min_align = fbs_call_req.Minalign()
call_req_bytesize = fbs_call_req.Bytesize()
call_req_docs = parse_docs(fbs_call_req)
call_req_attrs = parse_attr(fbs_call_req)
call_req_fields, call_fields_by_id = parse_fields(fbs_call_req)
call_req = FbsObject(name=call_req_name,
fields=call_req_fields,
fields_by_id=call_fields_by_id,
is_struct=call_req_is_struct,
min_align=call_req_min_align,
bytesize=call_req_bytesize,
attrs=call_req_attrs,
docs=call_req_docs)

fbs_call_resp = fbs_call.Response()
call_resp_name = fbs_call_resp.Name()
if call_resp_name:
call_resp_name = call_resp_name.decode('utf8')
call_resp_is_struct = fbs_call_resp.IsStruct()
call_resp_min_align = fbs_call_resp.Minalign()
call_resp_bytesize = fbs_call_resp.Bytesize()
call_resp_docs = parse_docs(fbs_call_resp)
call_resp_attrs = parse_attr(fbs_call_resp)
call_resp_fields, call_resp_fields_by_id = parse_fields(fbs_call_resp)
call_resp = FbsObject(name=call_resp_name,
fields=call_resp_fields,
fields_by_id=call_resp_fields_by_id,
is_struct=call_resp_is_struct,
min_align=call_resp_min_align,
bytesize=call_resp_bytesize,
attrs=call_resp_attrs,
docs=call_resp_docs)

call_docs = parse_docs(fbs_call)
call_attrs = parse_attr(fbs_call)
call = FbsRPCCall(name=call_name,
id=call_id,
request=call_req,
response=call_resp,
docs=call_docs,
attrs=call_attrs)

assert call_name not in calls, 'call "{}" with id "{}" already in calls {}'.format(call_name, call_id, sorted(calls.keys()))
calls[call_name] = call
assert call_id not in calls_by_id, 'call "{}" with id " {}" already in calls {}'.format(call_name, call_id, sorted(calls.keys()))
calls_by_id[call_id] = call_name

res = []
for _, value in sorted(calls_by_id.items()):
res.append(value)
calls_by_id = res
return calls, calls_by_id


class FbsObject(object):
def __init__(self,
name: str,
Expand Down Expand Up @@ -477,11 +553,13 @@ def parse(fbs_obj):
class FbsRPCCall(object):
def __init__(self,
name: str,
id: int,
request: FbsObject,
response: FbsObject,
docs: str,
attrs: Dict[str, FbsAttribute]):
self._name = name
self._id = id
self._request = request
self._response = response
self._docs = docs
Expand All @@ -491,6 +569,10 @@ def __init__(self,
def name(self):
return self._name

@property
def id(self):
return self._id

@property
def request(self):
return self._request
Expand Down Expand Up @@ -528,10 +610,12 @@ class FbsService(object):
def __init__(self,
name: str,
calls: Dict[str, FbsRPCCall],
calls_by_id: Dict[int, str],
attrs: Dict[str, FbsAttribute],
docs: str):
self._name = name
self._calls = calls
self._calls_by_id = calls_by_id
self._attrs = attrs
self._docs = docs

Expand All @@ -543,6 +627,10 @@ def name(self):
def calls(self):
return self._calls

@property
def calls_by_id(self):
return self._calls_by_id

@property
def attrs(self):
return self._attrs
Expand Down Expand Up @@ -861,65 +949,11 @@ def load(filename) -> object:
if svc_name:
svc_name = svc_name.decode('utf8')

calls = {}
for j in range(svc_obj.CallsLength()):
fbs_call = svc_obj.Calls(j)

call_name = fbs_call.Name()
if call_name:
call_name = call_name.decode('utf8')

fbs_call_req = fbs_call.Request()
call_req_name = fbs_call_req.Name()
if call_req_name:
call_req_name = call_req_name.decode('utf8')
call_req_is_struct = fbs_call_req.IsStruct()
call_req_min_align = fbs_call_req.Minalign()
call_req_bytesize = fbs_call_req.Bytesize()
call_req_docs = parse_docs(fbs_call_req)
call_req_attrs = parse_attr(fbs_call_req)
call_req_fields, call_fields_by_id = parse_fields(fbs_call_req)
call_req = FbsObject(name=call_req_name,
fields=call_req_fields,
fields_by_id=call_fields_by_id,
is_struct=call_req_is_struct,
min_align=call_req_min_align,
bytesize=call_req_bytesize,
attrs=call_req_attrs,
docs=call_req_docs)

fbs_call_resp = fbs_call.Response()
call_resp_name = fbs_call_resp.Name()
if call_resp_name:
call_resp_name = call_resp_name.decode('utf8')
call_resp_is_struct = fbs_call_resp.IsStruct()
call_resp_min_align = fbs_call_resp.Minalign()
call_resp_bytesize = fbs_call_resp.Bytesize()
call_resp_docs = parse_docs(fbs_call_resp)
call_resp_attrs = parse_attr(fbs_call_resp)
call_resp_fields, call_resp_fields_by_id = parse_fields(fbs_call_resp)
call_resp = FbsObject(name=call_resp_name,
fields=call_resp_fields,
fields_by_id=call_resp_fields_by_id,
is_struct=call_resp_is_struct,
min_align=call_resp_min_align,
bytesize=call_resp_bytesize,
attrs=call_resp_attrs,
docs=call_resp_docs)

call_docs = parse_docs(fbs_call)
call_attrs = parse_attr(fbs_call)
call = FbsRPCCall(name=call_name,
request=call_req,
response=call_resp,
docs=call_docs,
attrs=call_attrs)
assert call_name not in calls
calls[call_name] = call

docs = parse_docs(svc_obj)
attrs = parse_attr(svc_obj)
service = FbsService(name=svc_name, calls=calls, attrs=attrs, docs=docs)
calls, calls_by_id = parse_calls(svc_obj)

service = FbsService(name=svc_name, calls=calls, calls_by_id=calls_by_id, attrs=attrs, docs=docs)
assert svc_name not in services
services[svc_name] = service

Expand Down