Hello community,

here is the log from the commit of package python-thriftpy2 for 
openSUSE:Factory checked in at 2019-10-08 19:59:30
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-thriftpy2 (Old)
 and      /work/SRC/openSUSE:Factory/.python-thriftpy2.new.2352 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-thriftpy2"

Tue Oct  8 19:59:30 2019 rev:2 rq:736036 version:0.4.7

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-thriftpy2/python-thriftpy2.changes        
2019-09-27 14:50:38.872421607 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-thriftpy2.new.2352/python-thriftpy2.changes  
    2019-10-08 19:59:32.783907099 +0200
@@ -1,0 +2,6 @@
+Tue Oct  8 09:06:54 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 0.4.7:
+  * minor bugfixes
+
+-------------------------------------------------------------------

Old:
----
  v0.4.5.tar.gz

New:
----
  v0.4.7.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-thriftpy2.spec ++++++
--- /var/tmp/diff_new_pack.WZSNnr/_old  2019-10-08 19:59:33.335905446 +0200
+++ /var/tmp/diff_new_pack.WZSNnr/_new  2019-10-08 19:59:33.339905434 +0200
@@ -18,7 +18,7 @@
 
 %{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-thriftpy2
-Version:        0.4.5
+Version:        0.4.7
 Release:        0
 Summary:        Pure python implementation of Apache Thrift
 License:        MIT

++++++ v0.4.5.tar.gz -> v0.4.7.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/.travis.yml 
new/thriftpy2-0.4.7/.travis.yml
--- old/thriftpy2-0.4.5/.travis.yml     2019-08-27 04:41:07.000000000 +0200
+++ new/thriftpy2-0.4.7/.travis.yml     2019-10-04 12:07:51.000000000 +0200
@@ -1,4 +1,3 @@
-sudo: false
 language: python
 
 python:
@@ -14,12 +13,8 @@
       script: tox -e flake8
     - python: 3.6
       script: tox -e coverage
-    # This is a workaround to make 3.7 running in travis-ci
-    # See https://github.com/travis-ci/travis-ci/issues/9815
     - python: 3.7
       script: tox -e py37
-      dist: xenial
-      sudo: true
 
 before_install:
   - sudo apt-get install -y python-dev gcc
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/CHANGES.rst 
new/thriftpy2-0.4.7/CHANGES.rst
--- old/thriftpy2-0.4.5/CHANGES.rst     2019-08-27 04:41:07.000000000 +0200
+++ new/thriftpy2-0.4.7/CHANGES.rst     2019-10-04 12:07:51.000000000 +0200
@@ -3,6 +3,35 @@
 
 0.4.x
 ~~~~~
+Version 0.4.7
+-------------
+
+Released on October 4, 2019.
+
+- Fix loading remote IDL file failed on Python 3, via `2-#88`_.
+
+.. _2-#88: https://github.com/Thriftpy/thriftpy2/pull/88
+
+
+Version 0.4.6
+-------------
+
+Released on September 24, 2019.
+
+- Follow strict datatype in TJsonProtocol, via `2-#85`_.
+- Add timeout support to asyncio contrib, via `2-#84`_.
+- Enable socket_timeout on unix_socket, via `2-#83`_.
+- Add url support as optional argument to make_client, via `2-#80`_.
+- Enforce required arguments, fixes #72, via `2-#81`_.
+
+.. _2-#80: https://github.com/Thriftpy/thriftpy2/pull/80
+.. _2-#81: https://github.com/Thriftpy/thriftpy2/pull/81
+.. _2-#83: https://github.com/Thriftpy/thriftpy2/pull/83
+.. _2-#84: https://github.com/Thriftpy/thriftpy2/pull/84
+.. _2-#85: https://github.com/Thriftpy/thriftpy2/pull/85
+
+
+
 Version 0.4.5
 -------------
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/tests/addressbook.thrift 
new/thriftpy2-0.4.7/tests/addressbook.thrift
--- old/thriftpy2-0.4.5/tests/addressbook.thrift        2019-08-27 
04:41:07.000000000 +0200
+++ new/thriftpy2-0.4.7/tests/addressbook.thrift        2019-10-04 
12:07:51.000000000 +0200
@@ -34,7 +34,7 @@
 
 service AddressBookService {
     void ping();
-    string hello(1: string name);
+    string hello(1: required string name);
     bool add(1: Person person);
     bool remove(1: string name) throws (1: PersonNotExistsError not_exists);
     Person get(1: string name) throws (1: PersonNotExistsError not_exists);
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/tests/test_aio.py 
new/thriftpy2-0.4.7/tests/test_aio.py
--- old/thriftpy2-0.4.5/tests/test_aio.py       2019-08-27 04:41:07.000000000 
+0200
+++ new/thriftpy2-0.4.7/tests/test_aio.py       2019-10-04 12:07:51.000000000 
+0200
@@ -16,6 +16,7 @@
 
 from thriftpy2.rpc import make_aio_server, make_aio_client  # noqa
 from thriftpy2.transport import TTransportException  # noqa
+from thriftpy2.thrift import TApplicationException  # noqa
 
 addressbook = thriftpy2.load(os.path.join(os.path.dirname(__file__),
                                           "addressbook.thrift"))
@@ -143,6 +144,25 @@
         keyfile="ssl/client.key")
 
 
+async def ssl_client_with_url(timeout=3000):
+    return await make_aio_client(
+        addressbook.AddressBookService,
+        url="thrift://localhost:{port}".format(port=SSL_PORT),
+        socket_timeout=timeout,
+        cafile="ssl/CA.pem", certfile="ssl/client.crt",
+        keyfile="ssl/client.key"
+    )
+
+
[email protected]
+async def test_clients(aio_ssl_server):
+    c1 = await ssl_client()
+    c2 = await ssl_client_with_url()
+    assert await c1.hello("world") == await c2.hello("world")
+    c1.close()
+    c2.close()
+
+
 @pytest.mark.asyncio
 async def test_void_api(aio_server):
     c = await client()
@@ -164,6 +184,16 @@
     c.close()
 
 
[email protected]
+async def test_required_argument(aio_server):
+    c = await client()
+    assert await c.hello("") == "hello "
+
+    with pytest.raises(TApplicationException):
+        await c.hello()
+    c.close()
+
+
 @pytest.mark.asyncio
 async def test_string_api_with_ssl(aio_ssl_server):
     c = await client()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/tests/test_framed_transport.py 
new/thriftpy2-0.4.7/tests/test_framed_transport.py
--- old/thriftpy2-0.4.5/tests/test_framed_transport.py  2019-08-27 
04:41:07.000000000 +0200
+++ new/thriftpy2-0.4.7/tests/test_framed_transport.py  2019-10-04 
12:07:51.000000000 +0200
@@ -87,15 +87,31 @@
                            proto_factory=self.PROTOCOL_FACTORY,
                            trans_factory=self.TRANSPORT_FACTORY)
 
