crossbario / autobahn-python

@@ -0,0 +1,1008 @@
Loading
1 +
###############################################################################
2 +
#
3 +
# The MIT License (MIT)
4 +
#
5 +
# Copyright (c) 2018 Luis Teixeira
6 +
# - copied & modified from https://github.com/vergl4s/ethereum-mnemonic-utils
7 +
#
8 +
# Permission is hereby granted, free of charge, to any person obtaining a copy
9 +
# of this software and associated documentation files (the "Software"), to deal
10 +
# in the Software without restriction, including without limitation the rights
11 +
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 +
# copies of the Software, and to permit persons to whom the Software is
13 +
# furnished to do so, subject to the following conditions:
14 +
#
15 +
# The above copyright notice and this permission notice shall be included in
16 +
# all copies or substantial portions of the Software.
17 +
#
18 +
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 +
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 +
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 +
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 +
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 +
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 +
# THE SOFTWARE.
25 +
#
26 +
###############################################################################
27 +
28 +
import os
29 +
import pprint
30 +
import hashlib
31 +
from typing import Dict, Optional
32 +
from pathlib import Path
33 +
34 +
from zlmdb.flatbuffers.reflection.Schema import Schema as _Schema
35 +
from zlmdb.flatbuffers.reflection.BaseType import BaseType as _BaseType
36 +
37 +
38 +
class FbsType(object):
39 +
    """
40 +
    """
41 +
42 +
    # no type
43 +
    None_ = _BaseType.None_
44 +
45 +
    # ???
46 +
    UType = _BaseType.UType
47 +
48 +
    # scalar types
49 +
    Bool = _BaseType.Bool
50 +
    Byte = _BaseType.Byte
51 +
    UByte = _BaseType.UByte
52 +
    Short = _BaseType.Short
53 +
    UShort = _BaseType.UShort
54 +
    Int = _BaseType.Int
55 +
    UInt = _BaseType.UInt
56 +
    Long = _BaseType.Long
57 +
    ULong = _BaseType.ULong
58 +
    Float = _BaseType.Float
59 +
    Double = _BaseType.Double
60 +
    String = _BaseType.String
61 +
62 +
    SCALAR_TYPES = [_BaseType.Bool,
63 +
                    _BaseType.Byte,
64 +
                    _BaseType.UByte,
65 +
                    _BaseType.Short,
66 +
                    _BaseType.UShort,
67 +
                    _BaseType.Int,
68 +
                    _BaseType.UInt,
69 +
                    _BaseType.Long,
70 +
                    _BaseType.ULong,
71 +
                    _BaseType.Float,
72 +
                    _BaseType.Double,
73 +
                    _BaseType.String]
74 +
75 +
    # structured types
76 +
    Vector = _BaseType.Vector
77 +
    Obj = _BaseType.Obj
78 +
    Union = _BaseType.Union
79 +
80 +
    STRUCTURED_TYPES = [_BaseType.Vector,
81 +
                        _BaseType.Obj,
82 +
                        _BaseType.Union]
83 +
84 +
    FBS2PY = {
85 +
        _BaseType.None_: 'type(None)',
86 +
        _BaseType.UType: 'int',
87 +
        _BaseType.Bool: 'bool',
88 +
        _BaseType.Byte: 'bytes',
89 +
        _BaseType.UByte: 'int',
90 +
        _BaseType.Short: 'int',
91 +
        _BaseType.UShort: 'int',
92 +
        _BaseType.Int: 'int',
93 +
        _BaseType.UInt: 'int',
94 +
        _BaseType.Long: 'int',
95 +
        _BaseType.ULong: 'int',
96 +
        _BaseType.Float: 'float',
97 +
        _BaseType.Double: 'float',
98 +
        _BaseType.String: 'str',
99 +
        _BaseType.Vector: 'List',
100 +
        _BaseType.Obj: 'object',
101 +
        _BaseType.Union: 'Union',
102 +
    }
103 +
104 +
    FBS2FLAGS = {
105 +
        _BaseType.Bool: 'BoolFlags',
106 +
        _BaseType.Byte: 'Int8Flags',
107 +
        _BaseType.UByte: 'Uint8Flags',
108 +
        _BaseType.Short: 'Int16Flags',
109 +
        _BaseType.UShort: 'Uint16Flags',
110 +
        _BaseType.Int: 'Int32Flags',
111 +
        _BaseType.UInt: 'Uint32Flags',
112 +
        _BaseType.Long: 'Int64Flags',
113 +
        _BaseType.ULong: 'Uint64Flags',
114 +
        _BaseType.Float: 'Float32Flags',
115 +
        _BaseType.Double: 'Float64Flags',
116 +
    }
