GithubHelp home page GithubHelp logo

thriftpy / thriftpy2 Goto Github PK

View Code? Open in Web Editor NEW
553.0 12.0 88.0 1.23 MB

Pure python approach of Apache Thrift.

License: MIT License

Makefile 0.10% Thrift 5.89% Python 85.31% C 0.87% Cython 6.99% Shell 0.85%
thrift thriftpy python rpc

thriftpy2's Introduction

ThriftPy

Thriftpy has been deprecated, please migrate to thriftpy2

image

image

image

image

ThriftPy is a pure python implementation of Apache Thrift in a pythonic way.

Documentation: https://thriftpy.readthedocs.org/

Installation

Install with pip.

$ pip install thriftpy

You may also install cython first to build cython extension locally.

$ pip install cython thriftpy

Code Demo

ThriftPy make it super easy to write server/client code with thrift. Let's checkout this simple pingpong service demo.

We need a 'pingpong.thrift' file:

service PingPong {
    string ping(),
}

Then we can make a server:

import thriftpy
pingpong_thrift = thriftpy.load("pingpong.thrift", module_name="pingpong_thrift")

from thriftpy.rpc import make_server

class Dispatcher(object):
    def ping(self):
        return "pong"

server = make_server(pingpong_thrift.PingPong, Dispatcher(), '127.0.0.1', 6000)
server.serve()

And a client:

import thriftpy
pingpong_thrift = thriftpy.load("pingpong.thrift", module_name="pingpong_thrift")

from thriftpy.rpc import make_client

client = make_client(pingpong_thrift.PingPong, '127.0.0.1', 6000)
print(client.ping())

See, it's that easy!

You can refer to 'examples' and 'tests' directory in source code for more usage examples.

Features

Currently ThriftPy have these features (also advantages over the upstream python lib):

  • Supports Python 2.7, Python 3.4+, PyPy and PyPy3.
  • Pure python implementation. No longer need to compile & install the 'thrift' package. All you need is thriftpy and thrift file.
  • Compatible with Apache Thrift. You can use ThriftPy together with the official implementation servers and clients, such as a upstream server with a thriftpy client or the opposite.

    Currently implemented protocols and transports:

    • binary protocol (python and cython)
    • compact protocol (python and cython)
    • json protocol
    • buffered transport (python & cython)
    • framed transport
    • tornado server and client (with tornado 4.0)
    • http server and client
  • Can directly load thrift file as module, the sdk code will be generated on the fly.

    For example, pingpong_thrift = thriftpy.load("pingpong.thrift", module_name="pingpong_thrift") will load 'pingpong.thrift' as 'pingpong_thrift' module.

    Or, when import hook enabled by thriftpy.install_import_hook(), you can directly use import pingpong_thrift to import the 'pingpong.thrift' file as module, you may also use from pingpong_thrift import PingService to import specific object from the thrift module.

  • Easy RPC server/client setup.

Contribute

  1. Fork the repo and make changes.
  2. Write a test which shows a bug was fixed or the feature works as expected.
  3. Make sure travis-ci or tox tests succeed.
  4. Send pull request.

Contributors

https://github.com/eleme/thriftpy/graphs/contributors

Changelog

https://github.com/eleme/thriftpy/blob/master/CHANGES.rst

thriftpy2's People

Contributors

1c4nfan avatar achimnol avatar aisk avatar aiudirog avatar bachmann1234 avatar cocolato avatar damnever avatar dan-blanchard avatar erkatz avatar ethe avatar halfcrazy avatar hit9 avatar hugovk avatar iamsudip avatar jonnoftw avatar jparise avatar junnplus avatar keitheis avatar kep-w avatar laserson avatar lepture avatar lexdene avatar lxyu avatar maralla avatar microdog avatar noodle4u avatar pawl avatar truebit avatar wooparadog avatar xvblack avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

thriftpy2's Issues

Add URL parsing to make_client/client_context

Currently you must pass in host, scheme, and path when using the HTTPClient. It would be a nice feature to take a url parameter, and have the client method use urllib.parse to extract out these values for the caller.

ImportError: cannot import name 'TCyBinaryProtocol'

Python 3.5

from api.lib import *

File "/root/protect/api/lib/init.py", line 2, in
from .client import LineClient
File "/root/protect/api/lib/client.py", line 3, in
from .api import LineAPI
File "/root/protect/api/lib/api.py", line 8, in
from api.thriftpy2.protocol import TCompactProtocol
File "/root/protect/api/thriftpy2/protocol/init.py", line 15, in
from .cybin import TCyBinaryProtocol, TCyBinaryProtocolFactory
ImportError: cannot import name 'TCyBinaryProtocol'

RecursionError: maximum recursion depth exceeded

windows is raise exception and linux is ok.
when I use rpc client in subprocess [using multiprocess.Process start]
Raise Exception:
Traceback (most recent call last):
File "", line 1, in
File "D:\ProgramData\Anaconda3\lib\multiprocessing\spawn.py", line 105, in spawn_main
exitcode = _main(fd)
File "D:\ProgramData\Anaconda3\lib\multiprocessing\spawn.py", line 115, in _main
self = reduction.pickle.load(from_parent)
File "D:\ProgramData\Anaconda3\lib\site-packages\thriftpy2\thrift.py", line 180, in getattr
print(self._service.thrift_services)
File "D:\ProgramData\Anaconda3\lib\site-packages\thriftpy2\thrift.py", line 180, in getattr
print(self._service.thrift_services)
File "D:\ProgramData\Anaconda3\lib\site-packages\thriftpy2\thrift.py", line 180, in getattr
print(self._service.thrift_services)
[Previous line repeated 328 more times]
RecursionError: maximum recursion depth exceeded while calling a Python object

