diff --git a/setup.py b/setup.py index efd4bdfc6..00fa84d36 100755 --- a/setup.py +++ b/setup.py @@ -29,7 +29,6 @@ setup( 'trezorlib.debuglink', 'trezorlib.mapping', 'trezorlib.messages_pb2', - 'trezorlib.protobuf_json', 'trezorlib.qt.pinmatrix', 'trezorlib.tools', 'trezorlib.transport', diff --git a/tests/unit_tests/test_protobuf_json.py b/tests/unit_tests/test_protobuf_json.py deleted file mode 100644 index b382ec21b..000000000 --- a/tests/unit_tests/test_protobuf_json.py +++ /dev/null @@ -1,36 +0,0 @@ -# This file is part of the TREZOR project. -# -# Copyright (C) 2012-2016 Marek Palatinus -# Copyright (C) 2012-2016 Pavol Rusnak -# -# This library is free software: you can redistribute it and/or modify -# it under the terms of the GNU Lesser General Public License as published by -# the Free Software Foundation, either version 3 of the License, or -# (at your option) any later version. -# -# This library is distributed in the hope that it will be useful, -# but WITHOUT ANY WARRANTY; without even the implied warranty of -# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -# GNU Lesser General Public License for more details. -# -# You should have received a copy of the GNU Lesser General Public License -# along with this library. If not, see . - -import common -import unittest - -from trezorlib.protobuf_json import pb2json -import trezorlib.messages_pb2 as msg - - -class TestProtobufJson(unittest.TestCase): - - def test_pb2json(self): - m = msg.Features() - m.device_id = '1234' - j = pb2json(m) - self.assertEqual(j, {'device_id': u'1234'}) - - -if __name__ == '__main__': - unittest.main() diff --git a/trezorctl b/trezorctl index b81505b9a..d72fab44b 100755 --- a/trezorctl +++ b/trezorctl @@ -24,7 +24,6 @@ import json import base64 import click -from trezorlib import protobuf_json from trezorlib.client import TrezorClient, TrezorClientVerbose, CallException import trezorlib.types_pb2 as types @@ -77,7 +76,8 @@ def cli(ctx, transport, path, verbose, is_json): def print_result(res, transport, path, verbose, is_json): if is_json: if hasattr(res, '__module__') and res.__module__ == 'messages_pb2': - click.echo(protobuf_json.pb2json(res)) + from google.protobuf import json_format + click.echo(json_format.MessageToJson(res, preserving_proto_field_name=True)) else: click.echo(json.dumps(res, sort_keys=True, indent=4)) else: @@ -101,7 +101,11 @@ def print_result(res, transport, path, verbose, is_json): def ls(transport_name): transport_class = get_transport_class_by_name(transport_name) devices = transport_class.enumerate() - return [d[0] for d in devices] + if transport_name == 'usb': + return [dev[0] for dev in devices] + if transport_name == 'bridge': + return devices + return [] # diff --git a/trezorlib/client.py b/trezorlib/client.py index d968d25a5..5e272e863 100644 --- a/trezorlib/client.py +++ b/trezorlib/client.py @@ -93,7 +93,7 @@ def pprint(msg): """ msg_ser = msg.SerializeToString() msg_id = mapping.get_type(msg) - msg_json = json.dumps(protobuf_json.pb2json(msg)) + msg_json = json_format.MessageToDict(msg, preserving_proto_field_name=True) """ if isinstance(msg, proto.FirmwareUpload): return "<%s> (%d bytes):\n" % (msg_class, msg_size) diff --git a/trezorlib/protobuf_json.py b/trezorlib/protobuf_json.py deleted file mode 100644 index ccc0d6a37..000000000 --- a/trezorlib/protobuf_json.py +++ /dev/null @@ -1,163 +0,0 @@ -# JSON serialization support for Google's protobuf Messages -# Copyright (c) 2009, Paul Dovbush -# All rights reserved. -# http://code.google.com/p/protobuf-json/ -# -# Redistribution and use in source and binary forms, with or without -# modification, are permitted provided that the following conditions are -# met: -# -# * Redistributions of source code must retain the above copyright -# notice, this list of conditions and the following disclaimer. -# * Redistributions in binary form must reproduce the above -# copyright notice, this list of conditions and the following disclaimer -# in the documentation and/or other materials provided with the -# distribution. -# * Neither the name of nor the names of its -# contributors may be used to endorse or promote products derived from -# this software without specific prior written permission. -# -# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR -# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT -# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, -# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT -# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, -# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY -# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT -# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE -# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - -''' -Provide serialization and de-serialization of Google's protobuf Messages into/from JSON format. -''' - -# groups are deprecated and not supported; -# Note that preservation of unknown fields is currently not available for Python (c) google docs -# extensions is not supported from 0.0.5 (due to gpb2.3 changes) - -__version__ = '0.0.6' -__author__ = 'Paul Dovbush ' - - -from google.protobuf.descriptor import FieldDescriptor as FD -from functools import partial - - -class ParseError(Exception): - pass - - -def json2pb(pb, js, useFieldNumber=False): - ''' convert JSON string to google.protobuf.descriptor instance ''' - for field in pb.DESCRIPTOR.fields: - if useFieldNumber: - key = field.number - else: - key = field.name - if key not in js: - continue - if field.type == FD.TYPE_MESSAGE: - pass - elif field.type in _js2ftype: - ftype = _js2ftype[field.type] - else: - raise ParseError("Field %s.%s of type '%d' is not supported" % (pb.__class__.__name__, field.name, field.type, )) - value = js[key] - if field.label == FD.LABEL_REPEATED: - pb_value = getattr(pb, field.name, None) - for v in value: - if field.type == FD.TYPE_MESSAGE: - json2pb(pb_value.add(), v, useFieldNumber=useFieldNumber) - else: - pb_value.append(ftype(v)) - else: - if field.type == FD.TYPE_MESSAGE: - json2pb(getattr(pb, field.name, None), value, useFieldNumber=useFieldNumber) - else: - setattr(pb, field.name, ftype(value)) - return pb - - -def pb2json(pb, useFieldNumber=False): - ''' convert google.protobuf.descriptor instance to JSON string ''' - js = {} - # fields = pb.DESCRIPTOR.fields # all fields - fields = pb.ListFields() # only filled (including extensions) - for field, value in fields: - if useFieldNumber: - key = field.number - else: - key = field.name - if field.type == FD.TYPE_MESSAGE: - ftype = partial(pb2json, useFieldNumber=useFieldNumber) - # ---- monkey patching ---- - elif field.type == FD.TYPE_ENUM: - def ftype(x): - return field.enum_type.values[x].name - # ---- end of monkey patching ---- - elif field.type in _ftype2js: - ftype = _ftype2js[field.type] - else: - raise ParseError("Field %s.%s of type '%d' is not supported" % (pb.__class__.__name__, field.name, field.type, )) - if field.label == FD.LABEL_REPEATED: - js_value = [] - for v in value: - js_value.append(ftype(v)) - else: - js_value = ftype(value) - js[key] = js_value - return js - - -_ftype2js = { - FD.TYPE_DOUBLE: float, - FD.TYPE_FLOAT: float, - FD.TYPE_INT64: int, - FD.TYPE_UINT64: int, - FD.TYPE_INT32: int, - FD.TYPE_FIXED64: float, - FD.TYPE_FIXED32: float, - FD.TYPE_BOOL: bool, - FD.TYPE_STRING: str, - # FD.TYPE_MESSAGE: pb2json, #handled specially - FD.TYPE_BYTES: lambda x: x.encode('string_escape'), - FD.TYPE_UINT32: int, - FD.TYPE_ENUM: int, - FD.TYPE_SFIXED32: float, - FD.TYPE_SFIXED64: float, - FD.TYPE_SINT32: int, - FD.TYPE_SINT64: int, -} - -_js2ftype = { - FD.TYPE_DOUBLE: float, - FD.TYPE_FLOAT: float, - FD.TYPE_INT64: int, - FD.TYPE_UINT64: int, - FD.TYPE_INT32: int, - FD.TYPE_FIXED64: float, - FD.TYPE_FIXED32: float, - FD.TYPE_BOOL: bool, - FD.TYPE_STRING: str, - # FD.TYPE_MESSAGE: json2pb, # handled specially - FD.TYPE_BYTES: lambda x: x.decode('string_escape'), - FD.TYPE_UINT32: int, - FD.TYPE_ENUM: int, - FD.TYPE_SFIXED32: float, - FD.TYPE_SFIXED64: float, - FD.TYPE_SINT32: int, - FD.TYPE_SINT64: int, -} - -# more monkey patching - -import binascii -from . import types_pb2 as types - -_ftype2js[FD.TYPE_BYTES] = lambda x: binascii.hexlify(x) -del _ftype2js[FD.TYPE_ENUM] # handled specially - -_js2ftype[FD.TYPE_BYTES] = lambda x: binascii.unhexlify(x) -_js2ftype[FD.TYPE_ENUM] = lambda x: getattr(types, x) diff --git a/trezorlib/transport_bridge.py b/trezorlib/transport_bridge.py index 6c4a1dadb..0413281d2 100644 --- a/trezorlib/transport_bridge.py +++ b/trezorlib/transport_bridge.py @@ -22,7 +22,7 @@ import binascii import json import requests -from . import protobuf_json +from google.protobuf import json_format from . import messages_pb2 as proto from .transport import TransportV1 @@ -109,8 +109,8 @@ class BridgeTransport(TransportV1): # Override main 'write' method, HTTP transport cannot be # splitted to chunks cls = protobuf_msg.__class__.__name__ - msg = protobuf_json.pb2json(protobuf_msg) - payload = '{"type": "%s", "message": %s}' % (cls, json.dumps(msg)) + msg = json_format.MessageToJson(protobuf_msg, preserving_proto_field_name=True) + payload = '{"type": "%s", "message": %s}' % (cls, msg) r = self.conn.post(TREZORD_HOST + '/call/%s' % self.session, data=payload) if r.status_code != 200: raise Exception('trezord: Could not write message' + get_error(r)) @@ -122,5 +122,5 @@ class BridgeTransport(TransportV1): raise Exception('No response stored') cls = getattr(proto, self.response['type']) inst = cls() - pb = protobuf_json.json2pb(inst, self.response['message']) + pb = json_format.ParseDict(self.response['message'], inst) return (0, 'protobuf', pb)