117 +
118 +
    FBS2STR = {
119 +
        _BaseType.None_: 'None',
120 +
        _BaseType.UType: 'UType',
121 +
        _BaseType.Bool: 'Bool',
122 +
        _BaseType.Byte: 'Byte',
123 +
        _BaseType.UByte: 'UByte',
124 +
        _BaseType.Short: 'Short',
125 +
        _BaseType.UShort: 'UShort',
126 +
        _BaseType.Int: 'Int',
127 +
        _BaseType.UInt: 'UInt',
128 +
        _BaseType.Long: 'Long',
129 +
        _BaseType.ULong: 'ULong',
130 +
        _BaseType.Float: 'Float',
131 +
        _BaseType.Double: 'Double',
132 +
        _BaseType.String: 'String',
133 +
        _BaseType.Vector: 'Vector',
134 +
        _BaseType.Obj: 'Obj',
135 +
        _BaseType.Union: 'Union',
136 +
    }
137 +
138 +
    STR2FBS = {
139 +
        'None': _BaseType.None_,
140 +
        'UType': _BaseType.UType,
141 +
        'Bool': _BaseType.Bool,
142 +
        'Byte': _BaseType.Byte,
143 +
        'UByte': _BaseType.UByte,
144 +
        'Short': _BaseType.Short,
145 +
        'UShort': _BaseType.UShort,
146 +
        'Int': _BaseType.Int,
147 +
        'UInt': _BaseType.UInt,
148 +
        'Long': _BaseType.Long,
149 +
        'ULong': _BaseType.ULong,
150 +
        'Float': _BaseType.Float,
151 +
        'Double': _BaseType.Double,
152 +
        'String': _BaseType.String,
153 +
        'Vector': _BaseType.Vector,
154 +
        'Obj': _BaseType.Obj,
155 +
        'Union': _BaseType.Union,
156 +
    }
157 +
158 +
    def __init__(self, basetype: int, element: int, index: int):
159 +
        self._basetype = basetype
160 +
        self._element = element
161 +
        self._index = index
162 +
163 +
    @property
164 +
    def basetype(self):
165 +
        return self._basetype
166 +
167 +
    @property
168 +
    def element(self):
169 +
        return self._element
170 +
171 +
    @property
172 +
    def index(self):
173 +
        return self._index
174 +
175 +
    def map(self, language: str, attrs: Optional[Dict] = None, required: Optional[bool] = True) -> str:
176 +
        """
177 +
178 +
        :param language:
179 +
        :return:
180 +
        """
181 +
        if language == 'python':
182 +
            _mapped_type = None
183 +
            if self.basetype == FbsType.Vector:
184 +
                # vectors of uint8 are mapped to byte strings ..
185 +
                if self.element == FbsType.UByte:
186 +
                    if attrs and 'uuid' in attrs:
187 +
                        _mapped_type = 'uuid.UUID'
188 +
                    else:
189 +
                        _mapped_type = 'bytes'
190 +
                # .. whereas all other vectors are mapped to lists of the same element type
191 +
                else:
192 +
                    _mapped_type = 'List[{}]'.format(FbsType.FBS2PY[self.element])
193 +
            elif self.basetype in FbsType.SCALAR_TYPES:
194 +
                if self.basetype == FbsType.ULong and attrs and 'timestamp' in attrs:
195 +
                    _mapped_type = 'np.datetime64'
196 +
                else:
197 +
                    _mapped_type = FbsType.FBS2PY[self.basetype]
198 +
            else:
199 +
                raise NotImplementedError('FIXME: implement mapping of FlatBuffers type "{}" to Python in {}'.format(self.basetype, self.map))
200 +
            if required:
201 +
                return _mapped_type
202 +
            else:
203 +
                return 'Optional[{}]'.format(_mapped_type)
204 +
        else:
205 +
            raise RuntimeError('cannot map FlatBuffers type to target language "{}" in {}'.format(language, self.map))
206 +
207 +
    def __str__(self):
208 +
        return '\n{}\n'.format(pprint.pformat(self.marshal()))
209 +
210 +
    def marshal(self):
211 +
        obj = {
212 +
            'basetype': self.FBS2STR.get(self._basetype, None),
213 +
            'element': self.FBS2STR.get(self._element, None),
214 +
            'index': self._index,
215 +
        }
216 +
        return obj
217 +
218 +
219 +
class FbsAttribute(object):
220 +
    def __init__(self):
221 +
        pass
222 +
223 +
    def __str__(self):
224 +
        return ''.format()
225 +
226 +
227 +
class FbsField(object):
228 +
    def __init__(self,
229 +
                 name: str,
230 +
                 type: FbsType,
231 +
                 id: int,
232 +
                 offset: int,
233 +
                 default_int: int,
234 +
                 default_real: float,
235 +
                 deprecated: bool,
236 +
                 required: bool,
237 +
                 attrs: Dict[str, FbsAttribute],
238 +
                 docs: str):
239 +
        self._name = name
240 +
        self._type = type
241 +
        self._id = id
242 +
        self._offset = offset
243 +
        self._default_int = default_int
244 +
        self._default_real = default_real
245 +
        self._deprecated = deprecated