How to close socket connection when using make_client?

 import thriftpy2

 pingpong_thrift` = thriftpy2.load("pingpong.thrift", module_name="pingpong_thrift")

from thriftpy2.rpc import make_client

client = make_client(pingpong_thrift.PingPong, '127.0.0.1', 6000)
print(client.ping())

for the client code example as showed in homepage, how and when to close socket connection?

TProtocolException message is omitted in repr

When getting TProtocolException in stack trace, I see no message:

Traceback (most recent call last):
  File "/usr/local/lib/python3.8/site-packages/happybase/table.py", line 418, in scan
    raise e
  File "/usr/local/lib/python3.8/site-packages/happybase/table.py", line 415, in scan
    items = self.connection.client.scannerGetList(scan_id, how_many)
  File "/usr/local/lib/python3.8/site-packages/thriftpy2/thrift.py", line 219, in _req
    return self._recv(_api)
  File "/usr/local/lib/python3.8/site-packages/thriftpy2/thrift.py", line 231, in _recv
    fname, mtype, rseqid = self._iprot.read_message_begin()
  File "/usr/local/lib/python3.8/site-packages/thriftpy2/protocol/compact.py", line 145, in read_message_begin
    raise TProtocolException(TProtocolException.BAD_VERSION,
thriftpy2.protocol.exc.TProtocolException: TProtocolException(type=4)

Consider the following snippet:

Python 3.8.0 (default, Nov 23 2019, 05:36:56) 
[GCC 8.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> from thriftpy2.protocol.exc import TProtocolException
>>> x = TProtocolException(TProtocolException.BAD_VERSION, 'message please')
>>> x
TProtocolException(type=4)
>>> x.message
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'TProtocolException' object has no attribute 'message'
>>> x.args
('message please',)
>>> x.__dict__
{'type': 4}

Looks like this is caused by overriding the default __str__() in TPayload: https://github.com/Thriftpy/thriftpy2/blob/master/thriftpy2/thrift.py#L169

Types used in lists must be declared beforehand

If you have a field with a type like list<T>, T must already have been declared, or the field will be serialized wrong.

How to reproduce:
In tests/container.thrift, move ListStruct to the top of the file, before ListItem,
Run the tests and test_container.py will fail:

    def test_list_struct():
        l_item = container.ListItem()
        l_item.list_string = ['foo', 'bar'] * 100
        l_item.list_list_string = [['foo', 'bar']] * 100
    
        l_struct = container.ListStruct()
        l_struct.list_items = [l_item] * 100
    
        b = serialize(l_struct)
        l_struct2 = deserialize(container.ListStruct(), b)
>       assert l_struct == l_struct2
E       AssertionError: assert ListStruct(list_items=[ListItem(list_string=['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'fo...r'], ['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar'], ['foo', 'bar']])])
== ListStruct(list_items=[None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None,...one, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None])

test_container.py:55: AssertionError

It looks like fill_incomplete_ttype should deal with declaration order, but misses the list field. I would also expect serializing or deserializing incomplete types to fail instead of silently substituting 'None', since this makes bugs hard to debug.

Python 3.8 support

Hi there, thank you for this project!

I'm opening this issue to track support for Python 3.8, in case you all hadn't had a chance to look into it yet.

Currently, the sdist fails to install on macOS and 3.8.0b1 installed via pyenv . I have not tried on Linux.

$ pip3.8 install thriftpy2

Collecting thriftpy2
  Using cached https://files.pythonhosted.org/packages/b1/6e/ee0400c5d25babf1426b20fc75192f723c693915e81d251056097206a161/thriftpy2-0.4.4.tar.gz
Collecting ply<4.0,>=3.4 (from thriftpy2)
  Using cached https://files.pythonhosted.org/packages/a3/58/35da89ee790598a0700ea49b2a66594140f44dec458c07e8e3d4979137fc/ply-3.11-py2.py3-none-any.whl
Installing collected packages: ply, thriftpy2
  Running setup.py install for thriftpy2 ... error
    Complete output from command /Users/eric/.pyenv/versions/3.8-dev/bin/python3.8 -u -c "import setuptools, tokenize;__file__='/private/var/folders/sx/pdpbqz4x5cscn9hhfpbsbqvm0000gn/T/pip-install-hu1_p_gv/thriftpy2/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /private/var/folders/sx/pdpbqz4x5cscn9hhfpbsbqvm0000gn/T/pip-record-ngyw_g3u/install-record.txt --single-version-externally-managed --compile:
    running install
    running build
    running build_py
    creating build
    creating build/lib.macosx-10.14-x86_64-3.8
    creating build/lib.macosx-10.14-x86_64-3.8/thriftpy2
    copying thriftpy2/server.py -> build/lib.macosx-10.14-x86_64-3.8/thriftpy2
    ...
    copying thriftpy2/contrib/aio/protocol/__init__.py -> build/lib.macosx-10.14-x86_64-3.8/thriftpy2/contrib/aio/protocol
    running egg_info
    writing thriftpy2.egg-info/PKG-INFO
    writing dependency_links to thriftpy2.egg-info/dependency_links.txt
    writing requirements to thriftpy2.egg-info/requires.txt
    writing top-level names to thriftpy2.egg-info/top_level.txt
    reading manifest file 'thriftpy2.egg-info/SOURCES.txt'
    reading manifest template 'MANIFEST.in'
    writing manifest file 'thriftpy2.egg-info/SOURCES.txt'
    copying thriftpy2/transport/cybase.c -> build/lib.macosx-10.14-x86_64-3.8/thriftpy2/transport
   ...
    copying thriftpy2/contrib/tracking/tracking.thrift -> build/lib.macosx-10.14-x86_64-3.8/thriftpy2/contrib/tracking
    running build_ext
    building 'thriftpy2.transport.cybase' extension
    creating build/temp.macosx-10.14-x86_64-3.8
    creating build/temp.macosx-10.14-x86_64-3.8/thriftpy2
    creating build/temp.macosx-10.14-x86_64-3.8/thriftpy2/transport
    clang -Wno-unused-result -Wsign-compare -Wunreachable-code -DNDEBUG -g -fwrapv -O3 -Wall -I/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include -I/Library/Developer/CommandLineTools/SDKs/MacOSX10.14.sdk/usr/include -I/usr/local/opt/openssl/include -I/Users/eric/.pyenv/versions/3.8-dev/include/python3.8 -c thriftpy2/transport/cybase.c -o build/temp.macosx-10.14-x86_64-3.8/thriftpy2/transport/cybase.o
    thriftpy2/transport/cybase.c:4007:33: error: too few arguments to function call, expected 16, have 15
      __pyx_codeobj__4 = (PyObject*)__Pyx_PyCode_New(3, 0, 5, 0, CO_OPTIMIZED|CO_NEWLOCALS, __pyx_empty_bytes, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_tuple__3, __pyx_empty_tuple, __pyx_empty_tuple, __pyx_kp_s_stringsource, __pyx_n_s_pyx_unpickle_CyTransportBase, 1, __pyx_empty_bytes); if (unlikely(!__pyx_codeobj__4)) __PYX_ERR(0, 1, __pyx_L1_error)
                                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    thriftpy2/transport/cybase.c:327:83: note: expanded from macro '__Pyx_PyCode_New'
              PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
              ~~~~~~~~~~                                                              ^
    /Users/eric/.pyenv/versions/3.8-dev/include/python3.8/code.h:122:12: note: 'PyCode_New' declared here
    PyAPI_FUNC(PyCodeObject *) PyCode_New(
               ^
    thriftpy2/transport/cybase.c:4069:54: error: no member named 'tp_print' in 'struct _typeobject'
      __pyx_type_9thriftpy2_9transport_6cybase_TCyBuffer.tp_print = 0;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
    thriftpy2/transport/cybase.c:4083:60: error: no member named 'tp_print' in 'struct _typeobject'
      __pyx_type_9thriftpy2_9transport_6cybase_CyTransportBase.tp_print = 0;
      ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
    thriftpy2/transport/cybase.c:5803:15: error: too few arguments to function call, expected 16, have 15
        py_code = __Pyx_PyCode_New(
                  ^~~~~~~~~~~~~~~~~
    thriftpy2/transport/cybase.c:327:83: note: expanded from macro '__Pyx_PyCode_New'
              PyCode_New(a, k, l, s, f, code, c, n, v, fv, cell, fn, name, fline, lnos)
              ~~~~~~~~~~                                                              ^
    /Users/eric/.pyenv/versions/3.8-dev/include/python3.8/code.h:122:12: note: 'PyCode_New' declared here
    PyAPI_FUNC(PyCodeObject *) PyCode_New(
               ^
    4 errors generated.
    error: command 'clang' failed with exit status 1

    ----------------------------------------
Command "/Users/eric/.pyenv/versions/3.8-dev/bin/python3.8 -u -c "import setuptools, tokenize;__file__='/private/var/folders/sx/pdpbqz4x5cscn9hhfpbsbqvm0000gn/T/pip-install-hu1_p_gv/thriftpy2/setup.py';f=getattr(tokenize, 'open', open)(__file__);code=f.read().replace('\r\n', '\n');f.close();exec(compile(code, __file__, 'exec'))" install --record /private/var/folders/sx/pdpbqz4x5cscn9hhfpbsbqvm0000gn/T/pip-record-ngyw_g3u/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/var/folders/sx/pdpbqz4x5cscn9hhfpbsbqvm0000gn/T/pip-install-hu1_p_gv/thriftpy2/

Service method named 'close' in thrift file seems to be incorrectly translated in client

Hi,
I am implementing a Python client using thriftpy2 to a thrift C++ server.
One of the method from a service is called 'close'.
It seems that the thriftpy client fails to implement it correctly.

I have written a minimalist python script that reproduces the issue.
The script loads the following thrift file:

service File {
    void close(1: i32 idfile, 2: string anything);
    void close2(1: i32 idfile, 2: string anything);
}

It then prints the signature of the close and close2 methods, as loaded by the thriftpy client:

#!/usr/bin/python3

import thriftpy2
from thriftpy2.rpc import client_context
from thriftpy2.rpc import make_client
from thriftpy2.protocol import (
    TBinaryProtocolFactory,
    TMultiplexedProtocolFactory
)

import inspect

file_thrift = thriftpy2.load("File.thrift", module_name="file_thrift")
binary_factory = TBinaryProtocolFactory()
client = make_client(file_thrift.File, '192.168.57.2', 9090,
                     proto_factory=binary_factory)

print("Signature of the close method:")
print(inspect.signature(client.close))
print("Signature of the close2 method:")
print(inspect.signature(client.close2))

Here is the output I get:

Signature of the close method:
()
Signature of the close2 method:
(*args, **kwargs)

It seems that thriftpy has some conflict with the name 'close'.
Eventually, is there a way to aliase the thrift service method name? (I cannot change it in the server implementation)

Regards,
Florent
thriftpy2_close_bug.zip

about log request parameters

Hi,
How to get the request parameters for logging, is there any example to check.
Which I mean define a method as below:
string ping(1:i32 a, 2:i32 b)
can I catch the parameters of ping(1, 2, 3). It seems that it only print (1,2)

Thx.

docker server no response

i use the pingpong demo server in docker,but the client could not get any response,can you help me ?

thriftpy2.transport.TTransportException: TTransportException(type=4, message='TSocket read 0 bytes')

thriftpy2.load(path=url) 当通过url的方式获取加载thrift文件时会报错

thriftpy2.load(path=url) 当通过url的方式获取加载thrift文件时会报错
TypeError: 'in ' requires string as left operand, not int
因为在thriftpy2.parser.parser文件line 567 data = urlopen(path).read(),data的type是bytes,不是string
当改成data = urlopen(path).read().decode('utf-8')时问题就解决了
请问是否有计划完善这部分?

Invalid thrift_spec if type is used before define

Codes to reproduce this:

test.thrift

struct Container {
    1: A field1;
    2: list<A> field2;
    3: list<map<string, A>> field3;
}

struct A {
    1: string value
}

test.py

import thriftpy2
from pprint import pprint

test_thrift = thriftpy2.load('./test.thrift')

pprint(test_thrift.Container.thrift_spec)

output:

{1: (12, 'field1', <class 'test.A'>, False),
 2: (15, 'field2', (12, <class 'test.A'>), False),
 3: (15, 'field3', (13, (11, -3)), False)}

Notice the field3, it's spec is expected to be (15, 'field3', (13, (11, <class 'test.A'>)), False) like field2.

Thriftpy should enforce required arguments

It seems that thriftpy is not enforcing required parameters to service calls. Instead of the client raising an exception, the request is serialized with None in place of the missing arguments. I could see this being reasonable for optional arguments, but required arguments should be required.

For the example service:

service HelloService {
    string greet(1: required string greeting);
}

Calling client.greet() will send None as the value for greeting. I would expect this to throw an exception.

No protocol version header

when i use java client to invok my python server,it errors

2018-11-02 21:37:01 ERROR    thriftpy.server  - No protocol version header
Traceback (most recent call last):
  File "/root/anaconda3/envs/rasa/lib/python3.6/site-packages/thriftpy/server.py", line 95, in handle
    self.processor.process(iprot, oprot)
  File "/root/anaconda3/envs/rasa/lib/python3.6/site-packages/thriftpy/thrift.py", line 294, in process
    api, seqid, result, call = self.process_in(iprot)
  File "/root/anaconda3/envs/rasa/lib/python3.6/site-packages/thriftpy/thrift.py", line 250, in process_in
    api, type, seqid = iprot.read_message_begin()
  File "thriftpy/protocol/cybin/cybin.pyx", line 439, in cybin.TCyBinaryProtocol.read_message_begin
cybin.ProtocolError: No protocol version header

will it block when I make a rpc request on my client server?

I use flask providing web api, above flask, I use gunicorn to patch all block I/O such as pymongo and requests, but I think it will block on rpc client request, because rpc use tcp to communicate, and gunicorn don't patch it. so, how can I make the client request not blocking?

我用flask框架来做服务端, 项目启动的时候用gunicorn的gevent的worker模式, 据我所知, gevent会把Python标准库以及常用的pymongo等数据库请求以及requests等库patch成非阻塞的,这样我的服务就可以有很大的并发能力,但我们现在用了thrift rpc之后, 我怀疑在做rpc请求时(本服务向另一个微服务请求), I/O 会阻塞掉, 请问有什么好方法来解决呢? 请求调用改成asyncio能解决这个问题吗(我不确定thriftpy里边实际的tcp过程是否会继续阻塞的)?

Default timeout in thriftpy2.rpc.make_client() is different from thriftpy.rpc.make_client()

Hello,

I've noticed that the default timeout in thriftpy2.rpc.make_client() differs in the old thriftpy:

thriftpy2.rpc.make_client(service, host='localhost', port=9090, unix_socket=None, proto_factory=<cybin.TCyBinaryProtocolFactory object at 0x7fc655ef3400>, trans_factory=<thriftpy2.transport.buffered.cybuffered.TCyBufferedTransportFactory object at 0x7fc655ef3240>, timeout=3000, cafile=None, ssl_context=None, certfile=None, keyfile=None, url='')

thriftpy.rpc.make_client(service, host='localhost', port=9090, unix_socket=None, proto_factory=<cybin.TCyBinaryProtocolFactory object at 0x7fc656bf9ba8>, trans_factory=<thriftpy.transport.buffered.cybuffered.TCyBufferedTransportFactory object at 0x7fc65b171a90>, timeout=None, cafile=None, ssl_context=None, certfile=None, keyfile=None)

The timeout was introduced in #60 which broke compatibility with the old thriftpy.

Parser error when downloading thrift file from network

I've tried using thriftpy2.load with url instead of file path.

backend_thrift = thriftpy2.load("http://host/backend.thrift", module_name="backend_thrift")

When file is read from local file everything is fine, but from url I recived error:

Traceback (most recent call last):
...
  File "/.../venv/lib/python3.6/site-packages/ply/lex.py", line 314, in token
    if lexdata[lexpos] in lexignore:
TypeError: 'in <string>' requires string as left operand, not int

Fast fix in venv/lib/python3.6/site-packages/thriftpy2/parser/parser.py:567:

    elif url_scheme in ('http', 'https'):
        data = urlopen(path).read().decode()

Add enum constructor to create enum from value

Thought we have a thrift file:

enum TestEnum {
    a = 1;
    b = 2;
}

It's common to create a enum from it's value like this:

a = TestEnum(1)

For now, the enum type do not accept any constructor parameters, can we add it like above, or generated a public api to do this convert?

Can't pickle TMemoryBuffer class for Pyspark Spark-Submit

I'm havign trouble pickling TMemoryBuffer so I can use the object within a spark-submit pyspark job. Has anyone seen this before/found a good workaround?

Pickling error:

>>> transportIn = TMemoryBuffer(bytes_l)
>>> pickle.dumps(transportIn)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib64/python2.7/pickle.py", line 1380, in dumps
    Pickler(file, protocol).dump(obj)
  File "/usr/lib64/python2.7/pickle.py", line 224, in dump
    self.save(obj)
  File "/usr/lib64/python2.7/pickle.py", line 331, in save
    self.save_reduce(obj=obj, *rv)
  File "/usr/lib64/python2.7/pickle.py", line 425, in save_reduce
    save(state)
  File "/usr/lib64/python2.7/pickle.py", line 286, in save
    f(self, obj) # Call unbound method with explicit self
  File "/usr/lib64/python2.7/pickle.py", line 568, in save_tuple
    save(element)
  File "/usr/lib64/python2.7/pickle.py", line 306, in save
    rv = reduce(self.proto)
  File "stringsource", line 2, in thriftpy2.transport.cybase.TCyBuffer.__reduce_cython__
TypeError: no default __reduce__ due to non-trivial __cinit__

Spark-Submit error:

Caused by: org.apache.spark.api.python.PythonException: Traceback (most recent call last):
  File "/mnt/yarn/usercache/hadoop/appcache/application_1570742233522_0318/container_1570742233522_0318_01_000003/pyspark.zip/pyspark/worker.py", line 216, in main
    func, profiler, deserializer, serializer = read_command(pickleSer, infile)
  File "/mnt/yarn/usercache/hadoop/appcache/application_1570742233522_0318/container_1570742233522_0318_01_000003/pyspark.zip/pyspark/worker.py", line 58, in read_command
    command = serializer._read_with_length(file)
  File "/mnt/yarn/usercache/hadoop/appcache/application_1570742233522_0318/container_1570742233522_0318_01_000003/pyspark.zip/pyspark/serializers.py", line 170, in _read_with_length
    return self.loads(obj)
  File "/mnt/yarn/usercache/hadoop/appcache/application_1570742233522_0318/container_1570742233522_0318_01_000003/pyspark.zip/pyspark/serializers.py", line 562, in loads
    return pickle.loads(obj)
ImportError: No module named thriftpy2.transport.memory.cymemory

Installing thriftpy2 on pypy breaks installing it on CPython

If you run pip install thriftpy2 in a pypy virtualenv, pip generates a thriftpy2-0.4.1-py2.py3-none-any.whl wheel which won't work in CPython. pip also saves these wheels in your home folder cache, which means that if you try to install it in any other virtualenv afterwards it'll just use that cached wheel.

If you now install it in a CPython virtualenv and try to import from thriftpy2.protocol.binary import read_list_begin you'll get an error like ModuleNotFoundError: No module named 'thriftpy2.protocol.cybin'.

From what I understand, when we're running in pypy we don't compile some modules with cython. Which is why it generates a universal wheel. However when running in CPython the code somehow understands that you should have compiled those modules, so it tries to import the .so files. And fails since the wheel was built in pypy.

This is very annoying since I have to either always specify --no-binary thriftpy2 in every pip install or wipe my local cache every time I run the tests.

I'm not sure what the best solution is here, but if we made the code resistant to those modules being missing that'd already help.


To reproduce just create a Dockerfile with this content:

FROM ubuntu:bionic

RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \
    build-essential \
    pypy \
    python3-dev \
    virtualenv

RUN virtualenv -p pypy venv_pypy
RUN venv_pypy/bin/pip install -v thriftpy2
RUN venv_pypy/bin/python -c 'from thriftpy2.protocol.binary import read_list_begin'

RUN virtualenv -p python3 venv_py3
RUN venv_py3/bin/pip install -v thriftpy2
RUN venv_py3/bin/python -c 'from thriftpy2.protocol.binary import read_list_begin'

and then run docker build .

Parse error on empty set field value

The following thift file,

(NB that the file can be parsed correctly using the Thrift executable from https://thrift.apache.org/download, tested with the latest version at the time of writing 0.12.0)

struct Status {
	1: string state,
	2: optional set<string> info={},  # <-- problem line
}
	
service EchoService {
    string echo(1: string param),
    Status get_status(),
}

causes a parse error,

Traceback (most recent call last):
  File "C:\Users\daniel.farrell\AppData\Local\Continuum\anaconda3\envs\porosity_env\lib\site-packages\thriftpy2\parser\parser.py", line 341, in p_simple_field
    val = _cast(p[3])(p[6])
  File "C:\Users\daniel.farrell\AppData\Local\Continuum\anaconda3\envs\porosity_env\lib\site-packages\thriftpy2\parser\parser.py", line 753, in __cast_set
    assert isinstance(v, (list, set))
AssertionError

The parse error is because Python does not have a literal for an empty set. The string {} in the thrift file is interpreted as a dict which generates the assertion error.

assert isinstance(v, (list, set))

A potential fix is to check for empty dict values and force the return value to be a set:

def _cast_set(t):
    assert t[0] == TType.SET

    def __cast_set(v):
        if len(v) == 0 and isinstance(v, dict):
            v = set()
        assert isinstance(v, (list, set))
        map(_cast(t[1]), v)
        if not isinstance(v, set):
            return set(v)
        return v
    return __cast_set

I'm working on a pull request and adding tests etc.

how to use multi server with its own port

Hi ,
I want to know how to use multi server with its own port in a program. For example, PingPing.ping use 127.0.0.1:80;PingDong.dong use 127.0.0.1:8080 as server address.
It seems that TThreadedServer supports multi server with same port in a program.

Thx!

Import issue on AWS Lambda

I'm trying to get Thriftpy2 to work with AWS Lambda. AWS Lambda depends on an AWS Linux which I think is based on RHEL/centos.
https://docs.aws.amazon.com/lambda/latest/dg/current-supported-versions.html

I get the following error:

Traceback (most recent call last):
  File "lambda_func.py", line 3, in <module>
    from thriftpy2.protocol import TCyBinaryProtocolFactory
  File "/var/task/thriftpy2/protocol/__init__.py", line 14, in <module>
    from .cybin import TCyBinaryProtocol, TCyBinaryProtocolFactory
ModuleNotFoundError: No module named 'thriftpy2.protocol.cybin'``` 