+    def mk_client_with_url(self):
+        return make_client(addressbook.AddressBookService,
+                           proto_factory=self.PROTOCOL_FACTORY,
+                           trans_factory=self.TRANSPORT_FACTORY,
+                           url='thrift://127.0.0.1:{port}'.format(
+                               port=self.port))
+
     def setUp(self):
         self.mk_server()
         time.sleep(0.1)
         self.client = self.mk_client()
+        self.client_created_using_url = self.mk_client_with_url()
 
     def tearDown(self):
         self.io_loop.stop()
 
     @pytest.mark.skipif(sys.version_info[:2] == (2, 6), reason="not support")
+    def test_make_client(self):
+        linus = addressbook.Person('Linus Torvalds')
+        success = self.client_created_using_url.add(linus)
+        assert success
+        success = self.client.add(linus)
+        assert not success
+
+    @pytest.mark.skipif(sys.version_info[:2] == (2, 6), reason="not support")
     def test_able_to_communicate(self):
         dennis = addressbook.Person(name='Dennis Ritchie')
         success = self.client.add(dennis)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/tests/test_http.py 
new/thriftpy2-0.4.7/tests/test_http.py
--- old/thriftpy2-0.4.5/tests/test_http.py      2019-08-27 04:41:07.000000000 
+0200
+++ new/thriftpy2-0.4.7/tests/test_http.py      2019-10-04 12:07:51.000000000 
+0200
@@ -12,7 +12,8 @@
 import thriftpy2
 thriftpy2.install_import_hook()  # noqa
 