246 +
        self._required = required
247 +
        self._attrs = attrs
248 +
        self._docs = docs
249 +
250 +
    @property
251 +
    def name(self):
252 +
        return self._name
253 +
254 +
    @property
255 +
    def type(self):
256 +
        return self._type
257 +
258 +
    @property
259 +
    def id(self):
260 +
        return self._id
261 +
262 +
    @property
263 +
    def offset(self):
264 +
        return self._offset
265 +
266 +
    @property
267 +
    def default_int(self):
268 +
        return self._default_int
269 +
270 +
    @property
271 +
    def default_real(self):
272 +
        return self._default_real
273 +
274 +
    @property
275 +
    def deprecated(self):
276 +
        return self._deprecated
277 +
278 +
    @property
279 +
    def required(self):
280 +
        return self._required
281 +
282 +
    @property
283 +
    def attrs(self):
284 +
        return self._attrs
285 +
286 +
    @property
287 +
    def docs(self):
288 +
        return self._docs
289 +
290 +
    def __str__(self):
291 +
        return '\n{}\n'.format(pprint.pformat(self.marshal()))
292 +
293 +
    def marshal(self):
294 +
        obj = {
295 +
            'name': self._name,
296 +
            'type': self._type.marshal() if self._type else None,
297 +
            'id': self._id,
298 +
            'offset': self._offset,
299 +
            'default_int': self._default_int,
300 +
            'default_real': self._default_real,
301 +
            'deprecated': self._deprecated,
302 +
            'required': self._required,
303 +
            'attrs': {},
304 +
            'docs': self._docs,
305 +
        }
306 +
        if self._attrs:
307 +
            for k, v in self._attrs.items():
308 +
                obj['attrs'][k] = v
309 +
        return obj
310 +
311 +
312 +
def parse_attr(obj):
313 +
    attrs = {}
314 +
    for j in range(obj.AttributesLength()):
315 +
        fbs_attr = obj.Attributes(j)
316 +
        attr_key = fbs_attr.Key()
317 +
        if attr_key:
318 +
            attr_key = attr_key.decode('utf8')
319 +
        attr_value = fbs_attr.Value()
320 +
        if attr_value:
321 +
            attr_value = attr_value.decode('utf8')
322 +
        assert attr_key not in attrs
323 +
        attrs[attr_key] = attr_value
324 +
    return attrs
325 +
326 +
327 +
def parse_docs(obj):
328 +
    docs = []
329 +
    for j in range(obj.DocumentationLength()):
330 +
        doc_line = obj.Documentation(j)
331 +
        if doc_line:
332 +
            doc_line = doc_line.decode('utf8')
333 +
            docs.append(doc_line)
334 +
    docs = '\n'.join(docs).strip()
335 +
    return docs
336 +
337 +
338 +
def parse_fields(obj):
339 +
    fields = {}
340 +
    fields_by_id = {}
341 +
    for j in range(obj.FieldsLength()):
342 +
        fbs_field = obj.Fields(j)
343 +
        field_name = fbs_field.Name()
344 +
        if field_name:
345 +
            field_name = field_name.decode('utf8')
346 +
        field_id = int(fbs_field.Id())
347 +
        fbs_field_type = fbs_field.Type()
348 +
        field_type = FbsType(basetype=fbs_field_type.BaseType(),
349 +
                             element=fbs_field_type.Element(),
350 +
                             index=fbs_field_type.Index())
351 +
        field = FbsField(name=field_name,
352 +
                         type=field_type,
353 +
                         id=field_id,
354 +
                         offset=fbs_field.Offset(),
355 +
                         default_int=fbs_field.DefaultInteger(),
356 +
                         default_real=fbs_field.DefaultReal(),
357 +
                         deprecated=fbs_field.Deprecated(),
358 +
                         required=fbs_field.Required(),
359 +
                         attrs=parse_attr(fbs_field),
360 +
                         docs=parse_docs(fbs_field))
361 +
        assert field_name not in fields, 'field "{}" with id "{}" already in fields {}'.format(field_name, field_id, sorted(fields.keys()))
362 +
        fields[field_name] = field
363 +
        assert field_id not in fields_by_id, 'field "{}" with id " {}" already in fields {}'.format(field_name, field_id, sorted(fields.keys()))
364 +
        fields_by_id[field_id] = field_name
365 +
    res = []
366 +
    for _, value in sorted(fields_by_id.items()):
367 +
        res.append(value)
368 +
    fields_by_id = res
369 +
    return fields, fields_by_id
370 +
371 +
372 +
class FbsObject(object):
373 +
    def __init__(self,
374 +
                 name: str,
375 +
                 fields: Dict[str, FbsField],
376 +
                 fields_by_id: Dict[int, str],
377 +
                 is_struct: bool,
378 +
                 min_align: int,
379 +
                 bytesize: int,
380 +
                 attrs: Dict[str, FbsAttribute],
381 +
                 docs: str):