is this thread-safe

I tried to run some examples under multithreading environment,but I but I got a lot of exceptions.
just like:

  File "D:\Workspace\work\pypi_packages\thriftpy2src\thriftpy2\protocol\binary.py", line 386, in read_struct
    return read_struct(self.trans, obj, self.decode_response)
  File "D:\Workspace\work\pypi_packages\thriftpy2src\thriftpy2\protocol\binary.py", line 294, in read_struct
    f_type, fid = read_field_begin(inbuf)
  File "D:\Workspace\work\pypi_packages\thriftpy2src\thriftpy2\protocol\binary.py", line 189, in read_field_begin
    f_type = unpack_i8(inbuf.read(1))
  File "D:\Workspace\work\pypi_packages\thriftpy2src\thriftpy2\transport\__init__.py", line 32, in read
    return readall(self._read, sz)
  File "D:\Workspace\work\pypi_packages\thriftpy2src\thriftpy2\transport\__init__.py", line 14, in readall
    chunk = read_fn(sz - have)
  File "D:\Workspace\work\pypi_packages\thriftpy2src\thriftpy2\transport\buffered\__init__.py", line 39, in _read
    self._rbuf = BytesIO(self._trans.read(max(sz, self._buf_size)))
  File "D:\Workspace\work\pypi_packages\thriftpy2src\thriftpy2\transport\socket.py", line 109, in read
    buff = self.sock.recv(sz)
