Skip to content

Commit

Permalink
Wamp idl 3 (#1434)
Browse files Browse the repository at this point in the history
polish and fixes of CLI for WAMP IDL
  • Loading branch information
oberstet committed Dec 13, 2020
1 parent 1747858 commit 4bbc1a6
Show file tree
Hide file tree
Showing 13 changed files with 412 additions and 129 deletions.
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

0 comments on commit 4bbc1a6

Please sign in to comment.