382 +
        self._name = name
383 +
        self._fields = fields
384 +
        self._fields_by_id = fields_by_id
385 +
        self._is_struct = is_struct
386 +
        self._min_align = min_align
387 +
        self._bytesize = bytesize
388 +
        self._attrs = attrs
389 +
        self._docs = docs
390 +
391 +
    @property
392 +
    def name(self):
393 +
        return self._name
394 +
395 +
    @property
396 +
    def fields(self):
397 +
        return self._fields
398 +
399 +
    @property
400 +
    def fields_by_id(self):
401 +
        return self._fields_by_id
402 +
403 +
    @property
404 +
    def is_struct(self):
405 +
        return self._is_struct
406 +
407 +
    @property
408 +
    def min_align(self):
409 +
        return self._min_align
410 +
411 +
    @property
412 +
    def bytesize(self):
413 +
        return self._bytesize
414 +
415 +
    @property
416 +
    def attrs(self):
417 +
        return self._attrs
418 +
419 +
    @property
420 +
    def docs(self):
421 +
        return self._docs
422 +
423 +
    def __str__(self):
424 +
        return '\n{}\n'.format(pprint.pformat(self.marshal()))
425 +
426 +
    def marshal(self):
427 +
        obj = {
428 +
            'name': self._name,
429 +
            'fields': {},
430 +
            'is_struct': self._is_struct,
431 +
            'min_align': self._min_align,
432 +
            'bytesize': self._bytesize,
433 +
            'attrs': {},
434 +
            'docs': self._docs,
435 +
        }
436 +
        if self._fields:
437 +
            for k, v in self._fields.items():
438 +
                obj['fields'][k] = v.marshal() if v else None
439 +
        if self._attrs:
440 +
            for k, v in self._attrs.items():
441 +
                obj['attrs'][k] = v
442 +
        return obj
443 +
444 +
    @staticmethod
445 +
    def parse(fbs_obj):
446 +
        obj_name = fbs_obj.Name()
447 +
        if obj_name:
448 +
            obj_name = obj_name.decode('utf8')
449 +
        obj_docs = parse_docs(fbs_obj)
450 +
        obj_attrs = parse_attr(fbs_obj)
451 +
        obj_fields, obj_fields_by_id = parse_fields(fbs_obj)
452 +
        obj = FbsObject(name=obj_name,
453 +
                        fields=obj_fields,
454 +
                        fields_by_id=obj_fields_by_id,
455 +
                        is_struct=fbs_obj.IsStruct(),
456 +
                        min_align=fbs_obj.Minalign(),
457 +
                        bytesize=fbs_obj.Bytesize(),
458 +
                        attrs=obj_attrs,
459 +
                        docs=obj_docs)
460 +
        return obj
461 +
462 +
463 +
class FbsRPCCall(object):
464 +
    def __init__(self,
465 +
                 name: str,
466 +
                 request: FbsObject,
467 +
                 response: FbsObject,
468 +
                 docs: str,
469 +
                 attrs: Dict[str, FbsAttribute]):
470 +
        self._name = name
471 +
        self._request = request
472 +
        self._response = response
473 +
        self._docs = docs
474 +
        self._attrs = attrs
475 +
476 +
    @property
477 +
    def name(self):
478 +
        return self._name
479 +
480 +
    @property
481 +
    def request(self):
482 +
        return self._request
483 +
484 +
    @property
485 +
    def response(self):
486 +
        return self._response
487 +
488 +
    @property
489 +
    def docs(self):
490 +
        return self._docs
491 +
492 +
    @property
493 +
    def attrs(self):
494 +
        return self._attrs
495 +
496 +
    def __str__(self):
497 +
        return '\n{}\n'.format(pprint.pformat(self.marshal()))
498 +
499 +
    def marshal(self):
500 +
        obj = {
501 +
            'name': self._name,
502 +
            'request': self._request.marshal() if self._request else None,
503 +
            'response': self._response.marshal() if self._response else None,
504 +
            'attrs': {},
505 +
            'docs': self._docs,
506 +
        }
507 +
        if self._attrs:
508 +
            for k, v in self._attrs.items():
509 +
                obj['attrs'][k] = v
510 +
        return obj
511 +
512 +
513 +
class FbsService(object):
514 +
    def __init__(self,
515 +
                 name: str,
516 +
                 calls: Dict[str, FbsRPCCall],
517 +
                 attrs: Dict[str, FbsAttribute],
518 +
                 docs: str):
519 +
        self._name = name
520 +
        self._calls = calls
521 +
        self._attrs = attrs
522 +
        self._docs = docs
523 +
524 +
    @property
525 +
    def name(self):
526 +
        return self._name
527 +
528 +
    @property
529 +
    def calls(self):
530 +
        return self._calls
531 +
532 +
    @property
533 +
    def attrs(self):
534 +
        return self._attrs
535 +
536 +
    @property
537 +
    def docs(self):