AttributeError: 'NoneType' object has no attribute 'recv'

thriftpy2/parser/parser.py raise an error

File "/data/www/envs/flask/lib/python2.7/site-packages/happybase/init.py", line 10, in
'Hbase_thrift')
File "/data/www/envs/flask/lib/python2.7/site-packages/thriftpy2/parser/init.py", line 33, in load
include_dir=include_dir)
File "/data/www/envs/flask/lib/python2.7/site-packages/thriftpy2/parser/parser.py", line 545, in parse
lexer = lex.lex()
File "/data/www/envs/flask/lib/python2.7/site-packages/ply/lex.py", line 910, in lex
raise SyntaxError("Can't build lexer")
SyntaxError: Can't build lexer

os.path.samfile patch craches shutil.copy2 under python 2.7.15

The patch Thriftpy/thriftpy#172 changes the behavior of os.path.
The function os.path.samefile is not available for Python 2 under windows. The patch adds that function. Unfortunately it doesn't work as expected.

I have some code that copies one file to another:

src = u'D:\\tmp\\source.txt'
dst = u'D:\\tmp\\destination.txt'
shutil.copy2(src, dst)

If the files are identical it will crash.

My workaround is:

if sys.version_info.major == 2 and hasattr(os.path, 'samefile'):
    # Run with hack
    backupfcn = os.path.samefile
    del os.path.samefile
    shutil.copy2(src, src)
    os.path.samefile = backupfcn