-from thriftpy2.http import make_server, client_context
+from thriftpy2.http import make_server, make_client, client_context  # noqa
+from thriftpy2.thrift import TApplicationException
 
 
 addressbook = thriftpy2.load(os.path.join(os.path.dirname(__file__),
@@ -105,6 +106,28 @@
                           host="127.0.0.1", port=6080, timeout=timeout)
 
 
+def client_context_with_url(timeout=3000):
+    return client_context(addressbook.AddressBookService,
+                          url="http://127.0.0.1:6080";, timeout=timeout)
+
+
+def client_with_url(timeout=3000):
+    return make_client(addressbook.AddressBookService,
+                       url="http://127.0.0.1:6080";, timeout=timeout)
+
+
+def test_client_context(server):
+    with client() as c1, client_context_with_url() as c2:
+        assert c1.hello("world") == c2.hello("world")
+
+
+def test_clients(server):
+    with client() as c1:
+        c2 = client_with_url()
+        assert c1.hello("world") == c2.hello("world")
+        c2.close()
+
+
 def test_void_api(server):
     with client() as c:
         assert c.ping() is None
@@ -115,6 +138,14 @@
         assert c.hello("world") == "hello world"
 
 
+def test_required_argument(server):
+    with client() as c:
+        with pytest.raises(TApplicationException):
+            c.hello()
+
+        assert c.hello(name="") == "hello "
+
+
 def test_huge_res(server):
     with client() as c:
         big_str = "world" * 100000
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/tests/test_rpc.py 
new/thriftpy2-0.4.7/tests/test_rpc.py
--- old/thriftpy2-0.4.5/tests/test_rpc.py       2019-08-27 04:41:07.000000000 
+0200
+++ new/thriftpy2-0.4.7/tests/test_rpc.py       2019-10-04 12:07:51.000000000 
+0200
@@ -17,6 +17,7 @@
 from thriftpy2._compat import PY3  # noqa
 from thriftpy2.rpc import make_server, client_context  # noqa
 from thriftpy2.transport import TTransportException  # noqa
+from thriftpy2.thrift import TApplicationException  # noqa
 
 
 addressbook = thriftpy2.load(os.path.join(os.path.dirname(__file__),
@@ -143,6 +144,19 @@
                           keyfile="ssl/client.key")
 
 
+def ssl_client_with_url(timeout=3000):
+    return client_context(addressbook.AddressBookService,
+                          url="thrift://localhost:{port}".format(
+                              port=SSL_PORT),
+                          timeout=timeout, cafile="ssl/CA.pem",
+                          certfile="ssl/client.crt", keyfile="ssl/client.key")
+
+
+def test_clients(ssl_server):
+    with ssl_client() as c1, ssl_client_with_url() as c2:
+        assert c1.hello("world") == c2.hello("world")
+
+
 def test_void_api(server):
     with client() as c:
         assert c.ping() is None
@@ -158,6 +172,13 @@
         assert c.hello("world") == "hello world"
 
 
+def test_required_argument(server):
+    with client() as c:
+        assert c.hello("") == "hello "
+        with pytest.raises(TApplicationException):
+            c.hello()
+
+
 def test_string_api_with_ssl(ssl_server):
     with ssl_client() as c:
         assert c.hello("world") == "hello world"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/tests/test_tornado.py 
new/thriftpy2-0.4.7/tests/test_tornado.py
--- old/thriftpy2-0.4.5/tests/test_tornado.py   2019-08-27 04:41:07.000000000 
+0200
+++ new/thriftpy2-0.4.7/tests/test_tornado.py   2019-10-04 12:07:51.000000000 
+0200
@@ -77,18 +77,35 @@
         return make_client(addressbook.AddressBookService,
                            '127.0.0.1', self.port, io_loop=self.io_loop)
 
+    def mk_client_with_url(self):
+        return make_client(addressbook.AddressBookService,
+                           io_loop=self.io_loop,
+                           url='thrift://127.0.0.1:{port}'.format(
+                               port=self.port))
+
     def setUp(self):
         super(TornadoRPCTestCase, self).setUp()
         self.server = self.mk_server()
         self.client = self.io_loop.run_sync(self.mk_client)
+        self.client_with_url = self.io_loop.run_sync(self.mk_client_with_url)
 
     def tearDown(self):
         self.server.stop()
         self.client.close()
+        self.client_with_url.close()
         super(TornadoRPCTestCase, self).tearDown()
 
     @testing.gen_test
     @pytest.mark.skipif(sys.version_info[:2] == (2, 6), reason="not support")
+    def test_make_client(self):
+        linus = addressbook.Person(name='Linus Torvalds')
+        success = yield self.client_with_url.add(linus)
+        assert success
+        success = yield self.client.add(linus)
+        assert not success
+
+    @testing.gen_test
+    @pytest.mark.skipif(sys.version_info[:2] == (2, 6), reason="not support")
     def test_synchronous_result(self):
         dennis = addressbook.Person(name='Dennis Ritchie')
         success = yield self.client.add(dennis)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/thriftpy2/__init__.py 
new/thriftpy2-0.4.7/thriftpy2/__init__.py
--- old/thriftpy2-0.4.5/thriftpy2/__init__.py   2019-08-27 04:41:07.000000000 
+0200
+++ new/thriftpy2-0.4.7/thriftpy2/__init__.py   2019-10-04 12:07:51.000000000 
+0200
@@ -5,7 +5,7 @@
 from .hook import install_import_hook, remove_import_hook
 from .parser import load, load_module, load_fp
 
-__version__ = '0.4.5'
+__version__ = '0.4.7'
 __python__ = sys.version_info
 __all__ = ["install_import_hook", "remove_import_hook", "load", "load_module",
            "load_fp"]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/thriftpy2/contrib/aio/client.py 
new/thriftpy2-0.4.7/thriftpy2/contrib/aio/client.py
--- old/thriftpy2-0.4.5/thriftpy2/contrib/aio/client.py 2019-08-27 
04:41:07.000000000 +0200
+++ new/thriftpy2-0.4.7/thriftpy2/contrib/aio/client.py 2019-10-04 
12:07:51.000000000 +0200
@@ -1,7 +1,7 @@
 # -*- coding: utf-8 -*-
 import asyncio
 import functools
-from thriftpy2.thrift import args2kwargs
+from thriftpy2.thrift import args_to_kwargs
 from thriftpy2.thrift import TApplicationException, TMessageType
 
 
@@ -26,9 +26,14 @@
 
     @asyncio.coroutine
     def _req(self, _api, *args, **kwargs):
-        _kw = args2kwargs(getattr(self._service, _api + "_args").thrift_spec,
-                          *args)
-        kwargs.update(_kw)
+        try:
+            kwargs = args_to_kwargs(getattr(self._service, _api + 
"_args").thrift_spec,
+                          *args, **kwargs)
+        except ValueError as e:
+            raise TApplicationException(
+                    TApplicationException.UNKNOWN_METHOD,
+                    'missing required argument {arg} for 
{service}.{api}'.format(
+                        arg=e.args[0], service=self._service.__name__, 
api=_api))
         result_cls = getattr(self._service, _api + "_result")
 
         yield from self._send(_api, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/thriftpy2/contrib/aio/rpc.py 
new/thriftpy2-0.4.7/thriftpy2/contrib/aio/rpc.py
--- old/thriftpy2-0.4.5/thriftpy2/contrib/aio/rpc.py    2019-08-27 
04:41:07.000000000 +0200
+++ new/thriftpy2-0.4.7/thriftpy2/contrib/aio/rpc.py    2019-10-04 
12:07:51.000000000 +0200
@@ -1,6 +1,15 @@
 # -*- coding: utf-8 -*-import warnings
 import asyncio
 import warnings
+
+from thriftpy2._compat import PY3
+if PY3:
+    import urllib
+else:
+    import urllib2 as urllib
+    import urlparse
+    urllib.parse = urlparse
+
 from .processor import TAsyncProcessor
 from .client import TAsyncClient
 from .protocol.binary import TAsyncBinaryProtocolFactory
@@ -9,16 +18,23 @@
 from .server import TAsyncServer
 
 
+
 @asyncio.coroutine
-def make_client(service, host="localhost", port=9090, unix_socket=None,
+def make_client(service, host='localhost', port=9090, unix_socket=None,
                 proto_factory=TAsyncBinaryProtocolFactory(),
                 trans_factory=TAsyncBufferedTransportFactory(),
                 socket_timeout=3000, connect_timeout=None,
                 cafile=None, ssl_context=None,
                 certfile=None, keyfile=None,
-                validate=True):
+                validate=True, url=''):
+    if url:
+        parsed_url = urllib.parse.urlparse(url)
+        host = parsed_url.hostname or host
+        port = parsed_url.port or port
     if unix_socket:
-        socket = TAsyncSocket(unix_socket=unix_socket)
+        socket = TAsyncSocket(unix_socket=unix_socket,
+                              connect_timeout=connect_timeout,
+                              socket_timeout=socket_timeout)
         if certfile:
             warnings.warn("SSL only works with host:port, not unix_socket.")
     elif host and port:
@@ -28,7 +44,7 @@
                 cafile=cafile, ssl_context=ssl_context,
                 certfile=certfile, keyfile=keyfile, validate=validate)
     else:
-        raise ValueError("Either host/port or unix_socket must be provided.")
+        raise ValueError("Either host/port or unix_socket or url must be 
provided.")
 
     transport = trans_factory.get_transport(socket)
     protocol = proto_factory.get_protocol(transport)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/thriftpy2/http.py 
new/thriftpy2-0.4.7/thriftpy2/http.py
--- old/thriftpy2-0.4.5/thriftpy2/http.py       2019-08-27 04:41:07.000000000 
+0200
+++ new/thriftpy2-0.4.7/thriftpy2/http.py       2019-10-04 12:07:51.000000000 
+0200
@@ -280,11 +280,17 @@
         flush = __with_timeout(flush)
 
 
-def make_client(service, host, port, path='', scheme='http',
+def make_client(service, host='localhost', port=9090, path='', scheme='http',
                 proto_factory=TBinaryProtocolFactory(),
                 trans_factory=TBufferedTransportFactory(),
                 ssl_context_factory=None,
-                timeout=DEFAULT_HTTP_CLIENT_TIMEOUT_MS):
+                timeout=DEFAULT_HTTP_CLIENT_TIMEOUT_MS, url=''):
+    if url:
+        parsed_url = urllib.parse.urlparse(url)
+        host = parsed_url.hostname or host
+        port = parsed_url.port or port
+        scheme = parsed_url.scheme or scheme
+        path = parsed_url.path or path
     uri = HTTP_URI.format(scheme=scheme, host=host, port=port, path=path)
     http_socket = THttpClient(uri, timeout, ssl_context_factory)
     transport = trans_factory.get_transport(http_socket)
@@ -294,11 +300,17 @@
 
 
 @contextmanager
-def client_context(service, host, port, path='', scheme='http',
+def client_context(service, host='localhost', port=9090, path='', 
scheme='http',
                    proto_factory=TBinaryProtocolFactory(),
                    trans_factory=TBufferedTransportFactory(),
                    ssl_context_factory=None,
-                   timeout=DEFAULT_HTTP_CLIENT_TIMEOUT_MS):
+                   timeout=DEFAULT_HTTP_CLIENT_TIMEOUT_MS, url=''):
+    if url:
+        parsed_url = urllib.parse.urlparse(url)
+        host = parsed_url.hostname or host
+        port = parsed_url.port or port
+        scheme = parsed_url.scheme or scheme
+        path = parsed_url.path or path
     uri = HTTP_URI.format(scheme=scheme, host=host, port=port, path=path)
     http_socket = THttpClient(uri, timeout, ssl_context_factory)
     transport = trans_factory.get_transport(http_socket)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/thriftpy2/parser/__init__.py 
new/thriftpy2-0.4.7/thriftpy2/parser/__init__.py
--- old/thriftpy2-0.4.5/thriftpy2/parser/__init__.py    2019-08-27 
04:41:07.000000000 +0200
+++ new/thriftpy2-0.4.7/thriftpy2/parser/__init__.py    2019-10-04 
12:07:51.000000000 +0200
@@ -18,7 +18,7 @@
 from ..thrift import TPayloadMeta
 
 
-def load(path, module_name=None, include_dirs=None, include_dir=None):
+def load(path, module_name=None, include_dirs=None, include_dir=None, 
encoding='utf-8'):
     """Load thrift file as a module.
 
     The module loaded and objects inside may only be pickled if module_name
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/thriftpy2/parser/parser.py 
new/thriftpy2-0.4.7/thriftpy2/parser/parser.py
--- old/thriftpy2-0.4.5/thriftpy2/parser/parser.py      2019-08-27 
04:41:07.000000000 +0200
+++ new/thriftpy2-0.4.7/thriftpy2/parser/parser.py      2019-10-04 
12:07:51.000000000 +0200
@@ -14,7 +14,7 @@
 from ply import lex, yacc
 from .lexer import *  # noqa
 from .exc import ThriftParserError, ThriftGrammerError
-from thriftpy2._compat import urlopen, urlparse
+from thriftpy2._compat import urlopen, urlparse, PY3
 from ..thrift import gen_init, TType, TPayload, TException
 
 
@@ -503,7 +503,7 @@
 
 
 def parse(path, module_name=None, include_dirs=None, include_dir=None,
-          lexer=None, parser=None, enable_cache=True):
+          lexer=None, parser=None, enable_cache=True, encoding='utf-8'):
     """Parse a single thrift file to module object, e.g.::
 
         >>> from thriftpy2.parser.parser import parse
@@ -570,6 +570,9 @@
                                 'with path in protocol \'{}\''.format(
                                     url_scheme))
 
+    if PY3 and isinstance(data, bytes):
+        data = data.decode(encoding)
+
     if module_name is not None and not module_name.endswith('_thrift'):
         raise ThriftParserError('thriftpy2 can only generate module with '
                                 '\'_thrift\' suffix')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/thriftpy2/protocol/json.py 
new/thriftpy2-0.4.7/thriftpy2/protocol/json.py
--- old/thriftpy2-0.4.5/thriftpy2/protocol/json.py      2019-08-27 
04:41:07.000000000 +0200
+++ new/thriftpy2-0.4.7/thriftpy2/protocol/json.py      2019-10-04 
12:07:51.000000000 +0200
@@ -5,53 +5,57 @@
 import json
 import struct
 
+from thriftpy2._compat import u
 from thriftpy2.thrift import TType
 
 from .exc import TProtocolException
 
-INTEGER = (TType.BYTE, TType.I16, TType.I32, TType.I64)
-FLOAT = (TType.DOUBLE,)
-
 VERSION = 1
 
 
 def json_value(ttype, val, spec=None):
-    if ttype in INTEGER or ttype in FLOAT or ttype == TType.STRING:
-        return val
-
-    if ttype == TType.BOOL:
-        return True if val else False
-
-    if ttype == TType.STRUCT:
-        return struct_to_json(val)
-
-    if ttype in (TType.SET, TType.LIST):
-        return list_to_json(val, spec)
-
-    if ttype == TType.MAP:
-        return map_to_json(val, spec)
+    TTYPE_TO_JSONFUNC_MAP = {
+        TType.BYTE: (int, (val, )),
+        TType.I16: (int, (val, )),
+        TType.I32: (int, (val, )),
+        TType.I64: (int, (val, )),
+        TType.DOUBLE: (float, (val, )),
+        TType.STRING: (u, (val, )),
+        TType.BOOL: (bool, (val, )),
+        TType.STRUCT: (struct_to_json, (val, )),
+        TType.SET: (list_to_json, (val, spec)),
+        TType.LIST: (list_to_json, (val, spec)),
+        TType.MAP: (map_to_json, (val, spec)),
+    }
+    func, args = TTYPE_TO_JSONFUNC_MAP.get(ttype)
+    if func:
+        return func(*args)
 
 
 def obj_value(ttype, val, spec=None):
-    if ttype in INTEGER:
-        return int(val)
-
-    if ttype in FLOAT:
-        return float(val)
-
-    if ttype in (TType.STRING, TType.BOOL):
-        return val
-
+    TTYPE_TO_OBJFUNC_MAP = {
+        TType.BYTE: (int, (val, )),
+        TType.I16: (int, (val, )),
+        TType.I32: (int, (val, )),
+        TType.I64: (int, (val, )),
+        TType.DOUBLE: (float, (val, )),
+        TType.STRING: (u, (val, )),
+        TType.BOOL: (bool, (val, )),
+        TType.SET: (list_to_obj, (val, spec)),
+        TType.LIST: (list_to_obj, (val, spec)),
+        TType.MAP: (map_to_obj, (val, spec)),
+    }
+    func, args = TTYPE_TO_OBJFUNC_MAP.get(ttype)
+    if func:
+        return func(*args)
+
+    # Special case: since `spec` needs to get called if TType is STRUCT,
+    # if we initialize inside `TTYPE_TO_OBJFUNC_MAP` it will get called
+    # everytime the function gets called and incur in exception as
+    # `TypeError: 'NoneType' object is not callable`.
     if ttype == TType.STRUCT:
         return struct_to_obj(val, spec())
 
-    if ttype in (TType.SET, TType.LIST):
-        return list_to_obj(val, spec)
-
-    if ttype == TType.MAP:
-        return map_to_obj(val, spec)
-
-
 def map_to_obj(val, spec):
     res = {}
     if isinstance(spec[0], int):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/thriftpy2/rpc.py 
new/thriftpy2-0.4.7/thriftpy2/rpc.py
--- old/thriftpy2-0.4.5/thriftpy2/rpc.py        2019-08-27 04:41:07.000000000 
+0200
+++ new/thriftpy2-0.4.7/thriftpy2/rpc.py        2019-10-04 12:07:51.000000000 
+0200
@@ -5,7 +5,14 @@
 import contextlib
 import warnings
 
-from thriftpy2._compat import PY35
+from thriftpy2._compat import PY3, PY35
+if PY3:
+    import urllib
+else:
+    import urllib2 as urllib
+    import urlparse
+    urllib.parse = urlparse
+    urllib.parse.quote = urllib.quote
 
 from thriftpy2.protocol import TBinaryProtocolFactory
 from thriftpy2.server import TThreadedServer
@@ -22,10 +29,14 @@
 def make_client(service, host="localhost", port=9090, unix_socket=None,
                 proto_factory=TBinaryProtocolFactory(),
                 trans_factory=TBufferedTransportFactory(),
-                timeout=3000,
-                cafile=None, ssl_context=None, certfile=None, keyfile=None):
+                timeout=3000, cafile=None, ssl_context=None, certfile=None,
+                keyfile=None, url=""):
+    if url:
+        parsed_url = urllib.parse.urlparse(url)
+        host = parsed_url.hostname or host
+        port = parsed_url.port or port
     if unix_socket:
-        socket = TSocket(unix_socket=unix_socket)
+        socket = TSocket(unix_socket=unix_socket, socket_timeout=timeout)
         if certfile:
             warnings.warn("SSL only works with host:port, not unix_socket.")
     elif host and port:
@@ -37,7 +48,7 @@
         else:
             socket = TSocket(host, port, socket_timeout=timeout)
     else:
-        raise ValueError("Either host/port or unix_socket must be provided.")
+        raise ValueError("Either host/port or unix_socket or url must be 
provided.")
 
     transport = trans_factory.get_transport(socket)
     protocol = proto_factory.get_protocol(transport)
@@ -78,7 +89,13 @@
                    proto_factory=TBinaryProtocolFactory(),
                    trans_factory=TBufferedTransportFactory(),
                    timeout=None, socket_timeout=3000, connect_timeout=3000,
-                   cafile=None, ssl_context=None, certfile=None, keyfile=None):
+                   cafile=None, ssl_context=None, certfile=None, keyfile=None,
+                   url=""):
+    if url:
+        parsed_url = urllib.parse.urlparse(url)
+        host = parsed_url.hostname or host
+        port = parsed_url.port or port
+
     if timeout:
         warnings.warn("`timeout` deprecated, use `socket_timeout` and "
                       "`connect_timeout` instead.")