538 +
        return self._docs
539 +
540 +
    def __str__(self):
541 +
        return '\n{}\n'.format(pprint.pformat(self.marshal()))
542 +
543 +
    def marshal(self):
544 +
        obj = {
545 +
            'name': self._name,
546 +
            'calls': {},
547 +
            'attrs': {},
548 +
            'docs': self._docs,
549 +
        }
550 +
        if self._calls:
551 +
            for k, v in self._calls.items():
552 +
                obj['calls'][k] = v.marshal()
553 +
        if self._attrs:
554 +
            for k, v in self._attrs.items():
555 +
                obj['attrs'][k] = v
556 +
        return obj
557 +
558 +
559 +
class FbsEnumValue(object):
560 +
    def __init__(self, name, value, docs):
561 +
        self._name = name
562 +
        self._value = value
563 +
        self._attrs = {}
564 +
        self._docs = docs
565 +
566 +
    @property
567 +
    def name(self):
568 +
        return self._name
569 +
570 +
    @property
571 +
    def value(self):
572 +
        return self._value
573 +
574 +
    @property
575 +
    def attrs(self):
576 +
        return self._attrs
577 +
578 +
    @property
579 +
    def docs(self):
580 +
        return self._docs
581 +
582 +
    def __str__(self):
583 +
        return '\n{}\n'.format(pprint.pformat(self.marshal()))
584 +
585 +
    def marshal(self):
586 +
        obj = {
587 +
            'name': self._name,
588 +
            'attrs': self._attrs,
589 +
            'docs': self._docs,
590 +
            'value': self._value,
591 +
        }
592 +
        if self._attrs:
593 +
            for k, v in self._attrs.items():
594 +
                obj['attrs'][k] = v
595 +
        return obj
596 +
597 +
598 +
class FbsEnum(object):
599 +
    """
600 +
    FlatBuffers enum type.
601 +
    """
602 +
    def __init__(self,
603 +
                 name: str,
604 +
                 values: Dict[str, FbsEnumValue],
605 +
                 is_union: bool,
606 +
                 underlying_type: int,
607 +
                 attrs: Dict[str, FbsAttribute],
608 +
                 docs: str):
609 +
        self._name = name
610 +
        self._values = values
611 +
        self._is_union = is_union
612 +
613 +
        # zlmdb.flatbuffers.reflection.Type.Type
614 +
        self._underlying_type = underlying_type
615 +
        self._attrs = attrs
616 +
        self._docs = docs
617 +
618 +
    @property
619 +
    def name(self):
620 +
        return self._name
621 +
622 +
    @property
623 +
    def values(self):
624 +
        return self._values
625 +
626 +
    @property
627 +
    def is_union(self):
628 +
        return self._is_union
629 +
630 +
    @property
631 +
    def underlying_type(self):
632 +
        return self._underlying_type
633 +
634 +
    @property
635 +
    def attrs(self):
636 +
        return self._attrs
637 +
638 +
    @property
639 +
    def docs(self):
640 +
        return self._docs
641 +
642 +
    def __str__(self):
643 +
        return '\n{}\n'.format(pprint.pformat(self.marshal()))
644 +
645 +
    def marshal(self):
646 +
        obj = {
647 +
            'name': self._name,
648 +
            'values': {},
649 +
            'is_union': self._is_union,
650 +
            'underlying_type': FbsType.FBS2STR.get(self._underlying_type, None),
651 +
            'attrs': {},
652 +
            'docs': self._docs,
653 +
        }
654 +
        if self._values:
655 +
            for k, v in self._values.items():
656 +
                obj['values'][k] = v.marshal()
657 +
        if self._attrs:
658 +
            for k, v in self._attrs.items():
659 +
                obj['attrs'][k] = v
660 +
        return obj
661 +
662 +
663 +
class FbsSchema(object):
664 +
    """
665 +
    """
666 +
    def __init__(self,
667 +
                 file_name: str,
668 +
                 file_sha256: str,
669 +
                 file_size: int,
670 +
                 file_ident: str,
671 +
                 file_ext: str,
672 +
                 root_table: FbsObject,
673 +
                 root: _Schema,
674 +
                 objs: Dict[str, FbsObject],
675 +
                 enums: Dict[str, FbsEnum],
676 +
                 services: Dict[str, FbsService]):
677 +
        """
678 +
679 +
        :param file_name:
680 +
        :param file_sha256:
681 +
        :param file_size:
682 +
        :param file_ident:
683 +
        :param file_ext:
684 +
        :param root_table:
685 +
        :param root:
686 +
        :param objs:
687 +
        :param enums:
688 +
        :param services:
689 +
        """
690 +
        self._file_name = file_name
691 +
        self._file_sha256 = file_sha256
692 +
        self._file_size = file_size
693 +
        self._file_ident = file_ident
694 +
        self._file_ext = file_ext
695 +
        self._root_table = root_table
696 +
        self._root = root