else:
    shutil.copy2(src, src)

I can live with it. I am in the process of migrating to Python 3, and then this patch will not be used if I understand it correct.

I just wanted to indicate that the patch has impacts that may not have been intended

Regards
Josef

Double const failed to be parsed if leading zeros gets ommitted

Currently the parser fails when parsing

const SOME_DOUBLE_CONST = .15;

This is valid double const in thrift definition and needs to be supported.

  File "/usr/local/lib/python2.7/site-packages/thriftpy2/parser/parser.py", line 585, in parse
    parser.parse(data)
  File "/usr/local/lib/python2.7/site-packages/ply/yacc.py", line 333, in parse
    return self.parseopt_notrack(input, lexer, debug, tracking, tokenfunc)
  File "/usr/local/lib/python2.7/site-packages/ply/yacc.py", line 1063, in parseopt_notrack
    lookahead = get_token()     # Get the next token
  File "/usr/local/lib/python2.7/site-packages/ply/lex.py", line 386, in token
    newtok = self.lexerrorf(tok)
  File "/usr/local/lib/python2.7/site-packages/thriftpy2/parser/lexer.py", line 165, in t_error
    (t.value[0], t.lineno))
thriftpy2.parser.exc.ThriftLexerError: Illegal character '.' at line 88

Why is __thrift_meta__.consts a list?