@@ -103,7 +120,7 @@
                              connect_timeout=connect_timeout,
                              socket_timeout=socket_timeout)
     else:
-        raise ValueError("Either host/port or unix_socket must be provided.")
+        raise ValueError("Either host/port or unix_socket or url must be 
provided.")
 
     try:
         transport = trans_factory.get_transport(socket)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/thriftpy2/thrift.py 
new/thriftpy2-0.4.7/thriftpy2/thrift.py
--- old/thriftpy2-0.4.5/thriftpy2/thrift.py     2019-08-27 04:41:07.000000000 
+0200
+++ new/thriftpy2-0.4.7/thriftpy2/thrift.py     2019-10-04 12:07:51.000000000 
+0200
@@ -13,12 +13,22 @@
 import linecache
 import types
 
-from ._compat import with_metaclass
-
-
-def args2kwargs(thrift_spec, *args):
-    arg_names = [item[1][1] for item in sorted(thrift_spec.items())]
-    return dict(zip(arg_names, args))
+from ._compat import with_metaclass, PY3
+if PY3:
+    from itertools import zip_longest
+else:
+    from itertools import izip_longest as zip_longest
+
+
+def args_to_kwargs(thrift_spec, *args, **kwargs):
+    for item, value in zip_longest(sorted(thrift_spec.items()), args):
+        arg_name = item[1][1]
+        required = item[1][-1]
+        if value is not None:
+            kwargs[item[1][1]] = value
+        if required and arg_name not in kwargs:
+            raise ValueError(arg_name)
+    return kwargs
 
 
 def parse_spec(ttype, spec=None):
@@ -192,9 +202,15 @@
         return self._service.thrift_services
 
     def _req(self, _api, *args, **kwargs):
-        _kw = args2kwargs(getattr(self._service, _api + "_args").thrift_spec,
-                          *args)
-        kwargs.update(_kw)
+        try:
+            kwargs = args_to_kwargs(getattr(self._service, _api + 
"_args").thrift_spec,
+                          *args, **kwargs)
+        except ValueError as e:
+            raise TApplicationException(
+                    TApplicationException.UNKNOWN_METHOD,
+                    '{arg} is required argument for {service}.{api}'.format(
+                        arg=e.args[0], service=self._service.__name__, 
api=_api))
+
         result_cls = getattr(self._service, _api + "_result")
 
         self._send(_api, **kwargs)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/thriftpy2-0.4.5/thriftpy2/tornado.py 
new/thriftpy2-0.4.7/thriftpy2/tornado.py
--- old/thriftpy2-0.4.5/thriftpy2/tornado.py    2019-08-27 04:41:07.000000000 
+0200
+++ new/thriftpy2-0.4.7/thriftpy2/tornado.py    2019-10-04 12:07:51.000000000 
+0200
@@ -29,6 +29,14 @@
 
 # TODO need TCyTornadoStreamTransport to work with cython binary protocol
 from .protocol.binary import TBinaryProtocolFactory
+from ._compat import PY3
+if PY3:
+    import urllib
+else:
+    import urllib2 as urllib
+    import urlparse
+    urllib.parse = urlparse
+    urllib.parse.quote = urllib.quote
 
 import logging
 import socket
@@ -243,10 +251,15 @@
 
 @gen.coroutine
 def make_client(
-        service, host, port, proto_factory=TBinaryProtocolFactory(),
+        service, host='localhost', port=9090, 
proto_factory=TBinaryProtocolFactory(),
         io_loop=None, ssl_options=None,
         connect_timeout=TTornadoStreamTransport.DEFAULT_CONNECT_TIMEOUT,
-        read_timeout=TTornadoStreamTransport.DEFAULT_READ_TIMEOUT):
+        read_timeout=TTornadoStreamTransport.DEFAULT_READ_TIMEOUT,
+        url=''):
+    if url:
+        parsed_url = urllib.parse.urlparse(url)
+        host = parsed_url.hostname or host
+        port = parsed_url.port or port
     transport = TTornadoStreamTransport(
         host, port, io_loop=io_loop,
         ssl_options=ssl_options, read_timeout=read_timeout)


Reply via email to