697 +
        self._objs = objs
698 +
        self._enums = enums
699 +
        self._services = services
700 +
701 +
    @property
702 +
    def file_name(self):
703 +
        return self._file_name
704 +
705 +
    @property
706 +
    def file_sha256(self):
707 +
        return self._file_sha256
708 +
709 +
    @property
710 +
    def file_size(self):
711 +
        return self._file_size
712 +
713 +
    @property
714 +
    def file_ident(self):
715 +
        return self._file_ident
716 +
717 +
    @property
718 +
    def file_ext(self):
719 +
        return self._file_ext
720 +
721 +
    @property
722 +
    def root_table(self):
723 +
        return self._root_table
724 +
725 +
    @property
726 +
    def root(self):
727 +
        return self._root
728 +
729 +
    @property
730 +
    def objs(self):
731 +
        return self._objs
732 +
733 +
    @property
734 +
    def enums(self):
735 +
        return self._enums
736 +
737 +
    @property
738 +
    def services(self):
739 +
        return self._services
740 +
741 +
    def __str__(self):
742 +
        return '\n{}\n'.format(pprint.pformat(self.marshal(), width=255))
743 +
744 +
    def marshal(self) -> Dict[str, object]:
745 +
        """
746 +
747 +
        :return:
748 +
        """
749 +
        obj = {
750 +
            'schema': {
751 +
                'ident': self._file_ident,
752 +
                'ext': self._file_ext,
753 +
                'name': os.path.basename(self._file_name) if self._file_name else None,
754 +
                'sha256': self._file_sha256,
755 +
                'size': self._file_size,
756 +
                'objects': len(self._objs),
757 +
                'enums': len(self._enums),
758 +
                'services': len(self._services),
759 +
            },
760 +
            'root_table': self._root_table.marshal() if self._root_table else None,
761 +
            'enums': {},
762 +
            'objects': {},
763 +
            'services': {},
764 +
        }
765 +
        if self._enums:
766 +
            for k, v in self._enums.items():
767 +
                obj['enums'][k] = v.marshal()
768 +
        if self._objs:
769 +
            for k, v in self._objs.items():
770 +
                obj['objects'][k] = v.marshal()
771 +
        if self._services:
772 +
            for k, v in self._services.items():
773 +
                obj['services'][k] = v.marshal()
774 +
        return obj
775 +
776 +
    @staticmethod
777 +
    def load(filename) -> object:
778 +
        """
779 +
780 +
        :param filename:
781 +
        :return:
782 +
        """
783 +
        if not os.path.isfile(filename):
784 +
            raise RuntimeError('cannot open schema file {}'.format(filename))
785 +
        with open(filename, 'rb') as fd:
786 +
            data = fd.read()
787 +
788 +
        print('processing schema {} ({} bytes) ..'.format(filename, len(data)))
789 +
        root = _Schema.GetRootAsSchema(data, 0)
790 +
791 +
        file_ident = root.FileIdent()
792 +
        if file_ident is not None:
793 +
            file_ident = file_ident.decode('utf8')
794 +
795 +
        file_ext = root.FileExt()
796 +
        if file_ext is not None:
797 +
            file_ext = file_ext.decode('utf8')
798 +
799 +
        root_table = root.RootTable()
800 +
        if root_table is not None:
801 +
            root_table = FbsObject.parse(root_table)
802 +
803 +
        objs = {}
804 +
        services = {}
805 +
        enums = {}
806 +
807 +
        for i in range(root.EnumsLength()):
808 +
            fbs_enum = root.Enums(i)
809 +
810 +
            enum_name = fbs_enum.Name()
811 +
            if enum_name:
812 +
                enum_name = enum_name.decode('utf8')
813 +
814 +
            enum_underlying_type = fbs_enum.UnderlyingType()
815 +
816 +
            enum_values = {}
817 +
            for j in range(fbs_enum.ValuesLength()):
818 +
                fbs_enum_value = fbs_enum.Values(j)
819 +
                enum_value_name = fbs_enum_value.Name()
820 +
                if enum_value_name:
821 +
                    enum_value_name = enum_value_name.decode('utf8')
822 +
                enum_value_value = fbs_enum_value.Value()
823 +
                enum_value_docs = parse_docs(fbs_enum_value)
824 +
                enum_value = FbsEnumValue(name=enum_value_name, value=enum_value_value, docs=enum_value_docs)
825 +
                assert enum_value_name not in enum_values
826 +
                enum_values[enum_value_name] = enum_value
827 +
828 +
            enum = FbsEnum(name=enum_name,
829 +
                           values=enum_values,
830 +
                           is_union=fbs_enum.IsUnion(),
831 +
                           underlying_type=enum_underlying_type,
832 +
                           attrs=parse_attr(fbs_enum),
833 +
                           docs=parse_docs(fbs_enum))
834 +
            assert enum_name not in enums
835 +
            enums[enum_name] = enum