How do I get its identity?

IDL
const A = 1

Parsed
__thrift_meta__.consts = [1]

__thrift_meta__.consts = {"A": 1} Is this reasonable? or add const_names into thrift_meta

#98

Follow Strict Data Type in TJsonProtocol

Hey, I hava met a problem about using TJsonProtocol to serialize thrift obejct.

There is a double field defined in my thrift struct but assigned with a decimal object, which can not be serialized with TJsonProtocol.

I found the json_value function just return the value if it is a double field.

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)

I know the easiest way is to change the decimal object to float object, but it is possible to follow the strict data type in json value? such as:

def json_value(ttype, val, spec=None):
    if ttype in INTEGER:
	   return int(val)

    if ttype in FLOAT:
	   return float(val)

    if ttype == TType.STRING:
	   return str(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)

Thanks a lot!

bug

example/multiplexer/server.py forgot the host and port

NoneType TypeError happened when calling method `struct_to_obj`

Hey, i have met a problem when calling method thriftpy2.protocol.json.struct_to_obj. NoneType TypeError happened as follows.

...
  File "/xxx/venv/lib/python3.7/site-packages/thriftpy2/protocol/json.py", line 147, in struct_to_obj
    obj_value(field_type, val[field_name], field_type_spec))
  File "/xxx/venv/lib/python3.7/site-packages/thriftpy2/protocol/json.py", line 48, in obj_value
    func, args = TTYPE_TO_OBJFUNC_MAP.get(ttype)
TypeError: cannot unpack non-iterable NoneType object

Version thriftpy2==0.4.7

The error was due to missing keyTType.STRUCT in dict TTYPE_TO_OBJFUNC_MAP.

def obj_value(ttype, val, spec=None):
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())

I think of a solution as follows

func, args = TTYPE_TO_OBJFUNC_MAP.get(ttype) or (None, None)

Question about JSON protocol

I'm trying to use the TJSONProtocolFactory with the client I'm generating. And from what I can tell, the JSON it is generating is not valid thrift json. For example for a given function call on the client, I'm getting something like this:

'{"metadata": {"version": 1, "name": "registerThing", "ttype": 1, "seqid": 0}, 
"payload": {"request": {"uuid": "12322312121", "url": "someUrl", "user": "JohnSmith", "password": "pass1234"}}}'

In contrast I think I would be expecting something closer to this (the last object part is almost definitely wrong, but that kind of format anyways):

[1, "registerThing, 1, 0, { "1": {"rec" : {"1": {"str": "12322312121"}, "2": {"str": "someUrl"...............

or something like that.

I am very new to Thrift, so I could be wrong here, but I'm confused as to how I'm supposed to use this Protocol. The server I'm trying to connect to is rejecting the request as thriftpy sends it (unfortunately I can't give too much detail on that as it is a proprietary system). I noticed this difference in the json by debugging the request from the client I'm trying to write and comparing it to the requests received from other clients written in other languages.

Installation Error

pip install thriftpy2

DEPRECATION: Python 2.7 will reach the end of its life on January 1st, 2020. Please upgrade your Python as Python 2.7 won't be maintained after that date. A future version of pip will drop support for Python 2.7. More details about Python 2 support in pip, can be found at https://pip.pypa.io/en/latest/development/release-process/#python-2-support
Collecting thriftpy2
Using cached https://files.pythonhosted.org/packages/b1/6e/ee0400c5d25babf1426b20fc75192f723c693915e81d251056097206a161/thriftpy2-0.4.4.tar.gz
Requirement already satisfied: ply<4.0,>=3.4 in /usr/lib/python2.7/site-packages (from thriftpy2) (3.4)
Installing collected packages: thriftpy2
Running setup.py install for thriftpy2 ... error
ERROR: Command errored out with exit status 1:
command: /usr/bin/python2 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-68ikMM/thriftpy2/setup.py'"'"'; file='"'"'/tmp/pip-install-68ikMM/thriftpy2/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' install --record /tmp/pip-record-sXHwhY/install-record.txt --single-version-externally-managed --compile
cwd: /tmp/pip-install-68ikMM/thriftpy2/
Complete output (91 lines):
/usr/lib64/python2.7/distutils/dist.py:267: UserWarning: Unknown distribution option: 'python_requires'
warnings.warn(msg)
running install
running build
running build_py
creating build
creating build/lib.linux-x86_64-2.7
creating build/lib.linux-x86_64-2.7/thriftpy2
copying thriftpy2/init.py -> build/lib.linux-x86_64-2.7/thriftpy2
copying thriftpy2/_compat.py -> build/lib.linux-x86_64-2.7/thriftpy2
copying thriftpy2/hook.py -> build/lib.linux-x86_64-2.7/thriftpy2
copying thriftpy2/http.py -> build/lib.linux-x86_64-2.7/thriftpy2
copying thriftpy2/rpc.py -> build/lib.linux-x86_64-2.7/thriftpy2
copying thriftpy2/server.py -> build/lib.linux-x86_64-2.7/thriftpy2
copying thriftpy2/thrift.py -> build/lib.linux-x86_64-2.7/thriftpy2
copying thriftpy2/tornado.py -> build/lib.linux-x86_64-2.7/thriftpy2
copying thriftpy2/utils.py -> build/lib.linux-x86_64-2.7/thriftpy2
creating build/lib.linux-x86_64-2.7/thriftpy2/contrib
copying thriftpy2/contrib/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib
creating build/lib.linux-x86_64-2.7/thriftpy2/parser
copying thriftpy2/parser/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/parser
copying thriftpy2/parser/exc.py -> build/lib.linux-x86_64-2.7/thriftpy2/parser
copying thriftpy2/parser/lexer.py -> build/lib.linux-x86_64-2.7/thriftpy2/parser
copying thriftpy2/parser/parser.py -> build/lib.linux-x86_64-2.7/thriftpy2/parser
creating build/lib.linux-x86_64-2.7/thriftpy2/protocol
copying thriftpy2/protocol/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/protocol
copying thriftpy2/protocol/binary.py -> build/lib.linux-x86_64-2.7/thriftpy2/protocol
copying thriftpy2/protocol/compact.py -> build/lib.linux-x86_64-2.7/thriftpy2/protocol
copying thriftpy2/protocol/exc.py -> build/lib.linux-x86_64-2.7/thriftpy2/protocol
copying thriftpy2/protocol/json.py -> build/lib.linux-x86_64-2.7/thriftpy2/protocol
copying thriftpy2/protocol/multiplex.py -> build/lib.linux-x86_64-2.7/thriftpy2/protocol
creating build/lib.linux-x86_64-2.7/thriftpy2/transport
copying thriftpy2/transport/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/transport
copying thriftpy2/transport/_ssl.py -> build/lib.linux-x86_64-2.7/thriftpy2/transport
copying thriftpy2/transport/socket.py -> build/lib.linux-x86_64-2.7/thriftpy2/transport
copying thriftpy2/transport/sslsocket.py -> build/lib.linux-x86_64-2.7/thriftpy2/transport
creating build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio
copying thriftpy2/contrib/aio/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio
copying thriftpy2/contrib/aio/client.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio
copying thriftpy2/contrib/aio/processor.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio
copying thriftpy2/contrib/aio/rpc.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio
copying thriftpy2/contrib/aio/server.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio
copying thriftpy2/contrib/aio/socket.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio
creating build/lib.linux-x86_64-2.7/thriftpy2/contrib/tracking
copying thriftpy2/contrib/tracking/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/tracking
copying thriftpy2/contrib/tracking/tracker.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/tracking
creating build/lib.linux-x86_64-2.7/thriftpy2/transport/buffered
copying thriftpy2/transport/buffered/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/transport/buffered
creating build/lib.linux-x86_64-2.7/thriftpy2/transport/framed
copying thriftpy2/transport/framed/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/transport/framed
creating build/lib.linux-x86_64-2.7/thriftpy2/transport/memory
copying thriftpy2/transport/memory/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/transport/memory
creating build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio/protocol
copying thriftpy2/contrib/aio/protocol/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio/protocol
copying thriftpy2/contrib/aio/protocol/binary.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio/protocol
creating build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio/transport
copying thriftpy2/contrib/aio/transport/init.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio/transport
copying thriftpy2/contrib/aio/transport/buffered.py -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/aio/transport
running egg_info
writing requirements to thriftpy2.egg-info/requires.txt
writing thriftpy2.egg-info/PKG-INFO
writing top-level names to thriftpy2.egg-info/top_level.txt
writing dependency_links to thriftpy2.egg-info/dependency_links.txt
reading manifest file 'thriftpy2.egg-info/SOURCES.txt'
reading manifest template 'MANIFEST.in'
writing manifest file 'thriftpy2.egg-info/SOURCES.txt'
creating build/lib.linux-x86_64-2.7/thriftpy2/protocol/cybin
copying thriftpy2/protocol/cybin/cybin.c -> build/lib.linux-x86_64-2.7/thriftpy2/protocol/cybin
copying thriftpy2/protocol/cybin/cybin.pyx -> build/lib.linux-x86_64-2.7/thriftpy2/protocol/cybin
copying thriftpy2/protocol/cybin/endian_port.h -> build/lib.linux-x86_64-2.7/thriftpy2/protocol/cybin
copying thriftpy2/transport/cybase.c -> build/lib.linux-x86_64-2.7/thriftpy2/transport
copying thriftpy2/transport/cybase.pxd -> build/lib.linux-x86_64-2.7/thriftpy2/transport
copying thriftpy2/transport/cybase.pyx -> build/lib.linux-x86_64-2.7/thriftpy2/transport
copying thriftpy2/contrib/tracking/tracking.thrift -> build/lib.linux-x86_64-2.7/thriftpy2/contrib/tracking
copying thriftpy2/transport/buffered/cybuffered.c -> build/lib.linux-x86_64-2.7/thriftpy2/transport/buffered
copying thriftpy2/transport/buffered/cybuffered.pyx -> build/lib.linux-x86_64-2.7/thriftpy2/transport/buffered
copying thriftpy2/transport/framed/cyframed.c -> build/lib.linux-x86_64-2.7/thriftpy2/transport/framed
copying thriftpy2/transport/framed/cyframed.pyx -> build/lib.linux-x86_64-2.7/thriftpy2/transport/framed
copying thriftpy2/transport/memory/cymemory.c -> build/lib.linux-x86_64-2.7/thriftpy2/transport/memory
copying thriftpy2/transport/memory/cymemory.pyx -> build/lib.linux-x86_64-2.7/thriftpy2/transport/memory
running build_ext
building 'thriftpy2.transport.cybase' extension
creating build/temp.linux-x86_64-2.7
creating build/temp.linux-x86_64-2.7/thriftpy2
creating build/temp.linux-x86_64-2.7/thriftpy2/transport
gcc -pthread -fno-strict-aliasing -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -DNDEBUG -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector-strong --param=ssp-buffer-size=4 -grecord-gcc-switches -m64 -mtune=generic -D_GNU_SOURCE -fPIC -fwrapv -fPIC -I/usr/include/python2.7 -c thriftpy2/transport/cybase.c -o build/temp.linux-x86_64-2.7/thriftpy2/transport/cybase.o
thriftpy2/transport/cybase.c:17:20: fatal error: Python.h: No such file or directory
#include "Python.h"
^
compilation terminated.
error: command 'gcc' failed with exit status 1
----------------------------------------
ERROR: Command errored out with exit status 1: /usr/bin/python2 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-68ikMM/thriftpy2/setup.py'"'"'; file='"'"'/tmp/pip-install-68ikMM/thriftpy2/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(file);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, file, '"'"'exec'"'"'))' install --record /tmp/pip-record-sXHwhY/install-record.txt --single-version-externally-managed --compile Check the logs for full command output.

What's the difference between v1 and v2?

Can you provide some background information about the migration? We used the thriftpy v1 in production environment perfectly and someday my colleague told me v2 had come out. We prefer to do the migration after having enough background knowledge.

Thank in advance.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.