836 +
837 +
        for i in range(root.ObjectsLength()):
838 +
            fbs_obj = root.Objects(i)
839 +
            obj = FbsObject.parse(fbs_obj)
840 +
            assert obj.name not in objs
841 +
            objs[obj.name] = obj
842 +
843 +
        for i in range(root.ServicesLength()):
844 +
            svc_obj = root.Services(i)
845 +
846 +
            svc_name = svc_obj.Name()
847 +
            if svc_name:
848 +
                svc_name = svc_name.decode('utf8')
849 +
850 +
            calls = {}
851 +
            for j in range(svc_obj.CallsLength()):
852 +
                fbs_call = svc_obj.Calls(j)
853 +
854 +
                call_name = fbs_call.Name()
855 +
                if call_name:
856 +
                    call_name = call_name.decode('utf8')
857 +
858 +
                fbs_call_req = fbs_call.Request()
859 +
                call_req_name = fbs_call_req.Name()
860 +
                if call_req_name:
861 +
                    call_req_name = call_req_name.decode('utf8')
862 +
                call_req_is_struct = fbs_call_req.IsStruct()
863 +
                call_req_min_align = fbs_call_req.Minalign()
864 +
                call_req_bytesize = fbs_call_req.Bytesize()
865 +
                call_req_docs = parse_docs(fbs_call_req)
866 +
                call_req_attrs = parse_attr(fbs_call_req)
867 +
                call_req_fields, call_fields_by_id = parse_fields(fbs_call_req)
868 +
                call_req = FbsObject(name=call_req_name,
869 +
                                     fields=call_req_fields,
870 +
                                     fields_by_id=call_fields_by_id,
871 +
                                     is_struct=call_req_is_struct,
872 +
                                     min_align=call_req_min_align,
873 +
                                     bytesize=call_req_bytesize,
874 +
                                     attrs=call_req_attrs,
875 +
                                     docs=call_req_docs)
876 +
877 +
                fbs_call_resp = fbs_call.Response()
878 +
                call_resp_name = fbs_call_resp.Name()
879 +
                if call_resp_name:
880 +
                    call_resp_name = call_resp_name.decode('utf8')
881 +
                call_resp_is_struct = fbs_call_resp.IsStruct()
882 +
                call_resp_min_align = fbs_call_resp.Minalign()
883 +
                call_resp_bytesize = fbs_call_resp.Bytesize()
884 +
                call_resp_docs = parse_docs(fbs_call_resp)
885 +
                call_resp_attrs = parse_attr(fbs_call_resp)
886 +
                call_resp_fields, call_resp_fields_by_id = parse_fields(fbs_call_resp)
887 +
                call_resp = FbsObject(name=call_resp_name,
888 +
                                      fields=call_resp_fields,
889 +
                                      fields_by_id=call_resp_fields_by_id,
890 +
                                      is_struct=call_resp_is_struct,
891 +
                                      min_align=call_resp_min_align,
892 +
                                      bytesize=call_resp_bytesize,
893 +
                                      attrs=call_resp_attrs,
894 +
                                      docs=call_resp_docs)
895 +
896 +
                call_docs = parse_docs(fbs_call)
897 +
                call_attrs = parse_attr(fbs_call)
898 +
                call = FbsRPCCall(name=call_name,
899 +
                                  request=call_req,
900 +
                                  response=call_resp,
901 +
                                  docs=call_docs,
902 +
                                  attrs=call_attrs)
903 +
                assert call_name not in calls
904 +
                calls[call_name] = call
905 +
906 +
            docs = parse_docs(svc_obj)
907 +
            attrs = parse_attr(svc_obj)
908 +
            service = FbsService(name=svc_name, calls=calls, attrs=attrs, docs=docs)
909 +
            assert svc_name not in services
910 +
            services[svc_name] = service
911 +
912 +
        m = hashlib.sha256()
913 +
        m.update(data)
914 +
915 +
        schema = FbsSchema(file_name=filename,
916 +
                           file_size=len(data),
917 +
                           file_sha256=m.hexdigest(),
918 +
                           file_ident=file_ident,
919 +
                           file_ext=file_ext,
920 +
                           root_table=root_table,
921 +
                           root=root,
922 +
                           objs=objs,
923 +
                           enums=enums,
924 +
                           services=services)
925 +
        return schema
926 +
927 +
928 +
class FbsRepository(object):
929 +
    """
930 +
    """
931 +
932 +
    def __init__(self):
933 +
        self._schemata = {}
934 +
935 +
        # Dict[str, FbsObject]
936 +
        self._objs = {}
937 +
938 +
        # Dict[str, FbsEnum]
939 +
        self._enums = {}
940 +
941 +
        # Dict[str, FbsService]
942 +
        self._services = {}
943 +
944 +
    def summary(self, keys=False):
945 +
        if keys:
946 +
            return {
947 +
                'schemata': sorted(self._schemata.keys()),
948 +
                'objs': sorted(self._objs.keys()),
949 +
                'enums': sorted(self._enums.keys()),
950 +
                'services': sorted(self._services.keys()),
951 +
            }
952 +
        else:
953 +
            return {
954 +
                'schemata': len(self._schemata),
955 +
                'objs': len(self._objs),
956 +
                'enums': len(self._enums),
957 +
                'services': len(self._services),
958 +
            }
959 +
960 +
    @property
961 +
    def objs(self):
962 +
        return self._objs
963 +
964 +
    @property
965 +
    def enums(self):
966 +
        return self._enums
967 +
968 +
    @property
969 +
    def services(self):
970 +
        return self._services
971 +
972 +
    def load(self, dirname) -> object:
973 +
        if not os.path.isdir(dirname):
974 +
            raise RuntimeError('cannot open schema directory {}'.format(dirname))
975 +
976 +
        found = []
977 +
        for path in Path(dirname).rglob('*.bfbs'):
978 +
            fn = os.path.abspath(os.path.join(dirname, path.name))
979 +
            if fn not in self._schemata:
980 +
                found.append(fn)
981 +
            else:
982 +
                print('duplicate schema: {} already loaded'.format(fn))
983 +
984 +
        for fn in found:
985 +
            schema = FbsSchema.load(fn)
986 +
987 +
            # load enum types
988 +
            for enum in schema.enums.values():
989 +
                if enum.name in self._enums:
990 +
                    print('duplicate enum for name "{}"'.format(enum.name))
991 +
                else:
992 +
                    self._enums[enum.name] = enum
993 +
994 +
            # load object types
995 +
            for obj in schema.objs.values():
996 +
                if obj.name in self._objs:
997 +
                    print('duplicate object for name "{}"'.format(obj.name))
998 +
                else:
999 +
                    self._objs[obj.name] = obj
1000 +
1001 +
            # load service definitions ("APIs")
1002 +
            for svc in schema.services.values():
1003 +
                if svc.name in self._services:
1004 +
                    print('duplicate service for name "{}"'.format(svc.name))
1005 +
                else:
1006 +
                    self._services[svc.name] = svc
1007 +
1008 +
            self._schemata[fn] = schema

@@ -24,4 +24,4 @@
Loading
24 24
#
25 25
###############################################################################
26 26
27 -
__version__ = '20.7.1'
27 +
__version__ = '20.12.1'

@@ -59,6 +59,9 @@
Loading
59 59
60 60
    from autobahn.xbr._config import load_or_create_profile, UserConfig, Profile  # noqa
61 61
62 +
    from autobahn.xbr._schema import FbsSchema, FbsObject, FbsType, FbsRPCCall, FbsEnum, FbsService, FbsEnumValue, \
63 +
        FbsAttribute, FbsField, FbsRepository  # noqa
64 +
62 65
    HAS_XBR = True
63 66
64 67
    if not hasattr(abi, 'collapse_type'):
@@ -332,6 +335,17 @@
Loading
332 335
        'IConsumer',
333 336
        'ISeller',
334 337
        'IBuyer',
338 +
339 +
        'FbsSchema',
340 +
        'FbsService',
341 +
        'FbsType',
342 +
        'FbsObject',
343 +
        'FbsEnum',
344 +
        'FbsEnumValue',
345 +
        'FbsRPCCall',
346 +
        'FbsAttribute',
347 +
        'FbsField',
348 +
        'FbsRepository',
335 349
    )
336 350
337 351
except (ImportError, FileNotFoundError) as e:

@@ -33,7 +33,6 @@
Loading
33 33
import web3
34 34
from eth_utils.conversions import hexstr_if_str, to_hex
35 35
36 -
from txaio import make_logger
37 36
from autobahn.websocket.util import parse_url
38 37
from autobahn.xbr._util import hlval, hltype
39 38
@@ -59,8 +58,6 @@
Loading
59 58
60 59
class Profile(object):
61 60
62 -
    log = make_logger()
63 -
64 61
    def __init__(self,
65 62
                 path=None,
66 63
                 name=None,
@@ -72,6 +69,8 @@
Loading
72 69
                 infura_network=None,
73 70
                 infura_key=None,
74 71
                 infura_secret=None):
72 +
        from txaio import make_logger
73 +
        self.log = make_logger()
75 74
        self.path = path
76 75
        self.name = name
77 76
        self.ethkey = ethkey
@@ -119,9 +118,10 @@
Loading
119 118
120 119
class UserConfig(object):
121 120
122 -
    log = make_logger()
123 -
124 121
    def __init__(self, config_path):
122 +
        from txaio import make_logger
123 +
        self.log = make_logger()
124 +
125 125
        self._config_path = os.path.abspath(config_path)
126 126
127 127
        config = configparser.ConfigParser()
Files Coverage
autobahn 56.74%
Project Totals (72 files) 56.74%
Untitled

No yaml found.

Create your codecov.yml to customize your Codecov experience

Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading