├── src ├── evernote │ ├── edam │ │ ├── __init__.py │ │ ├── error │ │ │ ├── __init__.py │ │ │ ├── constants.py │ │ │ └── ttypes.py │ │ ├── type │ │ │ ├── __init__.py │ │ │ └── constants.py │ │ ├── limits │ │ │ ├── __init__.py │ │ │ ├── ttypes.py │ │ │ └── constants.py │ │ ├── notestore │ │ │ ├── __init__.py │ │ │ ├── constants.py │ │ │ └── NoteStore-remote │ │ └── userstore │ │ │ ├── __init__.py │ │ │ ├── constants.py │ │ │ ├── UserStore-remote │ │ │ └── ttypes.py │ └── __init__.py └── thrift │ ├── __init__.py │ ├── server │ ├── __init__.py │ ├── THttpServer.py │ ├── TServer.py │ └── TNonblockingServer.py │ ├── transport │ ├── __init__.py │ ├── THttpClient.py │ ├── TSocket.py │ ├── TTwisted.py │ └── TTransport.py │ ├── protocol │ ├── __init__.py │ ├── TProtocol.py │ ├── TBinaryProtocol.py │ └── fastbinary.c │ ├── TSCons.py │ ├── TSerialization.py │ └── Thrift.py ├── setup.py └── README.md /src/evernote/edam/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/evernote/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = '1.20' 2 | -------------------------------------------------------------------------------- /src/evernote/edam/error/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['ttypes', 'constants'] 2 | -------------------------------------------------------------------------------- /src/evernote/edam/type/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['ttypes', 'constants'] 2 | -------------------------------------------------------------------------------- /src/evernote/edam/limits/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['ttypes', 'constants'] 2 | -------------------------------------------------------------------------------- /src/evernote/edam/notestore/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['ttypes', 'constants', 'NoteStore'] 2 | -------------------------------------------------------------------------------- /src/evernote/edam/userstore/__init__.py: -------------------------------------------------------------------------------- 1 | __all__ = ['ttypes', 'constants', 'UserStore'] 2 | -------------------------------------------------------------------------------- /src/evernote/edam/error/constants.py: -------------------------------------------------------------------------------- 1 | # 2 | # Autogenerated by Thrift 3 | # 4 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | # 6 | 7 | from thrift.Thrift import * 8 | from ttypes import * 9 | 10 | -------------------------------------------------------------------------------- /src/evernote/edam/notestore/constants.py: -------------------------------------------------------------------------------- 1 | # 2 | # Autogenerated by Thrift 3 | # 4 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | # 6 | 7 | from thrift.Thrift import * 8 | from ttypes import * 9 | 10 | -------------------------------------------------------------------------------- /src/evernote/edam/userstore/constants.py: -------------------------------------------------------------------------------- 1 | # 2 | # Autogenerated by Thrift 3 | # 4 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | # 6 | 7 | from thrift.Thrift import * 8 | from ttypes import * 9 | 10 | EDAM_VERSION_MAJOR = 1 11 | 12 | EDAM_VERSION_MINOR = 20 13 | 14 | -------------------------------------------------------------------------------- /src/evernote/edam/type/constants.py: -------------------------------------------------------------------------------- 1 | # 2 | # Autogenerated by Thrift 3 | # 4 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | # 6 | 7 | from thrift.Thrift import * 8 | from ttypes import * 9 | 10 | EDAM_NOTE_SOURCE_WEB_CLIP = "web.clip" 11 | 12 | EDAM_NOTE_SOURCE_MAIL_CLIP = "mail.clip" 13 | 14 | EDAM_NOTE_SOURCE_MAIL_SMTP_GATEWAY = "mail.smtp" 15 | 16 | -------------------------------------------------------------------------------- /src/evernote/edam/limits/ttypes.py: -------------------------------------------------------------------------------- 1 | # 2 | # Autogenerated by Thrift 3 | # 4 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | # 6 | 7 | from thrift.Thrift import * 8 | 9 | from thrift.transport import TTransport 10 | from thrift.protocol import TBinaryProtocol 11 | try: 12 | from thrift.protocol import fastbinary 13 | except: 14 | fastbinary = None 15 | 16 | 17 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | # Setup script for Evernote API package. 2 | 3 | from setuptools import setup, find_packages 4 | 5 | 6 | setup( 7 | name = 'evernote', 8 | version = '1.20', 9 | author = 'Evernote Corporation', 10 | author_email = 'en-support@evernote.com', 11 | url = 'http://www.evernote.com/about/developer/api/', 12 | description = 'Python bindings to the Evernote API.', 13 | packages = find_packages('src'), 14 | package_dir = {'': 'src'}, 15 | ) 16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | evernote-python-api 2 | =================== 3 | 4 | Python bindings to the Evernote API. 5 | ------------------------------------ 6 | 7 | This is an unofficial package. The code herein is written by Evernote and is 8 | owned by them. More information can be found at http://www.evernote.com/about/developer/api/. 9 | 10 | Greplin has made these additions: 11 | 12 | * a setup.py file 13 | * version info at src/evernote/__init__.py 14 | * this README.md file 15 | 16 | These additions are licensed under the Apache 2 license. 17 | -------------------------------------------------------------------------------- /src/thrift/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | __all__ = ['Thrift', 'TSCons'] 21 | -------------------------------------------------------------------------------- /src/thrift/server/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | __all__ = ['TServer', 'TNonblockingServer'] 21 | -------------------------------------------------------------------------------- /src/thrift/transport/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | __all__ = ['TTransport', 'TSocket', 'THttpClient'] 21 | -------------------------------------------------------------------------------- /src/thrift/protocol/__init__.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | __all__ = ['TProtocol', 'TBinaryProtocol', 'fastbinary'] 21 | -------------------------------------------------------------------------------- /src/thrift/TSCons.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | from os import path 21 | from SCons.Builder import Builder 22 | 23 | def scons_env(env, add=''): 24 | opath = path.dirname(path.abspath('$TARGET')) 25 | lstr = 'thrift --gen cpp -o ' + opath + ' ' + add + ' $SOURCE' 26 | cppbuild = Builder(action = lstr) 27 | env.Append(BUILDERS = {'ThriftCpp' : cppbuild}) 28 | 29 | def gen_cpp(env, dir, file): 30 | scons_env(env) 31 | suffixes = ['_types.h', '_types.cpp'] 32 | targets = map(lambda s: 'gen-cpp/' + file + s, suffixes) 33 | return env.ThriftCpp(targets, dir+file+'.thrift') 34 | -------------------------------------------------------------------------------- /src/thrift/TSerialization.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | from protocol import TBinaryProtocol 21 | from transport import TTransport 22 | 23 | def serialize(thrift_object, protocol_factory = TBinaryProtocol.TBinaryProtocolFactory()): 24 | transport = TTransport.TMemoryBuffer() 25 | protocol = protocol_factory.getProtocol(transport) 26 | thrift_object.write(protocol) 27 | return transport.getvalue() 28 | 29 | def deserialize(base, buf, protocol_factory = TBinaryProtocol.TBinaryProtocolFactory()): 30 | transport = TTransport.TMemoryBuffer(buf) 31 | protocol = protocol_factory.getProtocol(transport) 32 | base.read(protocol) 33 | return base 34 | 35 | -------------------------------------------------------------------------------- /src/thrift/server/THttpServer.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | import BaseHTTPServer 21 | 22 | from thrift.server import TServer 23 | from thrift.transport import TTransport 24 | 25 | class THttpServer(TServer.TServer): 26 | """A simple HTTP-based Thrift server 27 | 28 | This class is not very performant, but it is useful (for example) for 29 | acting as a mock version of an Apache-based PHP Thrift endpoint.""" 30 | 31 | def __init__(self, processor, server_address, 32 | inputProtocolFactory, outputProtocolFactory = None): 33 | """Set up protocol factories and HTTP server. 34 | 35 | See BaseHTTPServer for server_address. 36 | See TServer for protocol factories.""" 37 | 38 | if outputProtocolFactory is None: 39 | outputProtocolFactory = inputProtocolFactory 40 | 41 | TServer.TServer.__init__(self, processor, None, None, None, 42 | inputProtocolFactory, outputProtocolFactory) 43 | 44 | thttpserver = self 45 | 46 | class RequestHander(BaseHTTPServer.BaseHTTPRequestHandler): 47 | def do_POST(self): 48 | # Don't care about the request path. 49 | self.send_response(200) 50 | self.send_header("content-type", "application/x-thrift") 51 | self.end_headers() 52 | 53 | itrans = TTransport.TFileObjectTransport(self.rfile) 54 | otrans = TTransport.TFileObjectTransport(self.wfile) 55 | iprot = thttpserver.inputProtocolFactory.getProtocol(itrans) 56 | oprot = thttpserver.outputProtocolFactory.getProtocol(otrans) 57 | thttpserver.processor.process(iprot, oprot) 58 | otrans.flush() 59 | 60 | self.httpd = BaseHTTPServer.HTTPServer(server_address, RequestHander) 61 | 62 | def serve(self): 63 | self.httpd.serve_forever() 64 | -------------------------------------------------------------------------------- /src/evernote/edam/userstore/UserStore-remote: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Autogenerated by Thrift 4 | # 5 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 6 | # 7 | 8 | import sys 9 | import pprint 10 | from urlparse import urlparse 11 | from thrift.transport import TTransport 12 | from thrift.transport import TSocket 13 | from thrift.transport import THttpClient 14 | from thrift.protocol import TBinaryProtocol 15 | 16 | import UserStore 17 | from ttypes import * 18 | 19 | if len(sys.argv) <= 1 or sys.argv[1] == '--help': 20 | print '' 21 | print 'Usage: ' + sys.argv[0] + ' [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]' 22 | print '' 23 | print 'Functions:' 24 | print ' bool checkVersion(string clientName, i16 edamVersionMajor, i16 edamVersionMinor)' 25 | print ' AuthenticationResult authenticate(string username, string password, string consumerKey, string consumerSecret)' 26 | print ' AuthenticationResult refreshAuthentication(string authenticationToken)' 27 | print ' User getUser(string authenticationToken)' 28 | print ' PublicUserInfo getPublicUserInfo(string username)' 29 | print ' PremiumInfo getPremiumInfo(string authenticationToken)' 30 | print '' 31 | sys.exit(0) 32 | 33 | pp = pprint.PrettyPrinter(indent = 2) 34 | host = 'localhost' 35 | port = 9090 36 | uri = '' 37 | framed = False 38 | http = False 39 | argi = 1 40 | 41 | if sys.argv[argi] == '-h': 42 | parts = sys.argv[argi+1].split(':') 43 | host = parts[0] 44 | port = int(parts[1]) 45 | argi += 2 46 | 47 | if sys.argv[argi] == '-u': 48 | url = urlparse(sys.argv[argi+1]) 49 | parts = url[1].split(':') 50 | host = parts[0] 51 | if len(parts) > 1: 52 | port = int(parts[1]) 53 | else: 54 | port = 80 55 | uri = url[2] 56 | http = True 57 | argi += 2 58 | 59 | if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed': 60 | framed = True 61 | argi += 1 62 | 63 | cmd = sys.argv[argi] 64 | args = sys.argv[argi+1:] 65 | 66 | if http: 67 | transport = THttpClient.THttpClient(host, port, uri) 68 | else: 69 | socket = TSocket.TSocket(host, port) 70 | if framed: 71 | transport = TTransport.TFramedTransport(socket) 72 | else: 73 | transport = TTransport.TBufferedTransport(socket) 74 | protocol = TBinaryProtocol.TBinaryProtocol(transport) 75 | client = UserStore.Client(protocol) 76 | transport.open() 77 | 78 | if cmd == 'checkVersion': 79 | if len(args) != 3: 80 | print 'checkVersion requires 3 args' 81 | sys.exit(1) 82 | pp.pprint(client.checkVersion(args[0],eval(args[1]),eval(args[2]),)) 83 | 84 | elif cmd == 'authenticate': 85 | if len(args) != 4: 86 | print 'authenticate requires 4 args' 87 | sys.exit(1) 88 | pp.pprint(client.authenticate(args[0],args[1],args[2],args[3],)) 89 | 90 | elif cmd == 'refreshAuthentication': 91 | if len(args) != 1: 92 | print 'refreshAuthentication requires 1 args' 93 | sys.exit(1) 94 | pp.pprint(client.refreshAuthentication(args[0],)) 95 | 96 | elif cmd == 'getUser': 97 | if len(args) != 1: 98 | print 'getUser requires 1 args' 99 | sys.exit(1) 100 | pp.pprint(client.getUser(args[0],)) 101 | 102 | elif cmd == 'getPublicUserInfo': 103 | if len(args) != 1: 104 | print 'getPublicUserInfo requires 1 args' 105 | sys.exit(1) 106 | pp.pprint(client.getPublicUserInfo(args[0],)) 107 | 108 | elif cmd == 'getPremiumInfo': 109 | if len(args) != 1: 110 | print 'getPremiumInfo requires 1 args' 111 | sys.exit(1) 112 | pp.pprint(client.getPremiumInfo(args[0],)) 113 | 114 | transport.close() 115 | -------------------------------------------------------------------------------- /src/thrift/Thrift.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | import sys 21 | 22 | class TType: 23 | STOP = 0 24 | VOID = 1 25 | BOOL = 2 26 | BYTE = 3 27 | I08 = 3 28 | DOUBLE = 4 29 | I16 = 6 30 | I32 = 8 31 | I64 = 10 32 | STRING = 11 33 | UTF7 = 11 34 | STRUCT = 12 35 | MAP = 13 36 | SET = 14 37 | LIST = 15 38 | UTF8 = 16 39 | UTF16 = 17 40 | 41 | class TMessageType: 42 | CALL = 1 43 | REPLY = 2 44 | EXCEPTION = 3 45 | ONEWAY = 4 46 | 47 | class TProcessor: 48 | 49 | """Base class for procsessor, which works on two streams.""" 50 | 51 | def process(iprot, oprot): 52 | pass 53 | 54 | class TException(Exception): 55 | 56 | """Base class for all thrift exceptions.""" 57 | 58 | # BaseException.message is deprecated in Python v[2.6,3.0) 59 | if (2,6,0) <= sys.version_info < (3,0): 60 | def _get_message(self): 61 | return self._message 62 | def _set_message(self, message): 63 | self._message = message 64 | message = property(_get_message, _set_message) 65 | 66 | def __init__(self, message=None): 67 | Exception.__init__(self, message) 68 | self.message = message 69 | 70 | class TApplicationException(TException): 71 | 72 | """Application level thrift exceptions.""" 73 | 74 | UNKNOWN = 0 75 | UNKNOWN_METHOD = 1 76 | INVALID_MESSAGE_TYPE = 2 77 | WRONG_METHOD_NAME = 3 78 | BAD_SEQUENCE_ID = 4 79 | MISSING_RESULT = 5 80 | 81 | def __init__(self, type=UNKNOWN, message=None): 82 | TException.__init__(self, message) 83 | self.type = type 84 | 85 | def __str__(self): 86 | if self.message: 87 | return self.message 88 | elif self.type == UNKNOWN_METHOD: 89 | return 'Unknown method' 90 | elif self.type == INVALID_MESSAGE_TYPE: 91 | return 'Invalid message type' 92 | elif self.type == WRONG_METHOD_NAME: 93 | return 'Wrong method name' 94 | elif self.type == BAD_SEQUENCE_ID: 95 | return 'Bad sequence ID' 96 | elif self.type == MISSING_RESULT: 97 | return 'Missing result' 98 | else: 99 | return 'Default (unknown) TApplicationException' 100 | 101 | def read(self, iprot): 102 | iprot.readStructBegin() 103 | while True: 104 | (fname, ftype, fid) = iprot.readFieldBegin() 105 | if ftype == TType.STOP: 106 | break 107 | if fid == 1: 108 | if ftype == TType.STRING: 109 | self.message = iprot.readString(); 110 | else: 111 | iprot.skip(ftype) 112 | elif fid == 2: 113 | if ftype == TType.I32: 114 | self.type = iprot.readI32(); 115 | else: 116 | iprot.skip(ftype) 117 | else: 118 | iprot.skip(ftype) 119 | iprot.readFieldEnd() 120 | iprot.readStructEnd() 121 | 122 | def write(self, oprot): 123 | oprot.writeStructBegin('TApplicationException') 124 | if self.message != None: 125 | oprot.writeFieldBegin('message', TType.STRING, 1) 126 | oprot.writeString(self.message) 127 | oprot.writeFieldEnd() 128 | if self.type != None: 129 | oprot.writeFieldBegin('type', TType.I32, 2) 130 | oprot.writeI32(self.type) 131 | oprot.writeFieldEnd() 132 | oprot.writeFieldStop() 133 | oprot.writeStructEnd() 134 | -------------------------------------------------------------------------------- /src/thrift/transport/THttpClient.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | from TTransport import * 21 | from cStringIO import StringIO 22 | 23 | import urlparse 24 | import httplib 25 | import warnings 26 | import socket 27 | 28 | class THttpClient(TTransportBase): 29 | 30 | """Http implementation of TTransport base.""" 31 | 32 | def __init__(self, uri_or_host, port=None, path=None): 33 | """THttpClient supports two different types constructor parameters. 34 | 35 | THttpClient(host, port, path) - deprecated 36 | THttpClient(uri) 37 | 38 | Only the second supports https.""" 39 | 40 | if port is not None: 41 | warnings.warn("Please use the THttpClient('http://host:port/path') syntax", DeprecationWarning, stacklevel=2) 42 | self.host = uri_or_host 43 | self.port = port 44 | assert path 45 | self.path = path 46 | self.scheme = 'http' 47 | else: 48 | parsed = urlparse.urlparse(uri_or_host) 49 | self.scheme = parsed.scheme 50 | assert self.scheme in ('http', 'https') 51 | if self.scheme == 'http': 52 | self.port = parsed.port or httplib.HTTP_PORT 53 | elif self.scheme == 'https': 54 | self.port = parsed.port or httplib.HTTPS_PORT 55 | self.host = parsed.hostname 56 | self.path = parsed.path 57 | self.__wbuf = StringIO() 58 | self.__http = None 59 | self.__timeout = None 60 | 61 | def open(self): 62 | if self.scheme == 'http': 63 | self.__http = httplib.HTTP(self.host, self.port) 64 | else: 65 | self.__http = httplib.HTTPS(self.host, self.port) 66 | 67 | def close(self): 68 | self.__http.close() 69 | self.__http = None 70 | 71 | def isOpen(self): 72 | return self.__http != None 73 | 74 | def setTimeout(self, ms): 75 | if not hasattr(socket, 'getdefaulttimeout'): 76 | raise NotImplementedError 77 | 78 | if ms is None: 79 | self.__timeout = None 80 | else: 81 | self.__timeout = ms/1000.0 82 | 83 | def read(self, sz): 84 | return self.__http.file.read(sz) 85 | 86 | def write(self, buf): 87 | self.__wbuf.write(buf) 88 | 89 | def __withTimeout(f): 90 | def _f(*args, **kwargs): 91 | orig_timeout = socket.getdefaulttimeout() 92 | socket.setdefaulttimeout(args[0].__timeout) 93 | result = f(*args, **kwargs) 94 | socket.setdefaulttimeout(orig_timeout) 95 | return result 96 | return _f 97 | 98 | def flush(self): 99 | if self.isOpen(): 100 | self.close() 101 | self.open(); 102 | 103 | # Pull data out of buffer 104 | data = self.__wbuf.getvalue() 105 | self.__wbuf = StringIO() 106 | 107 | # HTTP request 108 | self.__http.putrequest('POST', self.path) 109 | 110 | # Write headers 111 | self.__http.putheader('Host', self.host) 112 | self.__http.putheader('Content-Type', 'application/x-thrift') 113 | self.__http.putheader('Content-Length', str(len(data))) 114 | self.__http.endheaders() 115 | 116 | # Write payload 117 | self.__http.send(data) 118 | 119 | # Get reply to flush the request 120 | self.code, self.message, self.headers = self.__http.getreply() 121 | 122 | # Decorate if we know how to timeout 123 | if hasattr(socket, 'getdefaulttimeout'): 124 | flush = __withTimeout(flush) 125 | -------------------------------------------------------------------------------- /src/thrift/protocol/TProtocol.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | from thrift.Thrift import * 21 | 22 | class TProtocolException(TException): 23 | 24 | """Custom Protocol Exception class""" 25 | 26 | UNKNOWN = 0 27 | INVALID_DATA = 1 28 | NEGATIVE_SIZE = 2 29 | SIZE_LIMIT = 3 30 | BAD_VERSION = 4 31 | 32 | def __init__(self, type=UNKNOWN, message=None): 33 | TException.__init__(self, message) 34 | self.type = type 35 | 36 | class TProtocolBase: 37 | 38 | """Base class for Thrift protocol driver.""" 39 | 40 | def __init__(self, trans): 41 | self.trans = trans 42 | 43 | def writeMessageBegin(self, name, type, seqid): 44 | pass 45 | 46 | def writeMessageEnd(self): 47 | pass 48 | 49 | def writeStructBegin(self, name): 50 | pass 51 | 52 | def writeStructEnd(self): 53 | pass 54 | 55 | def writeFieldBegin(self, name, type, id): 56 | pass 57 | 58 | def writeFieldEnd(self): 59 | pass 60 | 61 | def writeFieldStop(self): 62 | pass 63 | 64 | def writeMapBegin(self, ktype, vtype, size): 65 | pass 66 | 67 | def writeMapEnd(self): 68 | pass 69 | 70 | def writeListBegin(self, etype, size): 71 | pass 72 | 73 | def writeListEnd(self): 74 | pass 75 | 76 | def writeSetBegin(self, etype, size): 77 | pass 78 | 79 | def writeSetEnd(self): 80 | pass 81 | 82 | def writeBool(self, bool): 83 | pass 84 | 85 | def writeByte(self, byte): 86 | pass 87 | 88 | def writeI16(self, i16): 89 | pass 90 | 91 | def writeI32(self, i32): 92 | pass 93 | 94 | def writeI64(self, i64): 95 | pass 96 | 97 | def writeDouble(self, dub): 98 | pass 99 | 100 | def writeString(self, str): 101 | pass 102 | 103 | def readMessageBegin(self): 104 | pass 105 | 106 | def readMessageEnd(self): 107 | pass 108 | 109 | def readStructBegin(self): 110 | pass 111 | 112 | def readStructEnd(self): 113 | pass 114 | 115 | def readFieldBegin(self): 116 | pass 117 | 118 | def readFieldEnd(self): 119 | pass 120 | 121 | def readMapBegin(self): 122 | pass 123 | 124 | def readMapEnd(self): 125 | pass 126 | 127 | def readListBegin(self): 128 | pass 129 | 130 | def readListEnd(self): 131 | pass 132 | 133 | def readSetBegin(self): 134 | pass 135 | 136 | def readSetEnd(self): 137 | pass 138 | 139 | def readBool(self): 140 | pass 141 | 142 | def readByte(self): 143 | pass 144 | 145 | def readI16(self): 146 | pass 147 | 148 | def readI32(self): 149 | pass 150 | 151 | def readI64(self): 152 | pass 153 | 154 | def readDouble(self): 155 | pass 156 | 157 | def readString(self): 158 | pass 159 | 160 | def skip(self, type): 161 | if type == TType.STOP: 162 | return 163 | elif type == TType.BOOL: 164 | self.readBool() 165 | elif type == TType.BYTE: 166 | self.readByte() 167 | elif type == TType.I16: 168 | self.readI16() 169 | elif type == TType.I32: 170 | self.readI32() 171 | elif type == TType.I64: 172 | self.readI64() 173 | elif type == TType.DOUBLE: 174 | self.readDouble() 175 | elif type == TType.STRING: 176 | self.readString() 177 | elif type == TType.STRUCT: 178 | name = self.readStructBegin() 179 | while True: 180 | (name, type, id) = self.readFieldBegin() 181 | if type == TType.STOP: 182 | break 183 | self.skip(type) 184 | self.readFieldEnd() 185 | self.readStructEnd() 186 | elif type == TType.MAP: 187 | (ktype, vtype, size) = self.readMapBegin() 188 | for i in range(size): 189 | self.skip(ktype) 190 | self.skip(vtype) 191 | self.readMapEnd() 192 | elif type == TType.SET: 193 | (etype, size) = self.readSetBegin() 194 | for i in range(size): 195 | self.skip(etype) 196 | self.readSetEnd() 197 | elif type == TType.LIST: 198 | (etype, size) = self.readListBegin() 199 | for i in range(size): 200 | self.skip(etype) 201 | self.readListEnd() 202 | 203 | class TProtocolFactory: 204 | def getProtocol(self, trans): 205 | pass 206 | -------------------------------------------------------------------------------- /src/thrift/transport/TSocket.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | from TTransport import * 21 | import os 22 | import errno 23 | import socket 24 | 25 | class TSocketBase(TTransportBase): 26 | def _resolveAddr(self): 27 | if self._unix_socket is not None: 28 | return [(socket.AF_UNIX, socket.SOCK_STREAM, None, None, self._unix_socket)] 29 | else: 30 | return socket.getaddrinfo(self.host, self.port, socket.AF_UNSPEC, socket.SOCK_STREAM, 0, socket.AI_PASSIVE | socket.AI_ADDRCONFIG) 31 | 32 | def close(self): 33 | if self.handle: 34 | self.handle.close() 35 | self.handle = None 36 | 37 | class TSocket(TSocketBase): 38 | """Socket implementation of TTransport base.""" 39 | 40 | def __init__(self, host='localhost', port=9090, unix_socket=None): 41 | """Initialize a TSocket 42 | 43 | @param host(str) The host to connect to. 44 | @param port(int) The (TCP) port to connect to. 45 | @param unix_socket(str) The filename of a unix socket to connect to. 46 | (host and port will be ignored.) 47 | """ 48 | 49 | self.host = host 50 | self.port = port 51 | self.handle = None 52 | self._unix_socket = unix_socket 53 | self._timeout = None 54 | 55 | def setHandle(self, h): 56 | self.handle = h 57 | 58 | def isOpen(self): 59 | return self.handle != None 60 | 61 | def setTimeout(self, ms): 62 | if ms is None: 63 | self._timeout = None 64 | else: 65 | self._timeout = ms/1000.0 66 | 67 | if (self.handle != None): 68 | self.handle.settimeout(self._timeout) 69 | 70 | def open(self): 71 | try: 72 | res0 = self._resolveAddr() 73 | for res in res0: 74 | self.handle = socket.socket(res[0], res[1]) 75 | self.handle.settimeout(self._timeout) 76 | try: 77 | self.handle.connect(res[4]) 78 | except socket.error, e: 79 | if res is not res0[-1]: 80 | continue 81 | else: 82 | raise e 83 | break 84 | except socket.error, e: 85 | if self._unix_socket: 86 | message = 'Could not connect to socket %s' % self._unix_socket 87 | else: 88 | message = 'Could not connect to %s:%d' % (self.host, self.port) 89 | raise TTransportException(type=TTransportException.NOT_OPEN, message=message) 90 | 91 | def read(self, sz): 92 | buff = self.handle.recv(sz) 93 | if len(buff) == 0: 94 | raise TTransportException(type=TTransportException.END_OF_FILE, message='TSocket read 0 bytes') 95 | return buff 96 | 97 | def write(self, buff): 98 | if not self.handle: 99 | raise TTransportException(type=TTransportException.NOT_OPEN, message='Transport not open') 100 | sent = 0 101 | have = len(buff) 102 | while sent < have: 103 | plus = self.handle.send(buff) 104 | if plus == 0: 105 | raise TTransportException(type=TTransportException.END_OF_FILE, message='TSocket sent 0 bytes') 106 | sent += plus 107 | buff = buff[plus:] 108 | 109 | def flush(self): 110 | pass 111 | 112 | class TServerSocket(TSocketBase, TServerTransportBase): 113 | """Socket implementation of TServerTransport base.""" 114 | 115 | def __init__(self, port=9090, unix_socket=None): 116 | self.host = None 117 | self.port = port 118 | self._unix_socket = unix_socket 119 | self.handle = None 120 | 121 | def listen(self): 122 | res0 = self._resolveAddr() 123 | for res in res0: 124 | if res[0] is socket.AF_INET6 or res is res0[-1]: 125 | break 126 | 127 | # We need remove the old unix socket if the file exists and 128 | # nobody is listening on it. 129 | if self._unix_socket: 130 | tmp = socket.socket(res[0], res[1]) 131 | try: 132 | tmp.connect(res[4]) 133 | except socket.error, err: 134 | eno, message = err.args 135 | if eno == errno.ECONNREFUSED: 136 | os.unlink(res[4]) 137 | 138 | self.handle = socket.socket(res[0], res[1]) 139 | self.handle.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) 140 | if hasattr(self.handle, 'set_timeout'): 141 | self.handle.set_timeout(None) 142 | self.handle.bind(res[4]) 143 | self.handle.listen(128) 144 | 145 | def accept(self): 146 | client, addr = self.handle.accept() 147 | result = TSocket() 148 | result.setHandle(client) 149 | return result 150 | -------------------------------------------------------------------------------- /src/evernote/edam/limits/constants.py: -------------------------------------------------------------------------------- 1 | # 2 | # Autogenerated by Thrift 3 | # 4 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | # 6 | 7 | from thrift.Thrift import * 8 | from ttypes import * 9 | 10 | EDAM_ATTRIBUTE_LEN_MIN = 1 11 | 12 | EDAM_ATTRIBUTE_LEN_MAX = 4096 13 | 14 | EDAM_ATTRIBUTE_REGEX = "^[^\\p{Cc}\\p{Zl}\\p{Zp}]{1,4096}$" 15 | 16 | EDAM_ATTRIBUTE_LIST_MAX = 100 17 | 18 | EDAM_ATTRIBUTE_MAP_MAX = 100 19 | 20 | EDAM_GUID_LEN_MIN = 36 21 | 22 | EDAM_GUID_LEN_MAX = 36 23 | 24 | EDAM_GUID_REGEX = "^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$" 25 | 26 | EDAM_EMAIL_LEN_MIN = 6 27 | 28 | EDAM_EMAIL_LEN_MAX = 255 29 | 30 | EDAM_EMAIL_LOCAL_REGEX = "^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(\\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*$" 31 | 32 | EDAM_EMAIL_DOMAIN_REGEX = "^[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*\\.([A-Za-z]{2,})$" 33 | 34 | EDAM_EMAIL_REGEX = "^[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+(\\.[A-Za-z0-9!#$%&'*+/=?^_`{|}~-]+)*@[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)*\\.([A-Za-z]{2,})$" 35 | 36 | EDAM_TIMEZONE_LEN_MIN = 1 37 | 38 | EDAM_TIMEZONE_LEN_MAX = 32 39 | 40 | EDAM_TIMEZONE_REGEX = "^([A-Za-z_-]+(/[A-Za-z_-]+)*)|(GMT(-|\\+)[0-9]{1,2}(:[0-9]{2})?)$" 41 | 42 | EDAM_MIME_LEN_MIN = 3 43 | 44 | EDAM_MIME_LEN_MAX = 255 45 | 46 | EDAM_MIME_REGEX = "^[A-Za-z]+/[A-Za-z0-9._+-]+$" 47 | 48 | EDAM_MIME_TYPE_GIF = "image/gif" 49 | 50 | EDAM_MIME_TYPE_JPEG = "image/jpeg" 51 | 52 | EDAM_MIME_TYPE_PNG = "image/png" 53 | 54 | EDAM_MIME_TYPE_WAV = "audio/wav" 55 | 56 | EDAM_MIME_TYPE_MP3 = "audio/mpeg" 57 | 58 | EDAM_MIME_TYPE_AMR = "audio/amr" 59 | 60 | EDAM_MIME_TYPE_MP4_VIDEO = "video/mp4" 61 | 62 | EDAM_MIME_TYPE_INK = "application/vnd.evernote.ink" 63 | 64 | EDAM_MIME_TYPE_PDF = "application/pdf" 65 | 66 | EDAM_MIME_TYPE_DEFAULT = "application/octet-stream" 67 | 68 | EDAM_MIME_TYPES = set([ 69 | "image/gif", 70 | "image/jpeg", 71 | "image/png", 72 | "audio/wav", 73 | "audio/mpeg", 74 | "audio/amr", 75 | "application/vnd.evernote.ink", 76 | "application/pdf", 77 | "video/mp4", 78 | ]) 79 | 80 | EDAM_COMMERCE_SERVICE_GOOGLE = "Google" 81 | 82 | EDAM_COMMERCE_SERVICE_PAYPAL = "Paypal" 83 | 84 | EDAM_COMMERCE_SERVICE_GIFT = "Gift" 85 | 86 | EDAM_COMMERCE_SERVICE_TRIALPAY = "TrialPay" 87 | 88 | EDAM_COMMERCE_SERVICE_TRIAL = "Trial" 89 | 90 | EDAM_COMMERCE_SERVICE_GROUP = "Group" 91 | 92 | EDAM_COMMERCE_SERVICE_CYBERSOURCE = "CYBERSRC" 93 | 94 | EDAM_COMMERCE_DEFAULT_CURRENCY_COUNTRY_CODE = "USD" 95 | 96 | EDAM_SEARCH_QUERY_LEN_MIN = 0 97 | 98 | EDAM_SEARCH_QUERY_LEN_MAX = 1024 99 | 100 | EDAM_SEARCH_QUERY_REGEX = "^[^\\p{Cc}\\p{Zl}\\p{Zp}]{0,1024}$" 101 | 102 | EDAM_HASH_LEN = 16 103 | 104 | EDAM_USER_USERNAME_LEN_MIN = 1 105 | 106 | EDAM_USER_USERNAME_LEN_MAX = 64 107 | 108 | EDAM_USER_USERNAME_REGEX = "^[a-z0-9]([a-z0-9_-]{0,62}[a-z0-9])?$" 109 | 110 | EDAM_USER_NAME_LEN_MIN = 1 111 | 112 | EDAM_USER_NAME_LEN_MAX = 255 113 | 114 | EDAM_USER_NAME_REGEX = "^[^\\p{Cc}\\p{Zl}\\p{Zp}]{1,255}$" 115 | 116 | EDAM_TAG_NAME_LEN_MIN = 1 117 | 118 | EDAM_TAG_NAME_LEN_MAX = 100 119 | 120 | EDAM_TAG_NAME_REGEX = "^[^,\\p{Cc}\\p{Z}]([^,\\p{Cc}\\p{Zl}\\p{Zp}]{0,98}[^,\\p{Cc}\\p{Z}])?$" 121 | 122 | EDAM_NOTE_TITLE_LEN_MIN = 1 123 | 124 | EDAM_NOTE_TITLE_LEN_MAX = 255 125 | 126 | EDAM_NOTE_TITLE_REGEX = "^[^\\p{Cc}\\p{Z}]([^\\p{Cc}\\p{Zl}\\p{Zp}]{0,253}[^\\p{Cc}\\p{Z}])?$" 127 | 128 | EDAM_NOTE_CONTENT_LEN_MIN = 0 129 | 130 | EDAM_NOTE_CONTENT_LEN_MAX = 5242880 131 | 132 | EDAM_APPLICATIONDATA_NAME_LEN_MIN = 3 133 | 134 | EDAM_APPLICATIONDATA_NAME_LEN_MAX = 32 135 | 136 | EDAM_APPLICATIONDATA_VALUE_LEN_MIN = 0 137 | 138 | EDAM_APPLICATIONDATA_VALUE_LEN_MAX = 4092 139 | 140 | EDAM_APPLICATIONDATA_ENTRY_LEN_MAX = 4095 141 | 142 | EDAM_APPLICATIONDATA_NAME_REGEX = "^[A-Za-z0-9_.-]{3,32}$" 143 | 144 | EDAM_APPLICATIONDATA_VALUE_REGEX = "^[^\\p{Cc}]{0,4092}$" 145 | 146 | EDAM_NOTEBOOK_NAME_LEN_MIN = 1 147 | 148 | EDAM_NOTEBOOK_NAME_LEN_MAX = 100 149 | 150 | EDAM_NOTEBOOK_NAME_REGEX = "^[^\\p{Cc}\\p{Z}]([^\\p{Cc}\\p{Zl}\\p{Zp}]{0,98}[^\\p{Cc}\\p{Z}])?$" 151 | 152 | EDAM_NOTEBOOK_STACK_LEN_MIN = 1 153 | 154 | EDAM_NOTEBOOK_STACK_LEN_MAX = 100 155 | 156 | EDAM_NOTEBOOK_STACK_REGEX = "^[^\\p{Cc}\\p{Z}]([^\\p{Cc}\\p{Zl}\\p{Zp}]{0,98}[^\\p{Cc}\\p{Z}])?$" 157 | 158 | EDAM_PUBLISHING_URI_LEN_MIN = 1 159 | 160 | EDAM_PUBLISHING_URI_LEN_MAX = 255 161 | 162 | EDAM_PUBLISHING_URI_REGEX = "^[a-zA-Z0-9.~_+-]{1,255}$" 163 | 164 | EDAM_PUBLISHING_URI_PROHIBITED = set([ 165 | "..", 166 | ]) 167 | 168 | EDAM_PUBLISHING_DESCRIPTION_LEN_MIN = 1 169 | 170 | EDAM_PUBLISHING_DESCRIPTION_LEN_MAX = 200 171 | 172 | EDAM_PUBLISHING_DESCRIPTION_REGEX = "^[^\\p{Cc}\\p{Z}]([^\\p{Cc}\\p{Zl}\\p{Zp}]{0,198}[^\\p{Cc}\\p{Z}])?$" 173 | 174 | EDAM_SAVED_SEARCH_NAME_LEN_MIN = 1 175 | 176 | EDAM_SAVED_SEARCH_NAME_LEN_MAX = 100 177 | 178 | EDAM_SAVED_SEARCH_NAME_REGEX = "^[^\\p{Cc}\\p{Z}]([^\\p{Cc}\\p{Zl}\\p{Zp}]{0,98}[^\\p{Cc}\\p{Z}])?$" 179 | 180 | EDAM_USER_PASSWORD_LEN_MIN = 6 181 | 182 | EDAM_USER_PASSWORD_LEN_MAX = 64 183 | 184 | EDAM_USER_PASSWORD_REGEX = "^[A-Za-z0-9!#$%&'()*+,./:;<=>?@^_`{|}~\\[\\]\\\\-]{6,64}$" 185 | 186 | EDAM_NOTE_TAGS_MAX = 100 187 | 188 | EDAM_NOTE_RESOURCES_MAX = 1000 189 | 190 | EDAM_USER_TAGS_MAX = 100000 191 | 192 | EDAM_USER_SAVED_SEARCHES_MAX = 100 193 | 194 | EDAM_USER_NOTES_MAX = 100000 195 | 196 | EDAM_USER_NOTEBOOKS_MAX = 250 197 | 198 | EDAM_USER_RECENT_MAILED_ADDRESSES_MAX = 10 199 | 200 | EDAM_USER_MAIL_LIMIT_DAILY_FREE = 50 201 | 202 | EDAM_USER_MAIL_LIMIT_DAILY_PREMIUM = 200 203 | 204 | EDAM_USER_UPLOAD_LIMIT_FREE = 62914560 205 | 206 | EDAM_USER_UPLOAD_LIMIT_PREMIUM = 1073741824 207 | 208 | EDAM_NOTE_SIZE_MAX_FREE = 26214400 209 | 210 | EDAM_NOTE_SIZE_MAX_PREMIUM = 52428800 211 | 212 | EDAM_RESOURCE_SIZE_MAX_FREE = 26214400 213 | 214 | EDAM_RESOURCE_SIZE_MAX_PREMIUM = 52428800 215 | 216 | EDAM_USER_LINKED_NOTEBOOK_MAX = 100 217 | 218 | EDAM_NOTEBOOK_SHARED_NOTEBOOK_MAX = 250 219 | 220 | EDAM_NOTE_CONTENT_CLASS_LEN_MIN = 3 221 | 222 | EDAM_NOTE_CONTENT_CLASS_LEN_MAX = 32 223 | 224 | EDAM_HELLO_APP_CONTENT_CLASS_PREFIX = "evernote.hello." 225 | 226 | EDAM_FOOD_APP_CONTENT_CLASS_PREFIX = "evernote.food." 227 | 228 | EDAM_NOTE_CONTENT_CLASS_REGEX = "^[A-Za-z0-9_.-]{3,32}$" 229 | 230 | EDAM_CONTENT_CLASS_HELLO_ENCOUNTER = "evernote.hello.encounter" 231 | 232 | EDAM_CONTENT_CLASS_HELLO_PROFILE = "evernote.hello.profile" 233 | 234 | EDAM_CONTENT_CLASS_FOOD_MEAL = "evernote.food.meal" 235 | 236 | -------------------------------------------------------------------------------- /src/thrift/transport/TTwisted.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | from zope.interface import implements, Interface, Attribute 20 | from twisted.internet.protocol import Protocol, ServerFactory, ClientFactory, \ 21 | connectionDone 22 | from twisted.internet import defer 23 | from twisted.protocols import basic 24 | from twisted.python import log 25 | from twisted.web import server, resource, http 26 | 27 | from thrift.transport import TTransport 28 | from cStringIO import StringIO 29 | 30 | 31 | class TMessageSenderTransport(TTransport.TTransportBase): 32 | 33 | def __init__(self): 34 | self.__wbuf = StringIO() 35 | 36 | def write(self, buf): 37 | self.__wbuf.write(buf) 38 | 39 | def flush(self): 40 | msg = self.__wbuf.getvalue() 41 | self.__wbuf = StringIO() 42 | self.sendMessage(msg) 43 | 44 | def sendMessage(self, message): 45 | raise NotImplementedError 46 | 47 | 48 | class TCallbackTransport(TMessageSenderTransport): 49 | 50 | def __init__(self, func): 51 | TMessageSenderTransport.__init__(self) 52 | self.func = func 53 | 54 | def sendMessage(self, message): 55 | self.func(message) 56 | 57 | 58 | class ThriftClientProtocol(basic.Int32StringReceiver): 59 | 60 | MAX_LENGTH = 2 ** 31 - 1 61 | 62 | def __init__(self, client_class, iprot_factory, oprot_factory=None): 63 | self._client_class = client_class 64 | self._iprot_factory = iprot_factory 65 | if oprot_factory is None: 66 | self._oprot_factory = iprot_factory 67 | else: 68 | self._oprot_factory = oprot_factory 69 | 70 | self.recv_map = {} 71 | self.started = defer.Deferred() 72 | 73 | def dispatch(self, msg): 74 | self.sendString(msg) 75 | 76 | def connectionMade(self): 77 | tmo = TCallbackTransport(self.dispatch) 78 | self.client = self._client_class(tmo, self._oprot_factory) 79 | self.started.callback(self.client) 80 | 81 | def connectionLost(self, reason=connectionDone): 82 | for k,v in self.client._reqs.iteritems(): 83 | tex = TTransport.TTransportException( 84 | type=TTransport.TTransportException.END_OF_FILE, 85 | message='Connection closed') 86 | v.errback(tex) 87 | 88 | def stringReceived(self, frame): 89 | tr = TTransport.TMemoryBuffer(frame) 90 | iprot = self._iprot_factory.getProtocol(tr) 91 | (fname, mtype, rseqid) = iprot.readMessageBegin() 92 | 93 | try: 94 | method = self.recv_map[fname] 95 | except KeyError: 96 | method = getattr(self.client, 'recv_' + fname) 97 | self.recv_map[fname] = method 98 | 99 | method(iprot, mtype, rseqid) 100 | 101 | 102 | class ThriftServerProtocol(basic.Int32StringReceiver): 103 | 104 | MAX_LENGTH = 2 ** 31 - 1 105 | 106 | def dispatch(self, msg): 107 | self.sendString(msg) 108 | 109 | def processError(self, error): 110 | self.transport.loseConnection() 111 | 112 | def processOk(self, _, tmo): 113 | msg = tmo.getvalue() 114 | 115 | if len(msg) > 0: 116 | self.dispatch(msg) 117 | 118 | def stringReceived(self, frame): 119 | tmi = TTransport.TMemoryBuffer(frame) 120 | tmo = TTransport.TMemoryBuffer() 121 | 122 | iprot = self.factory.iprot_factory.getProtocol(tmi) 123 | oprot = self.factory.oprot_factory.getProtocol(tmo) 124 | 125 | d = self.factory.processor.process(iprot, oprot) 126 | d.addCallbacks(self.processOk, self.processError, 127 | callbackArgs=(tmo,)) 128 | 129 | 130 | class IThriftServerFactory(Interface): 131 | 132 | processor = Attribute("Thrift processor") 133 | 134 | iprot_factory = Attribute("Input protocol factory") 135 | 136 | oprot_factory = Attribute("Output protocol factory") 137 | 138 | 139 | class IThriftClientFactory(Interface): 140 | 141 | client_class = Attribute("Thrift client class") 142 | 143 | iprot_factory = Attribute("Input protocol factory") 144 | 145 | oprot_factory = Attribute("Output protocol factory") 146 | 147 | 148 | class ThriftServerFactory(ServerFactory): 149 | 150 | implements(IThriftServerFactory) 151 | 152 | protocol = ThriftServerProtocol 153 | 154 | def __init__(self, processor, iprot_factory, oprot_factory=None): 155 | self.processor = processor 156 | self.iprot_factory = iprot_factory 157 | if oprot_factory is None: 158 | self.oprot_factory = iprot_factory 159 | else: 160 | self.oprot_factory = oprot_factory 161 | 162 | 163 | class ThriftClientFactory(ClientFactory): 164 | 165 | implements(IThriftClientFactory) 166 | 167 | protocol = ThriftClientProtocol 168 | 169 | def __init__(self, client_class, iprot_factory, oprot_factory=None): 170 | self.client_class = client_class 171 | self.iprot_factory = iprot_factory 172 | if oprot_factory is None: 173 | self.oprot_factory = iprot_factory 174 | else: 175 | self.oprot_factory = oprot_factory 176 | 177 | def buildProtocol(self, addr): 178 | p = self.protocol(self.client_class, self.iprot_factory, 179 | self.oprot_factory) 180 | p.factory = self 181 | return p 182 | 183 | 184 | class ThriftResource(resource.Resource): 185 | 186 | allowedMethods = ('POST',) 187 | 188 | def __init__(self, processor, inputProtocolFactory, 189 | outputProtocolFactory=None): 190 | resource.Resource.__init__(self) 191 | self.inputProtocolFactory = inputProtocolFactory 192 | if outputProtocolFactory is None: 193 | self.outputProtocolFactory = inputProtocolFactory 194 | else: 195 | self.outputProtocolFactory = outputProtocolFactory 196 | self.processor = processor 197 | 198 | def getChild(self, path, request): 199 | return self 200 | 201 | def _cbProcess(self, _, request, tmo): 202 | msg = tmo.getvalue() 203 | request.setResponseCode(http.OK) 204 | request.setHeader("content-type", "application/x-thrift") 205 | request.write(msg) 206 | request.finish() 207 | 208 | def render_POST(self, request): 209 | request.content.seek(0, 0) 210 | data = request.content.read() 211 | tmi = TTransport.TMemoryBuffer(data) 212 | tmo = TTransport.TMemoryBuffer() 213 | 214 | iprot = self.inputProtocolFactory.getProtocol(tmi) 215 | oprot = self.outputProtocolFactory.getProtocol(tmo) 216 | 217 | d = self.processor.process(iprot, oprot) 218 | d.addCallback(self._cbProcess, request, tmo) 219 | return server.NOT_DONE_YET 220 | -------------------------------------------------------------------------------- /src/thrift/protocol/TBinaryProtocol.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | from TProtocol import * 21 | from struct import pack, unpack 22 | 23 | class TBinaryProtocol(TProtocolBase): 24 | 25 | """Binary implementation of the Thrift protocol driver.""" 26 | 27 | # NastyHaxx. Python 2.4+ on 32-bit machines forces hex constants to be 28 | # positive, converting this into a long. If we hardcode the int value 29 | # instead it'll stay in 32 bit-land. 30 | 31 | # VERSION_MASK = 0xffff0000 32 | VERSION_MASK = -65536 33 | 34 | # VERSION_1 = 0x80010000 35 | VERSION_1 = -2147418112 36 | 37 | TYPE_MASK = 0x000000ff 38 | 39 | def __init__(self, trans, strictRead=False, strictWrite=True): 40 | TProtocolBase.__init__(self, trans) 41 | self.strictRead = strictRead 42 | self.strictWrite = strictWrite 43 | 44 | def writeMessageBegin(self, name, type, seqid): 45 | if self.strictWrite: 46 | self.writeI32(TBinaryProtocol.VERSION_1 | type) 47 | self.writeString(name) 48 | self.writeI32(seqid) 49 | else: 50 | self.writeString(name) 51 | self.writeByte(type) 52 | self.writeI32(seqid) 53 | 54 | def writeMessageEnd(self): 55 | pass 56 | 57 | def writeStructBegin(self, name): 58 | pass 59 | 60 | def writeStructEnd(self): 61 | pass 62 | 63 | def writeFieldBegin(self, name, type, id): 64 | self.writeByte(type) 65 | self.writeI16(id) 66 | 67 | def writeFieldEnd(self): 68 | pass 69 | 70 | def writeFieldStop(self): 71 | self.writeByte(TType.STOP); 72 | 73 | def writeMapBegin(self, ktype, vtype, size): 74 | self.writeByte(ktype) 75 | self.writeByte(vtype) 76 | self.writeI32(size) 77 | 78 | def writeMapEnd(self): 79 | pass 80 | 81 | def writeListBegin(self, etype, size): 82 | self.writeByte(etype) 83 | self.writeI32(size) 84 | 85 | def writeListEnd(self): 86 | pass 87 | 88 | def writeSetBegin(self, etype, size): 89 | self.writeByte(etype) 90 | self.writeI32(size) 91 | 92 | def writeSetEnd(self): 93 | pass 94 | 95 | def writeBool(self, bool): 96 | if bool: 97 | self.writeByte(1) 98 | else: 99 | self.writeByte(0) 100 | 101 | def writeByte(self, byte): 102 | buff = pack("!b", byte) 103 | self.trans.write(buff) 104 | 105 | def writeI16(self, i16): 106 | buff = pack("!h", i16) 107 | self.trans.write(buff) 108 | 109 | def writeI32(self, i32): 110 | buff = pack("!i", i32) 111 | self.trans.write(buff) 112 | 113 | def writeI64(self, i64): 114 | buff = pack("!q", i64) 115 | self.trans.write(buff) 116 | 117 | def writeDouble(self, dub): 118 | buff = pack("!d", dub) 119 | self.trans.write(buff) 120 | 121 | def writeString(self, str): 122 | self.writeI32(len(str)) 123 | self.trans.write(str) 124 | 125 | def readMessageBegin(self): 126 | sz = self.readI32() 127 | if sz < 0: 128 | version = sz & TBinaryProtocol.VERSION_MASK 129 | if version != TBinaryProtocol.VERSION_1: 130 | raise TProtocolException(type=TProtocolException.BAD_VERSION, message='Bad version in readMessageBegin: %d' % (sz)) 131 | type = sz & TBinaryProtocol.TYPE_MASK 132 | name = self.readString() 133 | seqid = self.readI32() 134 | else: 135 | if self.strictRead: 136 | raise TProtocolException(type=TProtocolException.BAD_VERSION, message='No protocol version header') 137 | name = self.trans.readAll(sz) 138 | type = self.readByte() 139 | seqid = self.readI32() 140 | return (name, type, seqid) 141 | 142 | def readMessageEnd(self): 143 | pass 144 | 145 | def readStructBegin(self): 146 | pass 147 | 148 | def readStructEnd(self): 149 | pass 150 | 151 | def readFieldBegin(self): 152 | type = self.readByte() 153 | if type == TType.STOP: 154 | return (None, type, 0) 155 | id = self.readI16() 156 | return (None, type, id) 157 | 158 | def readFieldEnd(self): 159 | pass 160 | 161 | def readMapBegin(self): 162 | ktype = self.readByte() 163 | vtype = self.readByte() 164 | size = self.readI32() 165 | return (ktype, vtype, size) 166 | 167 | def readMapEnd(self): 168 | pass 169 | 170 | def readListBegin(self): 171 | etype = self.readByte() 172 | size = self.readI32() 173 | return (etype, size) 174 | 175 | def readListEnd(self): 176 | pass 177 | 178 | def readSetBegin(self): 179 | etype = self.readByte() 180 | size = self.readI32() 181 | return (etype, size) 182 | 183 | def readSetEnd(self): 184 | pass 185 | 186 | def readBool(self): 187 | byte = self.readByte() 188 | if byte == 0: 189 | return False 190 | return True 191 | 192 | def readByte(self): 193 | buff = self.trans.readAll(1) 194 | val, = unpack('!b', buff) 195 | return val 196 | 197 | def readI16(self): 198 | buff = self.trans.readAll(2) 199 | val, = unpack('!h', buff) 200 | return val 201 | 202 | def readI32(self): 203 | buff = self.trans.readAll(4) 204 | val, = unpack('!i', buff) 205 | return val 206 | 207 | def readI64(self): 208 | buff = self.trans.readAll(8) 209 | val, = unpack('!q', buff) 210 | return val 211 | 212 | def readDouble(self): 213 | buff = self.trans.readAll(8) 214 | val, = unpack('!d', buff) 215 | return val 216 | 217 | def readString(self): 218 | len = self.readI32() 219 | str = self.trans.readAll(len) 220 | return str 221 | 222 | 223 | class TBinaryProtocolFactory: 224 | def __init__(self, strictRead=False, strictWrite=True): 225 | self.strictRead = strictRead 226 | self.strictWrite = strictWrite 227 | 228 | def getProtocol(self, trans): 229 | prot = TBinaryProtocol(trans, self.strictRead, self.strictWrite) 230 | return prot 231 | 232 | 233 | class TBinaryProtocolAccelerated(TBinaryProtocol): 234 | 235 | """C-Accelerated version of TBinaryProtocol. 236 | 237 | This class does not override any of TBinaryProtocol's methods, 238 | but the generated code recognizes it directly and will call into 239 | our C module to do the encoding, bypassing this object entirely. 240 | We inherit from TBinaryProtocol so that the normal TBinaryProtocol 241 | encoding can happen if the fastbinary module doesn't work for some 242 | reason. (TODO(dreiss): Make this happen sanely in more cases.) 243 | 244 | In order to take advantage of the C module, just use 245 | TBinaryProtocolAccelerated instead of TBinaryProtocol. 246 | 247 | NOTE: This code was contributed by an external developer. 248 | The internal Thrift team has reviewed and tested it, 249 | but we cannot guarantee that it is production-ready. 250 | Please feel free to report bugs and/or success stories 251 | to the public mailing list. 252 | """ 253 | 254 | pass 255 | 256 | 257 | class TBinaryProtocolAcceleratedFactory: 258 | def getProtocol(self, trans): 259 | return TBinaryProtocolAccelerated(trans) 260 | -------------------------------------------------------------------------------- /src/thrift/server/TServer.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | import logging 21 | import sys 22 | import os 23 | import traceback 24 | import threading 25 | import Queue 26 | 27 | from thrift.Thrift import TProcessor 28 | from thrift.transport import TTransport 29 | from thrift.protocol import TBinaryProtocol 30 | 31 | class TServer: 32 | 33 | """Base interface for a server, which must have a serve method.""" 34 | 35 | """ 3 constructors for all servers: 36 | 1) (processor, serverTransport) 37 | 2) (processor, serverTransport, transportFactory, protocolFactory) 38 | 3) (processor, serverTransport, 39 | inputTransportFactory, outputTransportFactory, 40 | inputProtocolFactory, outputProtocolFactory)""" 41 | def __init__(self, *args): 42 | if (len(args) == 2): 43 | self.__initArgs__(args[0], args[1], 44 | TTransport.TTransportFactoryBase(), 45 | TTransport.TTransportFactoryBase(), 46 | TBinaryProtocol.TBinaryProtocolFactory(), 47 | TBinaryProtocol.TBinaryProtocolFactory()) 48 | elif (len(args) == 4): 49 | self.__initArgs__(args[0], args[1], args[2], args[2], args[3], args[3]) 50 | elif (len(args) == 6): 51 | self.__initArgs__(args[0], args[1], args[2], args[3], args[4], args[5]) 52 | 53 | def __initArgs__(self, processor, serverTransport, 54 | inputTransportFactory, outputTransportFactory, 55 | inputProtocolFactory, outputProtocolFactory): 56 | self.processor = processor 57 | self.serverTransport = serverTransport 58 | self.inputTransportFactory = inputTransportFactory 59 | self.outputTransportFactory = outputTransportFactory 60 | self.inputProtocolFactory = inputProtocolFactory 61 | self.outputProtocolFactory = outputProtocolFactory 62 | 63 | def serve(self): 64 | pass 65 | 66 | class TSimpleServer(TServer): 67 | 68 | """Simple single-threaded server that just pumps around one transport.""" 69 | 70 | def __init__(self, *args): 71 | TServer.__init__(self, *args) 72 | 73 | def serve(self): 74 | self.serverTransport.listen() 75 | while True: 76 | client = self.serverTransport.accept() 77 | itrans = self.inputTransportFactory.getTransport(client) 78 | otrans = self.outputTransportFactory.getTransport(client) 79 | iprot = self.inputProtocolFactory.getProtocol(itrans) 80 | oprot = self.outputProtocolFactory.getProtocol(otrans) 81 | try: 82 | while True: 83 | self.processor.process(iprot, oprot) 84 | except TTransport.TTransportException, tx: 85 | pass 86 | except Exception, x: 87 | logging.exception(x) 88 | 89 | itrans.close() 90 | otrans.close() 91 | 92 | class TThreadedServer(TServer): 93 | 94 | """Threaded server that spawns a new thread per each connection.""" 95 | 96 | def __init__(self, *args): 97 | TServer.__init__(self, *args) 98 | 99 | def serve(self): 100 | self.serverTransport.listen() 101 | while True: 102 | try: 103 | client = self.serverTransport.accept() 104 | t = threading.Thread(target = self.handle, args=(client,)) 105 | t.start() 106 | except KeyboardInterrupt: 107 | raise 108 | except Exception, x: 109 | logging.exception(x) 110 | 111 | def handle(self, client): 112 | itrans = self.inputTransportFactory.getTransport(client) 113 | otrans = self.outputTransportFactory.getTransport(client) 114 | iprot = self.inputProtocolFactory.getProtocol(itrans) 115 | oprot = self.outputProtocolFactory.getProtocol(otrans) 116 | try: 117 | while True: 118 | self.processor.process(iprot, oprot) 119 | except TTransport.TTransportException, tx: 120 | pass 121 | except Exception, x: 122 | logging.exception(x) 123 | 124 | itrans.close() 125 | otrans.close() 126 | 127 | class TThreadPoolServer(TServer): 128 | 129 | """Server with a fixed size pool of threads which service requests.""" 130 | 131 | def __init__(self, *args): 132 | TServer.__init__(self, *args) 133 | self.clients = Queue.Queue() 134 | self.threads = 10 135 | 136 | def setNumThreads(self, num): 137 | """Set the number of worker threads that should be created""" 138 | self.threads = num 139 | 140 | def serveThread(self): 141 | """Loop around getting clients from the shared queue and process them.""" 142 | while True: 143 | try: 144 | client = self.clients.get() 145 | self.serveClient(client) 146 | except Exception, x: 147 | logging.exception(x) 148 | 149 | def serveClient(self, client): 150 | """Process input/output from a client for as long as possible""" 151 | itrans = self.inputTransportFactory.getTransport(client) 152 | otrans = self.outputTransportFactory.getTransport(client) 153 | iprot = self.inputProtocolFactory.getProtocol(itrans) 154 | oprot = self.outputProtocolFactory.getProtocol(otrans) 155 | try: 156 | while True: 157 | self.processor.process(iprot, oprot) 158 | except TTransport.TTransportException, tx: 159 | pass 160 | except Exception, x: 161 | logging.exception(x) 162 | 163 | itrans.close() 164 | otrans.close() 165 | 166 | def serve(self): 167 | """Start a fixed number of worker threads and put client into a queue""" 168 | for i in range(self.threads): 169 | try: 170 | t = threading.Thread(target = self.serveThread) 171 | t.start() 172 | except Exception, x: 173 | logging.exception(x) 174 | 175 | # Pump the socket for clients 176 | self.serverTransport.listen() 177 | while True: 178 | try: 179 | client = self.serverTransport.accept() 180 | self.clients.put(client) 181 | except Exception, x: 182 | logging.exception(x) 183 | 184 | 185 | class TForkingServer(TServer): 186 | 187 | """A Thrift server that forks a new process for each request""" 188 | """ 189 | This is more scalable than the threaded server as it does not cause 190 | GIL contention. 191 | 192 | Note that this has different semantics from the threading server. 193 | Specifically, updates to shared variables will no longer be shared. 194 | It will also not work on windows. 195 | 196 | This code is heavily inspired by SocketServer.ForkingMixIn in the 197 | Python stdlib. 198 | """ 199 | 200 | def __init__(self, *args): 201 | TServer.__init__(self, *args) 202 | self.children = [] 203 | 204 | def serve(self): 205 | def try_close(file): 206 | try: 207 | file.close() 208 | except IOError, e: 209 | logging.warning(e, exc_info=True) 210 | 211 | 212 | self.serverTransport.listen() 213 | while True: 214 | client = self.serverTransport.accept() 215 | try: 216 | pid = os.fork() 217 | 218 | if pid: # parent 219 | # add before collect, otherwise you race w/ waitpid 220 | self.children.append(pid) 221 | self.collect_children() 222 | 223 | # Parent must close socket or the connection may not get 224 | # closed promptly 225 | itrans = self.inputTransportFactory.getTransport(client) 226 | otrans = self.outputTransportFactory.getTransport(client) 227 | try_close(itrans) 228 | try_close(otrans) 229 | else: 230 | itrans = self.inputTransportFactory.getTransport(client) 231 | otrans = self.outputTransportFactory.getTransport(client) 232 | 233 | iprot = self.inputProtocolFactory.getProtocol(itrans) 234 | oprot = self.outputProtocolFactory.getProtocol(otrans) 235 | 236 | ecode = 0 237 | try: 238 | try: 239 | while True: 240 | self.processor.process(iprot, oprot) 241 | except TTransport.TTransportException, tx: 242 | pass 243 | except Exception, e: 244 | logging.exception(e) 245 | ecode = 1 246 | finally: 247 | try_close(itrans) 248 | try_close(otrans) 249 | 250 | os._exit(ecode) 251 | 252 | except TTransport.TTransportException, tx: 253 | pass 254 | except Exception, x: 255 | logging.exception(x) 256 | 257 | 258 | def collect_children(self): 259 | while self.children: 260 | try: 261 | pid, status = os.waitpid(0, os.WNOHANG) 262 | except os.error: 263 | pid = None 264 | 265 | if pid: 266 | self.children.remove(pid) 267 | else: 268 | break 269 | 270 | 271 | -------------------------------------------------------------------------------- /src/thrift/transport/TTransport.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | 20 | from cStringIO import StringIO 21 | from struct import pack,unpack 22 | from thrift.Thrift import TException 23 | 24 | class TTransportException(TException): 25 | 26 | """Custom Transport Exception class""" 27 | 28 | UNKNOWN = 0 29 | NOT_OPEN = 1 30 | ALREADY_OPEN = 2 31 | TIMED_OUT = 3 32 | END_OF_FILE = 4 33 | 34 | def __init__(self, type=UNKNOWN, message=None): 35 | TException.__init__(self, message) 36 | self.type = type 37 | 38 | class TTransportBase: 39 | 40 | """Base class for Thrift transport layer.""" 41 | 42 | def isOpen(self): 43 | pass 44 | 45 | def open(self): 46 | pass 47 | 48 | def close(self): 49 | pass 50 | 51 | def read(self, sz): 52 | pass 53 | 54 | def readAll(self, sz): 55 | buff = '' 56 | have = 0 57 | while (have < sz): 58 | chunk = self.read(sz-have) 59 | have += len(chunk) 60 | buff += chunk 61 | 62 | if len(chunk) == 0: 63 | raise EOFError() 64 | 65 | return buff 66 | 67 | def write(self, buf): 68 | pass 69 | 70 | def flush(self): 71 | pass 72 | 73 | # This class should be thought of as an interface. 74 | class CReadableTransport: 75 | """base class for transports that are readable from C""" 76 | 77 | # TODO(dreiss): Think about changing this interface to allow us to use 78 | # a (Python, not c) StringIO instead, because it allows 79 | # you to write after reading. 80 | 81 | # NOTE: This is a classic class, so properties will NOT work 82 | # correctly for setting. 83 | @property 84 | def cstringio_buf(self): 85 | """A cStringIO buffer that contains the current chunk we are reading.""" 86 | pass 87 | 88 | def cstringio_refill(self, partialread, reqlen): 89 | """Refills cstringio_buf. 90 | 91 | Returns the currently used buffer (which can but need not be the same as 92 | the old cstringio_buf). partialread is what the C code has read from the 93 | buffer, and should be inserted into the buffer before any more reads. The 94 | return value must be a new, not borrowed reference. Something along the 95 | lines of self._buf should be fine. 96 | 97 | If reqlen bytes can't be read, throw EOFError. 98 | """ 99 | pass 100 | 101 | class TServerTransportBase: 102 | 103 | """Base class for Thrift server transports.""" 104 | 105 | def listen(self): 106 | pass 107 | 108 | def accept(self): 109 | pass 110 | 111 | def close(self): 112 | pass 113 | 114 | class TTransportFactoryBase: 115 | 116 | """Base class for a Transport Factory""" 117 | 118 | def getTransport(self, trans): 119 | return trans 120 | 121 | class TBufferedTransportFactory: 122 | 123 | """Factory transport that builds buffered transports""" 124 | 125 | def getTransport(self, trans): 126 | buffered = TBufferedTransport(trans) 127 | return buffered 128 | 129 | 130 | class TBufferedTransport(TTransportBase,CReadableTransport): 131 | 132 | """Class that wraps another transport and buffers its I/O.""" 133 | 134 | DEFAULT_BUFFER = 4096 135 | 136 | def __init__(self, trans): 137 | self.__trans = trans 138 | self.__wbuf = StringIO() 139 | self.__rbuf = StringIO("") 140 | 141 | def isOpen(self): 142 | return self.__trans.isOpen() 143 | 144 | def open(self): 145 | return self.__trans.open() 146 | 147 | def close(self): 148 | return self.__trans.close() 149 | 150 | def read(self, sz): 151 | ret = self.__rbuf.read(sz) 152 | if len(ret) != 0: 153 | return ret 154 | 155 | self.__rbuf = StringIO(self.__trans.read(max(sz, self.DEFAULT_BUFFER))) 156 | return self.__rbuf.read(sz) 157 | 158 | def write(self, buf): 159 | self.__wbuf.write(buf) 160 | 161 | def flush(self): 162 | out = self.__wbuf.getvalue() 163 | # reset wbuf before write/flush to preserve state on underlying failure 164 | self.__wbuf = StringIO() 165 | self.__trans.write(out) 166 | self.__trans.flush() 167 | 168 | # Implement the CReadableTransport interface. 169 | @property 170 | def cstringio_buf(self): 171 | return self.__rbuf 172 | 173 | def cstringio_refill(self, partialread, reqlen): 174 | retstring = partialread 175 | if reqlen < self.DEFAULT_BUFFER: 176 | # try to make a read of as much as we can. 177 | retstring += self.__trans.read(self.DEFAULT_BUFFER) 178 | 179 | # but make sure we do read reqlen bytes. 180 | if len(retstring) < reqlen: 181 | retstring += self.__trans.readAll(reqlen - len(retstring)) 182 | 183 | self.__rbuf = StringIO(retstring) 184 | return self.__rbuf 185 | 186 | class TMemoryBuffer(TTransportBase, CReadableTransport): 187 | """Wraps a cStringIO object as a TTransport. 188 | 189 | NOTE: Unlike the C++ version of this class, you cannot write to it 190 | then immediately read from it. If you want to read from a 191 | TMemoryBuffer, you must either pass a string to the constructor. 192 | TODO(dreiss): Make this work like the C++ version. 193 | """ 194 | 195 | def __init__(self, value=None): 196 | """value -- a value to read from for stringio 197 | 198 | If value is set, this will be a transport for reading, 199 | otherwise, it is for writing""" 200 | if value is not None: 201 | self._buffer = StringIO(value) 202 | else: 203 | self._buffer = StringIO() 204 | 205 | def isOpen(self): 206 | return not self._buffer.closed 207 | 208 | def open(self): 209 | pass 210 | 211 | def close(self): 212 | self._buffer.close() 213 | 214 | def read(self, sz): 215 | return self._buffer.read(sz) 216 | 217 | def write(self, buf): 218 | self._buffer.write(buf) 219 | 220 | def flush(self): 221 | pass 222 | 223 | def getvalue(self): 224 | return self._buffer.getvalue() 225 | 226 | # Implement the CReadableTransport interface. 227 | @property 228 | def cstringio_buf(self): 229 | return self._buffer 230 | 231 | def cstringio_refill(self, partialread, reqlen): 232 | # only one shot at reading... 233 | raise EOFError() 234 | 235 | class TFramedTransportFactory: 236 | 237 | """Factory transport that builds framed transports""" 238 | 239 | def getTransport(self, trans): 240 | framed = TFramedTransport(trans) 241 | return framed 242 | 243 | 244 | class TFramedTransport(TTransportBase, CReadableTransport): 245 | 246 | """Class that wraps another transport and frames its I/O when writing.""" 247 | 248 | def __init__(self, trans,): 249 | self.__trans = trans 250 | self.__rbuf = StringIO() 251 | self.__wbuf = StringIO() 252 | 253 | def isOpen(self): 254 | return self.__trans.isOpen() 255 | 256 | def open(self): 257 | return self.__trans.open() 258 | 259 | def close(self): 260 | return self.__trans.close() 261 | 262 | def read(self, sz): 263 | ret = self.__rbuf.read(sz) 264 | if len(ret) != 0: 265 | return ret 266 | 267 | self.readFrame() 268 | return self.__rbuf.read(sz) 269 | 270 | def readFrame(self): 271 | buff = self.__trans.readAll(4) 272 | sz, = unpack('!i', buff) 273 | self.__rbuf = StringIO(self.__trans.readAll(sz)) 274 | 275 | def write(self, buf): 276 | self.__wbuf.write(buf) 277 | 278 | def flush(self): 279 | wout = self.__wbuf.getvalue() 280 | wsz = len(wout) 281 | # reset wbuf before write/flush to preserve state on underlying failure 282 | self.__wbuf = StringIO() 283 | # N.B.: Doing this string concatenation is WAY cheaper than making 284 | # two separate calls to the underlying socket object. Socket writes in 285 | # Python turn out to be REALLY expensive, but it seems to do a pretty 286 | # good job of managing string buffer operations without excessive copies 287 | buf = pack("!i", wsz) + wout 288 | self.__trans.write(buf) 289 | self.__trans.flush() 290 | 291 | # Implement the CReadableTransport interface. 292 | @property 293 | def cstringio_buf(self): 294 | return self.__rbuf 295 | 296 | def cstringio_refill(self, prefix, reqlen): 297 | # self.__rbuf will already be empty here because fastbinary doesn't 298 | # ask for a refill until the previous buffer is empty. Therefore, 299 | # we can start reading new frames immediately. 300 | while len(prefix) < reqlen: 301 | self.readFrame() 302 | prefix += self.__rbuf.getvalue() 303 | self.__rbuf = StringIO(prefix) 304 | return self.__rbuf 305 | 306 | 307 | class TFileObjectTransport(TTransportBase): 308 | """Wraps a file-like object to make it work as a Thrift transport.""" 309 | 310 | def __init__(self, fileobj): 311 | self.fileobj = fileobj 312 | 313 | def isOpen(self): 314 | return True 315 | 316 | def close(self): 317 | self.fileobj.close() 318 | 319 | def read(self, sz): 320 | return self.fileobj.read(sz) 321 | 322 | def write(self, buf): 323 | self.fileobj.write(buf) 324 | 325 | def flush(self): 326 | self.fileobj.flush() 327 | -------------------------------------------------------------------------------- /src/evernote/edam/error/ttypes.py: -------------------------------------------------------------------------------- 1 | # 2 | # Autogenerated by Thrift 3 | # 4 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | # 6 | 7 | from thrift.Thrift import * 8 | 9 | from thrift.transport import TTransport 10 | from thrift.protocol import TBinaryProtocol 11 | try: 12 | from thrift.protocol import fastbinary 13 | except: 14 | fastbinary = None 15 | 16 | 17 | class EDAMErrorCode(object): 18 | """ 19 | Numeric codes indicating the type of error that occurred on the 20 | service. 21 |
22 |
UNKNOWN
No information available about the error 24 |
BAD_DATA_FORMAT
25 |
The format of the request data was incorrect
26 |
PERMISSION_DENIED
27 |
Not permitted to perform action
28 |
INTERNAL_ERROR
29 |
Unexpected problem with the service
30 |
DATA_REQUIRED
31 |
A required parameter/field was absent
32 |
LIMIT_REACHED
33 |
Operation denied due to data model limit
34 |
QUOTA_REACHED
35 |
Operation denied due to user storage limit
36 |
INVALID_AUTH
37 |
Username and/or password incorrect
38 |
AUTH_EXPIRED
39 |
Authentication token expired
40 |
DATA_CONFLICT
41 |
Change denied due to data model conflict
42 |
ENML_VALIDATION
43 |
Content of submitted note was malformed
44 |
SHARD_UNAVAILABLE
45 |
Service shard with account data is temporarily down
46 |
47 | """ 48 | UNKNOWN = 1 49 | BAD_DATA_FORMAT = 2 50 | PERMISSION_DENIED = 3 51 | INTERNAL_ERROR = 4 52 | DATA_REQUIRED = 5 53 | LIMIT_REACHED = 6 54 | QUOTA_REACHED = 7 55 | INVALID_AUTH = 8 56 | AUTH_EXPIRED = 9 57 | DATA_CONFLICT = 10 58 | ENML_VALIDATION = 11 59 | SHARD_UNAVAILABLE = 12 60 | 61 | _VALUES_TO_NAMES = { 62 | 1: "UNKNOWN", 63 | 2: "BAD_DATA_FORMAT", 64 | 3: "PERMISSION_DENIED", 65 | 4: "INTERNAL_ERROR", 66 | 5: "DATA_REQUIRED", 67 | 6: "LIMIT_REACHED", 68 | 7: "QUOTA_REACHED", 69 | 8: "INVALID_AUTH", 70 | 9: "AUTH_EXPIRED", 71 | 10: "DATA_CONFLICT", 72 | 11: "ENML_VALIDATION", 73 | 12: "SHARD_UNAVAILABLE", 74 | } 75 | 76 | _NAMES_TO_VALUES = { 77 | "UNKNOWN": 1, 78 | "BAD_DATA_FORMAT": 2, 79 | "PERMISSION_DENIED": 3, 80 | "INTERNAL_ERROR": 4, 81 | "DATA_REQUIRED": 5, 82 | "LIMIT_REACHED": 6, 83 | "QUOTA_REACHED": 7, 84 | "INVALID_AUTH": 8, 85 | "AUTH_EXPIRED": 9, 86 | "DATA_CONFLICT": 10, 87 | "ENML_VALIDATION": 11, 88 | "SHARD_UNAVAILABLE": 12, 89 | } 90 | 91 | class EDAMUserException(Exception): 92 | """ 93 | This exception is thrown by EDAM procedures when a call fails as a result of 94 | a problem that a user may be able to resolve. For example, if the user 95 | attempts to add a note to their account which would exceed their storage 96 | quota, this type of exception may be thrown to indicate the source of the 97 | error so that they can choose an alternate action. 98 | 99 | This exception would not be used for internal system errors that do not 100 | reflect user actions, but rather reflect a problem within the service that 101 | the user cannot resolve. 102 | 103 | errorCode: The numeric code indicating the type of error that occurred. 104 | must be one of the values of EDAMErrorCode. 105 | 106 | parameter: If the error applied to a particular input parameter, this will 107 | indicate which parameter. 108 | 109 | Attributes: 110 | - errorCode 111 | - parameter 112 | """ 113 | 114 | thrift_spec = ( 115 | None, # 0 116 | (1, TType.I32, 'errorCode', None, None, ), # 1 117 | (2, TType.STRING, 'parameter', None, None, ), # 2 118 | ) 119 | 120 | def __init__(self, errorCode=None, parameter=None,): 121 | self.errorCode = errorCode 122 | self.parameter = parameter 123 | 124 | def read(self, iprot): 125 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 126 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 127 | return 128 | iprot.readStructBegin() 129 | while True: 130 | (fname, ftype, fid) = iprot.readFieldBegin() 131 | if ftype == TType.STOP: 132 | break 133 | if fid == 1: 134 | if ftype == TType.I32: 135 | self.errorCode = iprot.readI32(); 136 | else: 137 | iprot.skip(ftype) 138 | elif fid == 2: 139 | if ftype == TType.STRING: 140 | self.parameter = iprot.readString(); 141 | else: 142 | iprot.skip(ftype) 143 | else: 144 | iprot.skip(ftype) 145 | iprot.readFieldEnd() 146 | iprot.readStructEnd() 147 | 148 | def write(self, oprot): 149 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 150 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 151 | return 152 | oprot.writeStructBegin('EDAMUserException') 153 | if self.errorCode != None: 154 | oprot.writeFieldBegin('errorCode', TType.I32, 1) 155 | oprot.writeI32(self.errorCode) 156 | oprot.writeFieldEnd() 157 | if self.parameter != None: 158 | oprot.writeFieldBegin('parameter', TType.STRING, 2) 159 | oprot.writeString(self.parameter) 160 | oprot.writeFieldEnd() 161 | oprot.writeFieldStop() 162 | oprot.writeStructEnd() 163 | 164 | def __str__(self): 165 | return repr(self) 166 | 167 | def __repr__(self): 168 | L = ['%s=%r' % (key, value) 169 | for key, value in self.__dict__.iteritems()] 170 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 171 | 172 | def __eq__(self, other): 173 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 174 | 175 | def __ne__(self, other): 176 | return not (self == other) 177 | 178 | class EDAMSystemException(Exception): 179 | """ 180 | This exception is thrown by EDAM procedures when a call fails as a result of 181 | an a problem in the service that could not be changed through user action. 182 | 183 | errorCode: The numeric code indicating the type of error that occurred. 184 | must be one of the values of EDAMErrorCode. 185 | 186 | message: This may contain additional information about the error 187 | 188 | Attributes: 189 | - errorCode 190 | - message 191 | """ 192 | 193 | thrift_spec = ( 194 | None, # 0 195 | (1, TType.I32, 'errorCode', None, None, ), # 1 196 | (2, TType.STRING, 'message', None, None, ), # 2 197 | ) 198 | 199 | def __init__(self, errorCode=None, message=None,): 200 | self.errorCode = errorCode 201 | self.message = message 202 | 203 | def read(self, iprot): 204 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 205 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 206 | return 207 | iprot.readStructBegin() 208 | while True: 209 | (fname, ftype, fid) = iprot.readFieldBegin() 210 | if ftype == TType.STOP: 211 | break 212 | if fid == 1: 213 | if ftype == TType.I32: 214 | self.errorCode = iprot.readI32(); 215 | else: 216 | iprot.skip(ftype) 217 | elif fid == 2: 218 | if ftype == TType.STRING: 219 | self.message = iprot.readString(); 220 | else: 221 | iprot.skip(ftype) 222 | else: 223 | iprot.skip(ftype) 224 | iprot.readFieldEnd() 225 | iprot.readStructEnd() 226 | 227 | def write(self, oprot): 228 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 229 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 230 | return 231 | oprot.writeStructBegin('EDAMSystemException') 232 | if self.errorCode != None: 233 | oprot.writeFieldBegin('errorCode', TType.I32, 1) 234 | oprot.writeI32(self.errorCode) 235 | oprot.writeFieldEnd() 236 | if self.message != None: 237 | oprot.writeFieldBegin('message', TType.STRING, 2) 238 | oprot.writeString(self.message) 239 | oprot.writeFieldEnd() 240 | oprot.writeFieldStop() 241 | oprot.writeStructEnd() 242 | 243 | def __str__(self): 244 | return repr(self) 245 | 246 | def __repr__(self): 247 | L = ['%s=%r' % (key, value) 248 | for key, value in self.__dict__.iteritems()] 249 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 250 | 251 | def __eq__(self, other): 252 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 253 | 254 | def __ne__(self, other): 255 | return not (self == other) 256 | 257 | class EDAMNotFoundException(Exception): 258 | """ 259 | This exception is thrown by EDAM procedures when a caller asks to perform 260 | an operation that does not exist. This may be thrown based on an invalid 261 | primary identifier (e.g. a bad GUID), or when the caller refers to an object 262 | by another unique identifier (e.g. a User's email address). 263 | 264 | identifier: the object identifier that was not found on the server. 265 | 266 | key: the value passed from the client in the identifier, which was not 267 | found. E.g. the GUID of an object that was not found. 268 | 269 | Attributes: 270 | - identifier 271 | - key 272 | """ 273 | 274 | thrift_spec = ( 275 | None, # 0 276 | (1, TType.STRING, 'identifier', None, None, ), # 1 277 | (2, TType.STRING, 'key', None, None, ), # 2 278 | ) 279 | 280 | def __init__(self, identifier=None, key=None,): 281 | self.identifier = identifier 282 | self.key = key 283 | 284 | def read(self, iprot): 285 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 286 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 287 | return 288 | iprot.readStructBegin() 289 | while True: 290 | (fname, ftype, fid) = iprot.readFieldBegin() 291 | if ftype == TType.STOP: 292 | break 293 | if fid == 1: 294 | if ftype == TType.STRING: 295 | self.identifier = iprot.readString(); 296 | else: 297 | iprot.skip(ftype) 298 | elif fid == 2: 299 | if ftype == TType.STRING: 300 | self.key = iprot.readString(); 301 | else: 302 | iprot.skip(ftype) 303 | else: 304 | iprot.skip(ftype) 305 | iprot.readFieldEnd() 306 | iprot.readStructEnd() 307 | 308 | def write(self, oprot): 309 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 310 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 311 | return 312 | oprot.writeStructBegin('EDAMNotFoundException') 313 | if self.identifier != None: 314 | oprot.writeFieldBegin('identifier', TType.STRING, 1) 315 | oprot.writeString(self.identifier) 316 | oprot.writeFieldEnd() 317 | if self.key != None: 318 | oprot.writeFieldBegin('key', TType.STRING, 2) 319 | oprot.writeString(self.key) 320 | oprot.writeFieldEnd() 321 | oprot.writeFieldStop() 322 | oprot.writeStructEnd() 323 | 324 | def __str__(self): 325 | return repr(self) 326 | 327 | def __repr__(self): 328 | L = ['%s=%r' % (key, value) 329 | for key, value in self.__dict__.iteritems()] 330 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 331 | 332 | def __eq__(self, other): 333 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 334 | 335 | def __ne__(self, other): 336 | return not (self == other) 337 | 338 | -------------------------------------------------------------------------------- /src/thrift/server/TNonblockingServer.py: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, 13 | # software distributed under the License is distributed on an 14 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | # KIND, either express or implied. See the License for the 16 | # specific language governing permissions and limitations 17 | # under the License. 18 | # 19 | """Implementation of non-blocking server. 20 | 21 | The main idea of the server is reciving and sending requests 22 | only from main thread. 23 | 24 | It also makes thread pool server in tasks terms, not connections. 25 | """ 26 | import threading 27 | import socket 28 | import Queue 29 | import select 30 | import struct 31 | import logging 32 | 33 | from thrift.transport import TTransport 34 | from thrift.protocol.TBinaryProtocol import TBinaryProtocolFactory 35 | 36 | __all__ = ['TNonblockingServer'] 37 | 38 | class Worker(threading.Thread): 39 | """Worker is a small helper to process incoming connection.""" 40 | def __init__(self, queue): 41 | threading.Thread.__init__(self) 42 | self.queue = queue 43 | 44 | def run(self): 45 | """Process queries from task queue, stop if processor is None.""" 46 | while True: 47 | try: 48 | processor, iprot, oprot, otrans, callback = self.queue.get() 49 | if processor is None: 50 | break 51 | processor.process(iprot, oprot) 52 | callback(True, otrans.getvalue()) 53 | except Exception: 54 | logging.exception("Exception while processing request") 55 | callback(False, '') 56 | 57 | WAIT_LEN = 0 58 | WAIT_MESSAGE = 1 59 | WAIT_PROCESS = 2 60 | SEND_ANSWER = 3 61 | CLOSED = 4 62 | 63 | def locked(func): 64 | "Decorator which locks self.lock." 65 | def nested(self, *args, **kwargs): 66 | self.lock.acquire() 67 | try: 68 | return func(self, *args, **kwargs) 69 | finally: 70 | self.lock.release() 71 | return nested 72 | 73 | def socket_exception(func): 74 | "Decorator close object on socket.error." 75 | def read(self, *args, **kwargs): 76 | try: 77 | return func(self, *args, **kwargs) 78 | except socket.error: 79 | self.close() 80 | return read 81 | 82 | class Connection: 83 | """Basic class is represented connection. 84 | 85 | It can be in state: 86 | WAIT_LEN --- connection is reading request len. 87 | WAIT_MESSAGE --- connection is reading request. 88 | WAIT_PROCESS --- connection has just read whole request and 89 | waits for call ready routine. 90 | SEND_ANSWER --- connection is sending answer string (including length 91 | of answer). 92 | CLOSED --- socket was closed and connection should be deleted. 93 | """ 94 | def __init__(self, new_socket, wake_up): 95 | self.socket = new_socket 96 | self.socket.setblocking(False) 97 | self.status = WAIT_LEN 98 | self.len = 0 99 | self.message = '' 100 | self.lock = threading.Lock() 101 | self.wake_up = wake_up 102 | 103 | def _read_len(self): 104 | """Reads length of request. 105 | 106 | It's really paranoic routine and it may be replaced by 107 | self.socket.recv(4).""" 108 | read = self.socket.recv(4 - len(self.message)) 109 | if len(read) == 0: 110 | # if we read 0 bytes and self.message is empty, it means client close 111 | # connection 112 | if len(self.message) != 0: 113 | logging.error("can't read frame size from socket") 114 | self.close() 115 | return 116 | self.message += read 117 | if len(self.message) == 4: 118 | self.len, = struct.unpack('!i', self.message) 119 | if self.len < 0: 120 | logging.error("negative frame size, it seems client"\ 121 | " doesn't use FramedTransport") 122 | self.close() 123 | elif self.len == 0: 124 | logging.error("empty frame, it's really strange") 125 | self.close() 126 | else: 127 | self.message = '' 128 | self.status = WAIT_MESSAGE 129 | 130 | @socket_exception 131 | def read(self): 132 | """Reads data from stream and switch state.""" 133 | assert self.status in (WAIT_LEN, WAIT_MESSAGE) 134 | if self.status == WAIT_LEN: 135 | self._read_len() 136 | # go back to the main loop here for simplicity instead of 137 | # falling through, even though there is a good chance that 138 | # the message is already available 139 | elif self.status == WAIT_MESSAGE: 140 | read = self.socket.recv(self.len - len(self.message)) 141 | if len(read) == 0: 142 | logging.error("can't read frame from socket (get %d of %d bytes)" % 143 | (len(self.message), self.len)) 144 | self.close() 145 | return 146 | self.message += read 147 | if len(self.message) == self.len: 148 | self.status = WAIT_PROCESS 149 | 150 | @socket_exception 151 | def write(self): 152 | """Writes data from socket and switch state.""" 153 | assert self.status == SEND_ANSWER 154 | sent = self.socket.send(self.message) 155 | if sent == len(self.message): 156 | self.status = WAIT_LEN 157 | self.message = '' 158 | self.len = 0 159 | else: 160 | self.message = self.message[sent:] 161 | 162 | @locked 163 | def ready(self, all_ok, message): 164 | """Callback function for switching state and waking up main thread. 165 | 166 | This function is the only function witch can be called asynchronous. 167 | 168 | The ready can switch Connection to three states: 169 | WAIT_LEN if request was oneway. 170 | SEND_ANSWER if request was processed in normal way. 171 | CLOSED if request throws unexpected exception. 172 | 173 | The one wakes up main thread. 174 | """ 175 | assert self.status == WAIT_PROCESS 176 | if not all_ok: 177 | self.close() 178 | self.wake_up() 179 | return 180 | self.len = '' 181 | if len(message) == 0: 182 | # it was a oneway request, do not write answer 183 | self.message = '' 184 | self.status = WAIT_LEN 185 | else: 186 | self.message = struct.pack('!i', len(message)) + message 187 | self.status = SEND_ANSWER 188 | self.wake_up() 189 | 190 | @locked 191 | def is_writeable(self): 192 | "Returns True if connection should be added to write list of select." 193 | return self.status == SEND_ANSWER 194 | 195 | # it's not necessary, but... 196 | @locked 197 | def is_readable(self): 198 | "Returns True if connection should be added to read list of select." 199 | return self.status in (WAIT_LEN, WAIT_MESSAGE) 200 | 201 | @locked 202 | def is_closed(self): 203 | "Returns True if connection is closed." 204 | return self.status == CLOSED 205 | 206 | def fileno(self): 207 | "Returns the file descriptor of the associated socket." 208 | return self.socket.fileno() 209 | 210 | def close(self): 211 | "Closes connection" 212 | self.status = CLOSED 213 | self.socket.close() 214 | 215 | class TNonblockingServer: 216 | """Non-blocking server.""" 217 | def __init__(self, processor, lsocket, inputProtocolFactory=None, 218 | outputProtocolFactory=None, threads=10): 219 | self.processor = processor 220 | self.socket = lsocket 221 | self.in_protocol = inputProtocolFactory or TBinaryProtocolFactory() 222 | self.out_protocol = outputProtocolFactory or self.in_protocol 223 | self.threads = int(threads) 224 | self.clients = {} 225 | self.tasks = Queue.Queue() 226 | self._read, self._write = socket.socketpair() 227 | self.prepared = False 228 | 229 | def setNumThreads(self, num): 230 | """Set the number of worker threads that should be created.""" 231 | # implement ThreadPool interface 232 | assert not self.prepared, "You can't change number of threads for working server" 233 | self.threads = num 234 | 235 | def prepare(self): 236 | """Prepares server for serve requests.""" 237 | self.socket.listen() 238 | for _ in xrange(self.threads): 239 | thread = Worker(self.tasks) 240 | thread.setDaemon(True) 241 | thread.start() 242 | self.prepared = True 243 | 244 | def wake_up(self): 245 | """Wake up main thread. 246 | 247 | The server usualy waits in select call in we should terminate one. 248 | The simplest way is using socketpair. 249 | 250 | Select always wait to read from the first socket of socketpair. 251 | 252 | In this case, we can just write anything to the second socket from 253 | socketpair.""" 254 | self._write.send('1') 255 | 256 | def _select(self): 257 | """Does select on open connections.""" 258 | readable = [self.socket.handle.fileno(), self._read.fileno()] 259 | writable = [] 260 | for i, connection in self.clients.items(): 261 | if connection.is_readable(): 262 | readable.append(connection.fileno()) 263 | if connection.is_writeable(): 264 | writable.append(connection.fileno()) 265 | if connection.is_closed(): 266 | del self.clients[i] 267 | return select.select(readable, writable, readable) 268 | 269 | def handle(self): 270 | """Handle requests. 271 | 272 | WARNING! You must call prepare BEFORE calling handle. 273 | """ 274 | assert self.prepared, "You have to call prepare before handle" 275 | rset, wset, xset = self._select() 276 | for readable in rset: 277 | if readable == self._read.fileno(): 278 | # don't care i just need to clean readable flag 279 | self._read.recv(1024) 280 | elif readable == self.socket.handle.fileno(): 281 | client = self.socket.accept().handle 282 | self.clients[client.fileno()] = Connection(client, self.wake_up) 283 | else: 284 | connection = self.clients[readable] 285 | connection.read() 286 | if connection.status == WAIT_PROCESS: 287 | itransport = TTransport.TMemoryBuffer(connection.message) 288 | otransport = TTransport.TMemoryBuffer() 289 | iprot = self.in_protocol.getProtocol(itransport) 290 | oprot = self.out_protocol.getProtocol(otransport) 291 | self.tasks.put([self.processor, iprot, oprot, 292 | otransport, connection.ready]) 293 | for writeable in wset: 294 | self.clients[writeable].write() 295 | for oob in xset: 296 | self.clients[oob].close() 297 | del self.clients[oob] 298 | 299 | def close(self): 300 | """Closes the server.""" 301 | for _ in xrange(self.threads): 302 | self.tasks.put([None, None, None, None, None]) 303 | self.socket.close() 304 | self.prepared = False 305 | 306 | def serve(self): 307 | """Serve forever.""" 308 | self.prepare() 309 | while True: 310 | self.handle() 311 | -------------------------------------------------------------------------------- /src/evernote/edam/userstore/ttypes.py: -------------------------------------------------------------------------------- 1 | # 2 | # Autogenerated by Thrift 3 | # 4 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 5 | # 6 | 7 | from thrift.Thrift import * 8 | import evernote.edam.type.ttypes 9 | import evernote.edam.error.ttypes 10 | 11 | 12 | from thrift.transport import TTransport 13 | from thrift.protocol import TBinaryProtocol 14 | try: 15 | from thrift.protocol import fastbinary 16 | except: 17 | fastbinary = None 18 | 19 | 20 | class SponsoredGroupRole(object): 21 | """ 22 | Enumeration of Sponsored Group Roles 23 | """ 24 | GROUP_MEMBER = 1 25 | GROUP_ADMIN = 2 26 | GROUP_OWNER = 3 27 | 28 | _VALUES_TO_NAMES = { 29 | 1: "GROUP_MEMBER", 30 | 2: "GROUP_ADMIN", 31 | 3: "GROUP_OWNER", 32 | } 33 | 34 | _NAMES_TO_VALUES = { 35 | "GROUP_MEMBER": 1, 36 | "GROUP_ADMIN": 2, 37 | "GROUP_OWNER": 3, 38 | } 39 | 40 | class PublicUserInfo(object): 41 | """ 42 | This structure is used to provide publicly-available user information 43 | about a particular account. 44 |
45 |
userId:
46 |
47 | The unique numeric user identifier for the user account. 48 |
49 |
shardId:
50 |
51 | The name of the virtual server that manages the state of 52 | this user. This value is used internally to determine which system should 53 | service requests about this user's data. It is also used to construct 54 | the appropriate URL to make requests from the NoteStore. 55 |
56 |
privilege:
57 |
58 | The privilege level of the account, to determine whether 59 | this is a Premium or Free account. 60 |
61 |
62 | 63 | Attributes: 64 | - userId 65 | - shardId 66 | - privilege 67 | - username 68 | """ 69 | 70 | thrift_spec = ( 71 | None, # 0 72 | (1, TType.I32, 'userId', None, None, ), # 1 73 | (2, TType.STRING, 'shardId', None, None, ), # 2 74 | (3, TType.I32, 'privilege', None, None, ), # 3 75 | (4, TType.STRING, 'username', None, None, ), # 4 76 | ) 77 | 78 | def __init__(self, userId=None, shardId=None, privilege=None, username=None,): 79 | self.userId = userId 80 | self.shardId = shardId 81 | self.privilege = privilege 82 | self.username = username 83 | 84 | def read(self, iprot): 85 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 86 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 87 | return 88 | iprot.readStructBegin() 89 | while True: 90 | (fname, ftype, fid) = iprot.readFieldBegin() 91 | if ftype == TType.STOP: 92 | break 93 | if fid == 1: 94 | if ftype == TType.I32: 95 | self.userId = iprot.readI32(); 96 | else: 97 | iprot.skip(ftype) 98 | elif fid == 2: 99 | if ftype == TType.STRING: 100 | self.shardId = iprot.readString(); 101 | else: 102 | iprot.skip(ftype) 103 | elif fid == 3: 104 | if ftype == TType.I32: 105 | self.privilege = iprot.readI32(); 106 | else: 107 | iprot.skip(ftype) 108 | elif fid == 4: 109 | if ftype == TType.STRING: 110 | self.username = iprot.readString(); 111 | else: 112 | iprot.skip(ftype) 113 | else: 114 | iprot.skip(ftype) 115 | iprot.readFieldEnd() 116 | iprot.readStructEnd() 117 | 118 | def write(self, oprot): 119 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 120 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 121 | return 122 | oprot.writeStructBegin('PublicUserInfo') 123 | if self.userId != None: 124 | oprot.writeFieldBegin('userId', TType.I32, 1) 125 | oprot.writeI32(self.userId) 126 | oprot.writeFieldEnd() 127 | if self.shardId != None: 128 | oprot.writeFieldBegin('shardId', TType.STRING, 2) 129 | oprot.writeString(self.shardId) 130 | oprot.writeFieldEnd() 131 | if self.privilege != None: 132 | oprot.writeFieldBegin('privilege', TType.I32, 3) 133 | oprot.writeI32(self.privilege) 134 | oprot.writeFieldEnd() 135 | if self.username != None: 136 | oprot.writeFieldBegin('username', TType.STRING, 4) 137 | oprot.writeString(self.username) 138 | oprot.writeFieldEnd() 139 | oprot.writeFieldStop() 140 | oprot.writeStructEnd() 141 | 142 | def __repr__(self): 143 | L = ['%s=%r' % (key, value) 144 | for key, value in self.__dict__.iteritems()] 145 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 146 | 147 | def __eq__(self, other): 148 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 149 | 150 | def __ne__(self, other): 151 | return not (self == other) 152 | 153 | class PremiumInfo(object): 154 | """ 155 | This structure is used to provide information about a user's Premium account. 156 |
157 |
currentTime:
158 |
159 | The server-side date and time when this data was generated. 160 |
161 |
premium:
162 |
163 | True if the user's account is Premium. 164 |
165 |
premiumRecurring
166 |
167 | True if the user's account is Premium and has a recurring payment method. 168 |
169 |
premiumExpirationDate:
170 |
171 | The date when the user's Premium account expires, or the date when the user's 172 | account will be charged if it has a recurring payment method. 173 |
174 |
premiumExtendable:
175 |
176 | True if the user is eligible for purchasing Premium account extensions. 177 |
178 |
premiumPending:
179 |
180 | True if the user's Premium account is pending payment confirmation 181 |
182 |
premiumCancellationPending:
183 |
184 | True if the user has requested that no further charges to be made; the Premium 185 | account will remain active until it expires. 186 |
187 |
canPurchaseUploadAllowance:
188 |
189 | True if the user is eligible for purchasing additional upload allowance. 190 |
191 |
sponsoredGroupName:
192 |
193 | The name of the sponsored group that the user is part of. 194 |
195 |
sponsoredGroupRole:
196 |
197 | The role of the user within a sponsored group. 198 |
199 |
200 | 201 | Attributes: 202 | - currentTime 203 | - premium 204 | - premiumRecurring 205 | - premiumExpirationDate 206 | - premiumExtendable 207 | - premiumPending 208 | - premiumCancellationPending 209 | - canPurchaseUploadAllowance 210 | - sponsoredGroupName 211 | - sponsoredGroupRole 212 | """ 213 | 214 | thrift_spec = ( 215 | None, # 0 216 | (1, TType.I64, 'currentTime', None, None, ), # 1 217 | (2, TType.BOOL, 'premium', None, None, ), # 2 218 | (3, TType.BOOL, 'premiumRecurring', None, None, ), # 3 219 | (4, TType.I64, 'premiumExpirationDate', None, None, ), # 4 220 | (5, TType.BOOL, 'premiumExtendable', None, None, ), # 5 221 | (6, TType.BOOL, 'premiumPending', None, None, ), # 6 222 | (7, TType.BOOL, 'premiumCancellationPending', None, None, ), # 7 223 | (8, TType.BOOL, 'canPurchaseUploadAllowance', None, None, ), # 8 224 | (9, TType.STRING, 'sponsoredGroupName', None, None, ), # 9 225 | (10, TType.I32, 'sponsoredGroupRole', None, None, ), # 10 226 | ) 227 | 228 | def __init__(self, currentTime=None, premium=None, premiumRecurring=None, premiumExpirationDate=None, premiumExtendable=None, premiumPending=None, premiumCancellationPending=None, canPurchaseUploadAllowance=None, sponsoredGroupName=None, sponsoredGroupRole=None,): 229 | self.currentTime = currentTime 230 | self.premium = premium 231 | self.premiumRecurring = premiumRecurring 232 | self.premiumExpirationDate = premiumExpirationDate 233 | self.premiumExtendable = premiumExtendable 234 | self.premiumPending = premiumPending 235 | self.premiumCancellationPending = premiumCancellationPending 236 | self.canPurchaseUploadAllowance = canPurchaseUploadAllowance 237 | self.sponsoredGroupName = sponsoredGroupName 238 | self.sponsoredGroupRole = sponsoredGroupRole 239 | 240 | def read(self, iprot): 241 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 242 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 243 | return 244 | iprot.readStructBegin() 245 | while True: 246 | (fname, ftype, fid) = iprot.readFieldBegin() 247 | if ftype == TType.STOP: 248 | break 249 | if fid == 1: 250 | if ftype == TType.I64: 251 | self.currentTime = iprot.readI64(); 252 | else: 253 | iprot.skip(ftype) 254 | elif fid == 2: 255 | if ftype == TType.BOOL: 256 | self.premium = iprot.readBool(); 257 | else: 258 | iprot.skip(ftype) 259 | elif fid == 3: 260 | if ftype == TType.BOOL: 261 | self.premiumRecurring = iprot.readBool(); 262 | else: 263 | iprot.skip(ftype) 264 | elif fid == 4: 265 | if ftype == TType.I64: 266 | self.premiumExpirationDate = iprot.readI64(); 267 | else: 268 | iprot.skip(ftype) 269 | elif fid == 5: 270 | if ftype == TType.BOOL: 271 | self.premiumExtendable = iprot.readBool(); 272 | else: 273 | iprot.skip(ftype) 274 | elif fid == 6: 275 | if ftype == TType.BOOL: 276 | self.premiumPending = iprot.readBool(); 277 | else: 278 | iprot.skip(ftype) 279 | elif fid == 7: 280 | if ftype == TType.BOOL: 281 | self.premiumCancellationPending = iprot.readBool(); 282 | else: 283 | iprot.skip(ftype) 284 | elif fid == 8: 285 | if ftype == TType.BOOL: 286 | self.canPurchaseUploadAllowance = iprot.readBool(); 287 | else: 288 | iprot.skip(ftype) 289 | elif fid == 9: 290 | if ftype == TType.STRING: 291 | self.sponsoredGroupName = iprot.readString(); 292 | else: 293 | iprot.skip(ftype) 294 | elif fid == 10: 295 | if ftype == TType.I32: 296 | self.sponsoredGroupRole = iprot.readI32(); 297 | else: 298 | iprot.skip(ftype) 299 | else: 300 | iprot.skip(ftype) 301 | iprot.readFieldEnd() 302 | iprot.readStructEnd() 303 | 304 | def write(self, oprot): 305 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 306 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 307 | return 308 | oprot.writeStructBegin('PremiumInfo') 309 | if self.currentTime != None: 310 | oprot.writeFieldBegin('currentTime', TType.I64, 1) 311 | oprot.writeI64(self.currentTime) 312 | oprot.writeFieldEnd() 313 | if self.premium != None: 314 | oprot.writeFieldBegin('premium', TType.BOOL, 2) 315 | oprot.writeBool(self.premium) 316 | oprot.writeFieldEnd() 317 | if self.premiumRecurring != None: 318 | oprot.writeFieldBegin('premiumRecurring', TType.BOOL, 3) 319 | oprot.writeBool(self.premiumRecurring) 320 | oprot.writeFieldEnd() 321 | if self.premiumExpirationDate != None: 322 | oprot.writeFieldBegin('premiumExpirationDate', TType.I64, 4) 323 | oprot.writeI64(self.premiumExpirationDate) 324 | oprot.writeFieldEnd() 325 | if self.premiumExtendable != None: 326 | oprot.writeFieldBegin('premiumExtendable', TType.BOOL, 5) 327 | oprot.writeBool(self.premiumExtendable) 328 | oprot.writeFieldEnd() 329 | if self.premiumPending != None: 330 | oprot.writeFieldBegin('premiumPending', TType.BOOL, 6) 331 | oprot.writeBool(self.premiumPending) 332 | oprot.writeFieldEnd() 333 | if self.premiumCancellationPending != None: 334 | oprot.writeFieldBegin('premiumCancellationPending', TType.BOOL, 7) 335 | oprot.writeBool(self.premiumCancellationPending) 336 | oprot.writeFieldEnd() 337 | if self.canPurchaseUploadAllowance != None: 338 | oprot.writeFieldBegin('canPurchaseUploadAllowance', TType.BOOL, 8) 339 | oprot.writeBool(self.canPurchaseUploadAllowance) 340 | oprot.writeFieldEnd() 341 | if self.sponsoredGroupName != None: 342 | oprot.writeFieldBegin('sponsoredGroupName', TType.STRING, 9) 343 | oprot.writeString(self.sponsoredGroupName) 344 | oprot.writeFieldEnd() 345 | if self.sponsoredGroupRole != None: 346 | oprot.writeFieldBegin('sponsoredGroupRole', TType.I32, 10) 347 | oprot.writeI32(self.sponsoredGroupRole) 348 | oprot.writeFieldEnd() 349 | oprot.writeFieldStop() 350 | oprot.writeStructEnd() 351 | 352 | def __repr__(self): 353 | L = ['%s=%r' % (key, value) 354 | for key, value in self.__dict__.iteritems()] 355 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 356 | 357 | def __eq__(self, other): 358 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 359 | 360 | def __ne__(self, other): 361 | return not (self == other) 362 | 363 | class AuthenticationResult(object): 364 | """ 365 | When an authentication (or re-authentication) is performed, this structure 366 | provides the result to the client. 367 |
368 |
currentTime:
369 |
370 | The server-side date and time when this result was 371 | generated. 372 |
373 |
authenticationToken:
374 |
375 | Holds an opaque, ASCII-encoded token that can be 376 | used by the client to perform actions on a NoteStore. 377 |
378 |
expiration:
379 |
380 | Holds the server-side date and time when the 381 | authentication token will expire. 382 | This time can be compared to "currentTime" to produce an expiration 383 | time that can be reconciled with the client's local clock. 384 |
385 |
user:
386 |
387 | Holds the information about the account which was 388 | authenticated if this was a full authentication. May be absent if this 389 | particular authentication did not require user information. 390 |
391 |
publicUserInfo:
392 |
393 | If this authentication result was achieved without full permissions to 394 | access the full User structure, this field may be set to give back 395 | a more limited public set of data. 396 |
397 |
398 | 399 | Attributes: 400 | - currentTime 401 | - authenticationToken 402 | - expiration 403 | - user 404 | - publicUserInfo 405 | """ 406 | 407 | thrift_spec = ( 408 | None, # 0 409 | (1, TType.I64, 'currentTime', None, None, ), # 1 410 | (2, TType.STRING, 'authenticationToken', None, None, ), # 2 411 | (3, TType.I64, 'expiration', None, None, ), # 3 412 | (4, TType.STRUCT, 'user', (evernote.edam.type.ttypes.User, evernote.edam.type.ttypes.User.thrift_spec), None, ), # 4 413 | (5, TType.STRUCT, 'publicUserInfo', (PublicUserInfo, PublicUserInfo.thrift_spec), None, ), # 5 414 | ) 415 | 416 | def __init__(self, currentTime=None, authenticationToken=None, expiration=None, user=None, publicUserInfo=None,): 417 | self.currentTime = currentTime 418 | self.authenticationToken = authenticationToken 419 | self.expiration = expiration 420 | self.user = user 421 | self.publicUserInfo = publicUserInfo 422 | 423 | def read(self, iprot): 424 | if iprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and isinstance(iprot.trans, TTransport.CReadableTransport) and self.thrift_spec is not None and fastbinary is not None: 425 | fastbinary.decode_binary(self, iprot.trans, (self.__class__, self.thrift_spec)) 426 | return 427 | iprot.readStructBegin() 428 | while True: 429 | (fname, ftype, fid) = iprot.readFieldBegin() 430 | if ftype == TType.STOP: 431 | break 432 | if fid == 1: 433 | if ftype == TType.I64: 434 | self.currentTime = iprot.readI64(); 435 | else: 436 | iprot.skip(ftype) 437 | elif fid == 2: 438 | if ftype == TType.STRING: 439 | self.authenticationToken = iprot.readString(); 440 | else: 441 | iprot.skip(ftype) 442 | elif fid == 3: 443 | if ftype == TType.I64: 444 | self.expiration = iprot.readI64(); 445 | else: 446 | iprot.skip(ftype) 447 | elif fid == 4: 448 | if ftype == TType.STRUCT: 449 | self.user = evernote.edam.type.ttypes.User() 450 | self.user.read(iprot) 451 | else: 452 | iprot.skip(ftype) 453 | elif fid == 5: 454 | if ftype == TType.STRUCT: 455 | self.publicUserInfo = PublicUserInfo() 456 | self.publicUserInfo.read(iprot) 457 | else: 458 | iprot.skip(ftype) 459 | else: 460 | iprot.skip(ftype) 461 | iprot.readFieldEnd() 462 | iprot.readStructEnd() 463 | 464 | def write(self, oprot): 465 | if oprot.__class__ == TBinaryProtocol.TBinaryProtocolAccelerated and self.thrift_spec is not None and fastbinary is not None: 466 | oprot.trans.write(fastbinary.encode_binary(self, (self.__class__, self.thrift_spec))) 467 | return 468 | oprot.writeStructBegin('AuthenticationResult') 469 | if self.currentTime != None: 470 | oprot.writeFieldBegin('currentTime', TType.I64, 1) 471 | oprot.writeI64(self.currentTime) 472 | oprot.writeFieldEnd() 473 | if self.authenticationToken != None: 474 | oprot.writeFieldBegin('authenticationToken', TType.STRING, 2) 475 | oprot.writeString(self.authenticationToken) 476 | oprot.writeFieldEnd() 477 | if self.expiration != None: 478 | oprot.writeFieldBegin('expiration', TType.I64, 3) 479 | oprot.writeI64(self.expiration) 480 | oprot.writeFieldEnd() 481 | if self.user != None: 482 | oprot.writeFieldBegin('user', TType.STRUCT, 4) 483 | self.user.write(oprot) 484 | oprot.writeFieldEnd() 485 | if self.publicUserInfo != None: 486 | oprot.writeFieldBegin('publicUserInfo', TType.STRUCT, 5) 487 | self.publicUserInfo.write(oprot) 488 | oprot.writeFieldEnd() 489 | oprot.writeFieldStop() 490 | oprot.writeStructEnd() 491 | 492 | def __repr__(self): 493 | L = ['%s=%r' % (key, value) 494 | for key, value in self.__dict__.iteritems()] 495 | return '%s(%s)' % (self.__class__.__name__, ', '.join(L)) 496 | 497 | def __eq__(self, other): 498 | return isinstance(other, self.__class__) and self.__dict__ == other.__dict__ 499 | 500 | def __ne__(self, other): 501 | return not (self == other) 502 | 503 | -------------------------------------------------------------------------------- /src/evernote/edam/notestore/NoteStore-remote: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # 3 | # Autogenerated by Thrift 4 | # 5 | # DO NOT EDIT UNLESS YOU ARE SURE THAT YOU KNOW WHAT YOU ARE DOING 6 | # 7 | 8 | import sys 9 | import pprint 10 | from urlparse import urlparse 11 | from thrift.transport import TTransport 12 | from thrift.transport import TSocket 13 | from thrift.transport import THttpClient 14 | from thrift.protocol import TBinaryProtocol 15 | 16 | import NoteStore 17 | from ttypes import * 18 | 19 | if len(sys.argv) <= 1 or sys.argv[1] == '--help': 20 | print '' 21 | print 'Usage: ' + sys.argv[0] + ' [-h host:port] [-u url] [-f[ramed]] function [arg1 [arg2...]]' 22 | print '' 23 | print 'Functions:' 24 | print ' SyncState getSyncState(string authenticationToken)' 25 | print ' SyncChunk getSyncChunk(string authenticationToken, i32 afterUSN, i32 maxEntries, bool fullSyncOnly)' 26 | print ' SyncChunk getFilteredSyncChunk(string authenticationToken, i32 afterUSN, i32 maxEntries, SyncChunkFilter filter)' 27 | print ' SyncState getLinkedNotebookSyncState(string authenticationToken, LinkedNotebook linkedNotebook)' 28 | print ' SyncChunk getLinkedNotebookSyncChunk(string authenticationToken, LinkedNotebook linkedNotebook, i32 afterUSN, i32 maxEntries, bool fullSyncOnly)' 29 | print ' listNotebooks(string authenticationToken)' 30 | print ' Notebook getNotebook(string authenticationToken, Guid guid)' 31 | print ' Notebook getDefaultNotebook(string authenticationToken)' 32 | print ' Notebook createNotebook(string authenticationToken, Notebook notebook)' 33 | print ' i32 updateNotebook(string authenticationToken, Notebook notebook)' 34 | print ' i32 expungeNotebook(string authenticationToken, Guid guid)' 35 | print ' listTags(string authenticationToken)' 36 | print ' listTagsByNotebook(string authenticationToken, Guid notebookGuid)' 37 | print ' Tag getTag(string authenticationToken, Guid guid)' 38 | print ' Tag createTag(string authenticationToken, Tag tag)' 39 | print ' i32 updateTag(string authenticationToken, Tag tag)' 40 | print ' void untagAll(string authenticationToken, Guid guid)' 41 | print ' i32 expungeTag(string authenticationToken, Guid guid)' 42 | print ' listSearches(string authenticationToken)' 43 | print ' SavedSearch getSearch(string authenticationToken, Guid guid)' 44 | print ' SavedSearch createSearch(string authenticationToken, SavedSearch search)' 45 | print ' i32 updateSearch(string authenticationToken, SavedSearch search)' 46 | print ' i32 expungeSearch(string authenticationToken, Guid guid)' 47 | print ' NoteList findNotes(string authenticationToken, NoteFilter filter, i32 offset, i32 maxNotes)' 48 | print ' i32 findNoteOffset(string authenticationToken, NoteFilter filter, Guid guid)' 49 | print ' NotesMetadataList findNotesMetadata(string authenticationToken, NoteFilter filter, i32 offset, i32 maxNotes, NotesMetadataResultSpec resultSpec)' 50 | print ' NoteCollectionCounts findNoteCounts(string authenticationToken, NoteFilter filter, bool withTrash)' 51 | print ' Note getNote(string authenticationToken, Guid guid, bool withContent, bool withResourcesData, bool withResourcesRecognition, bool withResourcesAlternateData)' 52 | print ' LazyMap getNoteApplicationData(string authenticationToken, Guid guid)' 53 | print ' string getNoteApplicationDataEntry(string authenticationToken, Guid guid, string key)' 54 | print ' i32 setNoteApplicationDataEntry(string authenticationToken, Guid guid, string key, string value)' 55 | print ' i32 unsetNoteApplicationDataEntry(string authenticationToken, Guid guid, string key)' 56 | print ' string getNoteContent(string authenticationToken, Guid guid)' 57 | print ' string getNoteSearchText(string authenticationToken, Guid guid, bool noteOnly, bool tokenizeForIndexing)' 58 | print ' string getResourceSearchText(string authenticationToken, Guid guid)' 59 | print ' getNoteTagNames(string authenticationToken, Guid guid)' 60 | print ' Note createNote(string authenticationToken, Note note)' 61 | print ' Note updateNote(string authenticationToken, Note note)' 62 | print ' i32 deleteNote(string authenticationToken, Guid guid)' 63 | print ' i32 expungeNote(string authenticationToken, Guid guid)' 64 | print ' i32 expungeNotes(string authenticationToken, noteGuids)' 65 | print ' i32 expungeInactiveNotes(string authenticationToken)' 66 | print ' Note copyNote(string authenticationToken, Guid noteGuid, Guid toNotebookGuid)' 67 | print ' listNoteVersions(string authenticationToken, Guid noteGuid)' 68 | print ' Note getNoteVersion(string authenticationToken, Guid noteGuid, i32 updateSequenceNum, bool withResourcesData, bool withResourcesRecognition, bool withResourcesAlternateData)' 69 | print ' Resource getResource(string authenticationToken, Guid guid, bool withData, bool withRecognition, bool withAttributes, bool withAlternateData)' 70 | print ' LazyMap getResourceApplicationData(string authenticationToken, Guid guid)' 71 | print ' string getResourceApplicationDataEntry(string authenticationToken, Guid guid, string key)' 72 | print ' i32 setResourceApplicationDataEntry(string authenticationToken, Guid guid, string key, string value)' 73 | print ' i32 unsetResourceApplicationDataEntry(string authenticationToken, Guid guid, string key)' 74 | print ' i32 updateResource(string authenticationToken, Resource resource)' 75 | print ' string getResourceData(string authenticationToken, Guid guid)' 76 | print ' Resource getResourceByHash(string authenticationToken, Guid noteGuid, string contentHash, bool withData, bool withRecognition, bool withAlternateData)' 77 | print ' string getResourceRecognition(string authenticationToken, Guid guid)' 78 | print ' string getResourceAlternateData(string authenticationToken, Guid guid)' 79 | print ' ResourceAttributes getResourceAttributes(string authenticationToken, Guid guid)' 80 | print ' i64 getAccountSize(string authenticationToken)' 81 | print ' getAds(string authenticationToken, AdParameters adParameters)' 82 | print ' Ad getRandomAd(string authenticationToken, AdParameters adParameters)' 83 | print ' Notebook getPublicNotebook(UserID userId, string publicUri)' 84 | print ' SharedNotebook createSharedNotebook(string authenticationToken, SharedNotebook sharedNotebook)' 85 | print ' i32 sendMessageToSharedNotebookMembers(string authenticationToken, Guid notebookGuid, string messageText, recipients)' 86 | print ' listSharedNotebooks(string authenticationToken)' 87 | print ' i32 expungeSharedNotebooks(string authenticationToken, sharedNotebookIds)' 88 | print ' LinkedNotebook createLinkedNotebook(string authenticationToken, LinkedNotebook linkedNotebook)' 89 | print ' i32 updateLinkedNotebook(string authenticationToken, LinkedNotebook linkedNotebook)' 90 | print ' listLinkedNotebooks(string authenticationToken)' 91 | print ' i32 expungeLinkedNotebook(string authenticationToken, Guid guid)' 92 | print ' AuthenticationResult authenticateToSharedNotebook(string shareKey, string authenticationToken)' 93 | print ' SharedNotebook getSharedNotebookByAuth(string authenticationToken)' 94 | print ' void emailNote(string authenticationToken, NoteEmailParameters parameters)' 95 | print ' string shareNote(string authenticationToken, Guid guid)' 96 | print ' void stopSharingNote(string authenticationToken, Guid guid)' 97 | print ' AuthenticationResult authenticateToSharedNote(string guid, string noteKey)' 98 | print '' 99 | sys.exit(0) 100 | 101 | pp = pprint.PrettyPrinter(indent = 2) 102 | host = 'localhost' 103 | port = 9090 104 | uri = '' 105 | framed = False 106 | http = False 107 | argi = 1 108 | 109 | if sys.argv[argi] == '-h': 110 | parts = sys.argv[argi+1].split(':') 111 | host = parts[0] 112 | port = int(parts[1]) 113 | argi += 2 114 | 115 | if sys.argv[argi] == '-u': 116 | url = urlparse(sys.argv[argi+1]) 117 | parts = url[1].split(':') 118 | host = parts[0] 119 | if len(parts) > 1: 120 | port = int(parts[1]) 121 | else: 122 | port = 80 123 | uri = url[2] 124 | http = True 125 | argi += 2 126 | 127 | if sys.argv[argi] == '-f' or sys.argv[argi] == '-framed': 128 | framed = True 129 | argi += 1 130 | 131 | cmd = sys.argv[argi] 132 | args = sys.argv[argi+1:] 133 | 134 | if http: 135 | transport = THttpClient.THttpClient(host, port, uri) 136 | else: 137 | socket = TSocket.TSocket(host, port) 138 | if framed: 139 | transport = TTransport.TFramedTransport(socket) 140 | else: 141 | transport = TTransport.TBufferedTransport(socket) 142 | protocol = TBinaryProtocol.TBinaryProtocol(transport) 143 | client = NoteStore.Client(protocol) 144 | transport.open() 145 | 146 | if cmd == 'getSyncState': 147 | if len(args) != 1: 148 | print 'getSyncState requires 1 args' 149 | sys.exit(1) 150 | pp.pprint(client.getSyncState(args[0],)) 151 | 152 | elif cmd == 'getSyncChunk': 153 | if len(args) != 4: 154 | print 'getSyncChunk requires 4 args' 155 | sys.exit(1) 156 | pp.pprint(client.getSyncChunk(args[0],eval(args[1]),eval(args[2]),eval(args[3]),)) 157 | 158 | elif cmd == 'getFilteredSyncChunk': 159 | if len(args) != 4: 160 | print 'getFilteredSyncChunk requires 4 args' 161 | sys.exit(1) 162 | pp.pprint(client.getFilteredSyncChunk(args[0],eval(args[1]),eval(args[2]),eval(args[3]),)) 163 | 164 | elif cmd == 'getLinkedNotebookSyncState': 165 | if len(args) != 2: 166 | print 'getLinkedNotebookSyncState requires 2 args' 167 | sys.exit(1) 168 | pp.pprint(client.getLinkedNotebookSyncState(args[0],eval(args[1]),)) 169 | 170 | elif cmd == 'getLinkedNotebookSyncChunk': 171 | if len(args) != 5: 172 | print 'getLinkedNotebookSyncChunk requires 5 args' 173 | sys.exit(1) 174 | pp.pprint(client.getLinkedNotebookSyncChunk(args[0],eval(args[1]),eval(args[2]),eval(args[3]),eval(args[4]),)) 175 | 176 | elif cmd == 'listNotebooks': 177 | if len(args) != 1: 178 | print 'listNotebooks requires 1 args' 179 | sys.exit(1) 180 | pp.pprint(client.listNotebooks(args[0],)) 181 | 182 | elif cmd == 'getNotebook': 183 | if len(args) != 2: 184 | print 'getNotebook requires 2 args' 185 | sys.exit(1) 186 | pp.pprint(client.getNotebook(args[0],eval(args[1]),)) 187 | 188 | elif cmd == 'getDefaultNotebook': 189 | if len(args) != 1: 190 | print 'getDefaultNotebook requires 1 args' 191 | sys.exit(1) 192 | pp.pprint(client.getDefaultNotebook(args[0],)) 193 | 194 | elif cmd == 'createNotebook': 195 | if len(args) != 2: 196 | print 'createNotebook requires 2 args' 197 | sys.exit(1) 198 | pp.pprint(client.createNotebook(args[0],eval(args[1]),)) 199 | 200 | elif cmd == 'updateNotebook': 201 | if len(args) != 2: 202 | print 'updateNotebook requires 2 args' 203 | sys.exit(1) 204 | pp.pprint(client.updateNotebook(args[0],eval(args[1]),)) 205 | 206 | elif cmd == 'expungeNotebook': 207 | if len(args) != 2: 208 | print 'expungeNotebook requires 2 args' 209 | sys.exit(1) 210 | pp.pprint(client.expungeNotebook(args[0],eval(args[1]),)) 211 | 212 | elif cmd == 'listTags': 213 | if len(args) != 1: 214 | print 'listTags requires 1 args' 215 | sys.exit(1) 216 | pp.pprint(client.listTags(args[0],)) 217 | 218 | elif cmd == 'listTagsByNotebook': 219 | if len(args) != 2: 220 | print 'listTagsByNotebook requires 2 args' 221 | sys.exit(1) 222 | pp.pprint(client.listTagsByNotebook(args[0],eval(args[1]),)) 223 | 224 | elif cmd == 'getTag': 225 | if len(args) != 2: 226 | print 'getTag requires 2 args' 227 | sys.exit(1) 228 | pp.pprint(client.getTag(args[0],eval(args[1]),)) 229 | 230 | elif cmd == 'createTag': 231 | if len(args) != 2: 232 | print 'createTag requires 2 args' 233 | sys.exit(1) 234 | pp.pprint(client.createTag(args[0],eval(args[1]),)) 235 | 236 | elif cmd == 'updateTag': 237 | if len(args) != 2: 238 | print 'updateTag requires 2 args' 239 | sys.exit(1) 240 | pp.pprint(client.updateTag(args[0],eval(args[1]),)) 241 | 242 | elif cmd == 'untagAll': 243 | if len(args) != 2: 244 | print 'untagAll requires 2 args' 245 | sys.exit(1) 246 | pp.pprint(client.untagAll(args[0],eval(args[1]),)) 247 | 248 | elif cmd == 'expungeTag': 249 | if len(args) != 2: 250 | print 'expungeTag requires 2 args' 251 | sys.exit(1) 252 | pp.pprint(client.expungeTag(args[0],eval(args[1]),)) 253 | 254 | elif cmd == 'listSearches': 255 | if len(args) != 1: 256 | print 'listSearches requires 1 args' 257 | sys.exit(1) 258 | pp.pprint(client.listSearches(args[0],)) 259 | 260 | elif cmd == 'getSearch': 261 | if len(args) != 2: 262 | print 'getSearch requires 2 args' 263 | sys.exit(1) 264 | pp.pprint(client.getSearch(args[0],eval(args[1]),)) 265 | 266 | elif cmd == 'createSearch': 267 | if len(args) != 2: 268 | print 'createSearch requires 2 args' 269 | sys.exit(1) 270 | pp.pprint(client.createSearch(args[0],eval(args[1]),)) 271 | 272 | elif cmd == 'updateSearch': 273 | if len(args) != 2: 274 | print 'updateSearch requires 2 args' 275 | sys.exit(1) 276 | pp.pprint(client.updateSearch(args[0],eval(args[1]),)) 277 | 278 | elif cmd == 'expungeSearch': 279 | if len(args) != 2: 280 | print 'expungeSearch requires 2 args' 281 | sys.exit(1) 282 | pp.pprint(client.expungeSearch(args[0],eval(args[1]),)) 283 | 284 | elif cmd == 'findNotes': 285 | if len(args) != 4: 286 | print 'findNotes requires 4 args' 287 | sys.exit(1) 288 | pp.pprint(client.findNotes(args[0],eval(args[1]),eval(args[2]),eval(args[3]),)) 289 | 290 | elif cmd == 'findNoteOffset': 291 | if len(args) != 3: 292 | print 'findNoteOffset requires 3 args' 293 | sys.exit(1) 294 | pp.pprint(client.findNoteOffset(args[0],eval(args[1]),eval(args[2]),)) 295 | 296 | elif cmd == 'findNotesMetadata': 297 | if len(args) != 5: 298 | print 'findNotesMetadata requires 5 args' 299 | sys.exit(1) 300 | pp.pprint(client.findNotesMetadata(args[0],eval(args[1]),eval(args[2]),eval(args[3]),eval(args[4]),)) 301 | 302 | elif cmd == 'findNoteCounts': 303 | if len(args) != 3: 304 | print 'findNoteCounts requires 3 args' 305 | sys.exit(1) 306 | pp.pprint(client.findNoteCounts(args[0],eval(args[1]),eval(args[2]),)) 307 | 308 | elif cmd == 'getNote': 309 | if len(args) != 6: 310 | print 'getNote requires 6 args' 311 | sys.exit(1) 312 | pp.pprint(client.getNote(args[0],eval(args[1]),eval(args[2]),eval(args[3]),eval(args[4]),eval(args[5]),)) 313 | 314 | elif cmd == 'getNoteApplicationData': 315 | if len(args) != 2: 316 | print 'getNoteApplicationData requires 2 args' 317 | sys.exit(1) 318 | pp.pprint(client.getNoteApplicationData(args[0],eval(args[1]),)) 319 | 320 | elif cmd == 'getNoteApplicationDataEntry': 321 | if len(args) != 3: 322 | print 'getNoteApplicationDataEntry requires 3 args' 323 | sys.exit(1) 324 | pp.pprint(client.getNoteApplicationDataEntry(args[0],eval(args[1]),args[2],)) 325 | 326 | elif cmd == 'setNoteApplicationDataEntry': 327 | if len(args) != 4: 328 | print 'setNoteApplicationDataEntry requires 4 args' 329 | sys.exit(1) 330 | pp.pprint(client.setNoteApplicationDataEntry(args[0],eval(args[1]),args[2],args[3],)) 331 | 332 | elif cmd == 'unsetNoteApplicationDataEntry': 333 | if len(args) != 3: 334 | print 'unsetNoteApplicationDataEntry requires 3 args' 335 | sys.exit(1) 336 | pp.pprint(client.unsetNoteApplicationDataEntry(args[0],eval(args[1]),args[2],)) 337 | 338 | elif cmd == 'getNoteContent': 339 | if len(args) != 2: 340 | print 'getNoteContent requires 2 args' 341 | sys.exit(1) 342 | pp.pprint(client.getNoteContent(args[0],eval(args[1]),)) 343 | 344 | elif cmd == 'getNoteSearchText': 345 | if len(args) != 4: 346 | print 'getNoteSearchText requires 4 args' 347 | sys.exit(1) 348 | pp.pprint(client.getNoteSearchText(args[0],eval(args[1]),eval(args[2]),eval(args[3]),)) 349 | 350 | elif cmd == 'getResourceSearchText': 351 | if len(args) != 2: 352 | print 'getResourceSearchText requires 2 args' 353 | sys.exit(1) 354 | pp.pprint(client.getResourceSearchText(args[0],eval(args[1]),)) 355 | 356 | elif cmd == 'getNoteTagNames': 357 | if len(args) != 2: 358 | print 'getNoteTagNames requires 2 args' 359 | sys.exit(1) 360 | pp.pprint(client.getNoteTagNames(args[0],eval(args[1]),)) 361 | 362 | elif cmd == 'createNote': 363 | if len(args) != 2: 364 | print 'createNote requires 2 args' 365 | sys.exit(1) 366 | pp.pprint(client.createNote(args[0],eval(args[1]),)) 367 | 368 | elif cmd == 'updateNote': 369 | if len(args) != 2: 370 | print 'updateNote requires 2 args' 371 | sys.exit(1) 372 | pp.pprint(client.updateNote(args[0],eval(args[1]),)) 373 | 374 | elif cmd == 'deleteNote': 375 | if len(args) != 2: 376 | print 'deleteNote requires 2 args' 377 | sys.exit(1) 378 | pp.pprint(client.deleteNote(args[0],eval(args[1]),)) 379 | 380 | elif cmd == 'expungeNote': 381 | if len(args) != 2: 382 | print 'expungeNote requires 2 args' 383 | sys.exit(1) 384 | pp.pprint(client.expungeNote(args[0],eval(args[1]),)) 385 | 386 | elif cmd == 'expungeNotes': 387 | if len(args) != 2: 388 | print 'expungeNotes requires 2 args' 389 | sys.exit(1) 390 | pp.pprint(client.expungeNotes(args[0],eval(args[1]),)) 391 | 392 | elif cmd == 'expungeInactiveNotes': 393 | if len(args) != 1: 394 | print 'expungeInactiveNotes requires 1 args' 395 | sys.exit(1) 396 | pp.pprint(client.expungeInactiveNotes(args[0],)) 397 | 398 | elif cmd == 'copyNote': 399 | if len(args) != 3: 400 | print 'copyNote requires 3 args' 401 | sys.exit(1) 402 | pp.pprint(client.copyNote(args[0],eval(args[1]),eval(args[2]),)) 403 | 404 | elif cmd == 'listNoteVersions': 405 | if len(args) != 2: 406 | print 'listNoteVersions requires 2 args' 407 | sys.exit(1) 408 | pp.pprint(client.listNoteVersions(args[0],eval(args[1]),)) 409 | 410 | elif cmd == 'getNoteVersion': 411 | if len(args) != 6: 412 | print 'getNoteVersion requires 6 args' 413 | sys.exit(1) 414 | pp.pprint(client.getNoteVersion(args[0],eval(args[1]),eval(args[2]),eval(args[3]),eval(args[4]),eval(args[5]),)) 415 | 416 | elif cmd == 'getResource': 417 | if len(args) != 6: 418 | print 'getResource requires 6 args' 419 | sys.exit(1) 420 | pp.pprint(client.getResource(args[0],eval(args[1]),eval(args[2]),eval(args[3]),eval(args[4]),eval(args[5]),)) 421 | 422 | elif cmd == 'getResourceApplicationData': 423 | if len(args) != 2: 424 | print 'getResourceApplicationData requires 2 args' 425 | sys.exit(1) 426 | pp.pprint(client.getResourceApplicationData(args[0],eval(args[1]),)) 427 | 428 | elif cmd == 'getResourceApplicationDataEntry': 429 | if len(args) != 3: 430 | print 'getResourceApplicationDataEntry requires 3 args' 431 | sys.exit(1) 432 | pp.pprint(client.getResourceApplicationDataEntry(args[0],eval(args[1]),args[2],)) 433 | 434 | elif cmd == 'setResourceApplicationDataEntry': 435 | if len(args) != 4: 436 | print 'setResourceApplicationDataEntry requires 4 args' 437 | sys.exit(1) 438 | pp.pprint(client.setResourceApplicationDataEntry(args[0],eval(args[1]),args[2],args[3],)) 439 | 440 | elif cmd == 'unsetResourceApplicationDataEntry': 441 | if len(args) != 3: 442 | print 'unsetResourceApplicationDataEntry requires 3 args' 443 | sys.exit(1) 444 | pp.pprint(client.unsetResourceApplicationDataEntry(args[0],eval(args[1]),args[2],)) 445 | 446 | elif cmd == 'updateResource': 447 | if len(args) != 2: 448 | print 'updateResource requires 2 args' 449 | sys.exit(1) 450 | pp.pprint(client.updateResource(args[0],eval(args[1]),)) 451 | 452 | elif cmd == 'getResourceData': 453 | if len(args) != 2: 454 | print 'getResourceData requires 2 args' 455 | sys.exit(1) 456 | pp.pprint(client.getResourceData(args[0],eval(args[1]),)) 457 | 458 | elif cmd == 'getResourceByHash': 459 | if len(args) != 6: 460 | print 'getResourceByHash requires 6 args' 461 | sys.exit(1) 462 | pp.pprint(client.getResourceByHash(args[0],eval(args[1]),args[2],eval(args[3]),eval(args[4]),eval(args[5]),)) 463 | 464 | elif cmd == 'getResourceRecognition': 465 | if len(args) != 2: 466 | print 'getResourceRecognition requires 2 args' 467 | sys.exit(1) 468 | pp.pprint(client.getResourceRecognition(args[0],eval(args[1]),)) 469 | 470 | elif cmd == 'getResourceAlternateData': 471 | if len(args) != 2: 472 | print 'getResourceAlternateData requires 2 args' 473 | sys.exit(1) 474 | pp.pprint(client.getResourceAlternateData(args[0],eval(args[1]),)) 475 | 476 | elif cmd == 'getResourceAttributes': 477 | if len(args) != 2: 478 | print 'getResourceAttributes requires 2 args' 479 | sys.exit(1) 480 | pp.pprint(client.getResourceAttributes(args[0],eval(args[1]),)) 481 | 482 | elif cmd == 'getAccountSize': 483 | if len(args) != 1: 484 | print 'getAccountSize requires 1 args' 485 | sys.exit(1) 486 | pp.pprint(client.getAccountSize(args[0],)) 487 | 488 | elif cmd == 'getAds': 489 | if len(args) != 2: 490 | print 'getAds requires 2 args' 491 | sys.exit(1) 492 | pp.pprint(client.getAds(args[0],eval(args[1]),)) 493 | 494 | elif cmd == 'getRandomAd': 495 | if len(args) != 2: 496 | print 'getRandomAd requires 2 args' 497 | sys.exit(1) 498 | pp.pprint(client.getRandomAd(args[0],eval(args[1]),)) 499 | 500 | elif cmd == 'getPublicNotebook': 501 | if len(args) != 2: 502 | print 'getPublicNotebook requires 2 args' 503 | sys.exit(1) 504 | pp.pprint(client.getPublicNotebook(eval(args[0]),args[1],)) 505 | 506 | elif cmd == 'createSharedNotebook': 507 | if len(args) != 2: 508 | print 'createSharedNotebook requires 2 args' 509 | sys.exit(1) 510 | pp.pprint(client.createSharedNotebook(args[0],eval(args[1]),)) 511 | 512 | elif cmd == 'sendMessageToSharedNotebookMembers': 513 | if len(args) != 4: 514 | print 'sendMessageToSharedNotebookMembers requires 4 args' 515 | sys.exit(1) 516 | pp.pprint(client.sendMessageToSharedNotebookMembers(args[0],eval(args[1]),args[2],eval(args[3]),)) 517 | 518 | elif cmd == 'listSharedNotebooks': 519 | if len(args) != 1: 520 | print 'listSharedNotebooks requires 1 args' 521 | sys.exit(1) 522 | pp.pprint(client.listSharedNotebooks(args[0],)) 523 | 524 | elif cmd == 'expungeSharedNotebooks': 525 | if len(args) != 2: 526 | print 'expungeSharedNotebooks requires 2 args' 527 | sys.exit(1) 528 | pp.pprint(client.expungeSharedNotebooks(args[0],eval(args[1]),)) 529 | 530 | elif cmd == 'createLinkedNotebook': 531 | if len(args) != 2: 532 | print 'createLinkedNotebook requires 2 args' 533 | sys.exit(1) 534 | pp.pprint(client.createLinkedNotebook(args[0],eval(args[1]),)) 535 | 536 | elif cmd == 'updateLinkedNotebook': 537 | if len(args) != 2: 538 | print 'updateLinkedNotebook requires 2 args' 539 | sys.exit(1) 540 | pp.pprint(client.updateLinkedNotebook(args[0],eval(args[1]),)) 541 | 542 | elif cmd == 'listLinkedNotebooks': 543 | if len(args) != 1: 544 | print 'listLinkedNotebooks requires 1 args' 545 | sys.exit(1) 546 | pp.pprint(client.listLinkedNotebooks(args[0],)) 547 | 548 | elif cmd == 'expungeLinkedNotebook': 549 | if len(args) != 2: 550 | print 'expungeLinkedNotebook requires 2 args' 551 | sys.exit(1) 552 | pp.pprint(client.expungeLinkedNotebook(args[0],eval(args[1]),)) 553 | 554 | elif cmd == 'authenticateToSharedNotebook': 555 | if len(args) != 2: 556 | print 'authenticateToSharedNotebook requires 2 args' 557 | sys.exit(1) 558 | pp.pprint(client.authenticateToSharedNotebook(args[0],args[1],)) 559 | 560 | elif cmd == 'getSharedNotebookByAuth': 561 | if len(args) != 1: 562 | print 'getSharedNotebookByAuth requires 1 args' 563 | sys.exit(1) 564 | pp.pprint(client.getSharedNotebookByAuth(args[0],)) 565 | 566 | elif cmd == 'emailNote': 567 | if len(args) != 2: 568 | print 'emailNote requires 2 args' 569 | sys.exit(1) 570 | pp.pprint(client.emailNote(args[0],eval(args[1]),)) 571 | 572 | elif cmd == 'shareNote': 573 | if len(args) != 2: 574 | print 'shareNote requires 2 args' 575 | sys.exit(1) 576 | pp.pprint(client.shareNote(args[0],eval(args[1]),)) 577 | 578 | elif cmd == 'stopSharingNote': 579 | if len(args) != 2: 580 | print 'stopSharingNote requires 2 args' 581 | sys.exit(1) 582 | pp.pprint(client.stopSharingNote(args[0],eval(args[1]),)) 583 | 584 | elif cmd == 'authenticateToSharedNote': 585 | if len(args) != 2: 586 | print 'authenticateToSharedNote requires 2 args' 587 | sys.exit(1) 588 | pp.pprint(client.authenticateToSharedNote(args[0],args[1],)) 589 | 590 | transport.close() 591 | -------------------------------------------------------------------------------- /src/thrift/protocol/fastbinary.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one 3 | * or more contributor license agreements. See the NOTICE file 4 | * distributed with this work for additional information 5 | * regarding copyright ownership. The ASF licenses this file 6 | * to you under the Apache License, Version 2.0 (the 7 | * "License"); you may not use this file except in compliance 8 | * with the License. You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, 13 | * software distributed under the License is distributed on an 14 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 15 | * KIND, either express or implied. See the License for the 16 | * specific language governing permissions and limitations 17 | * under the License. 18 | */ 19 | 20 | #include 21 | #include "cStringIO.h" 22 | #include 23 | #include 24 | #include 25 | 26 | /* Fix endianness issues on Solaris */ 27 | #if defined (__SVR4) && defined (__sun) 28 | #if defined(__i386) && !defined(__i386__) 29 | #define __i386__ 30 | #endif 31 | 32 | #ifndef BIG_ENDIAN 33 | #define BIG_ENDIAN (4321) 34 | #endif 35 | #ifndef LITTLE_ENDIAN 36 | #define LITTLE_ENDIAN (1234) 37 | #endif 38 | 39 | /* I386 is LE, even on Solaris */ 40 | #if !defined(BYTE_ORDER) && defined(__i386__) 41 | #define BYTE_ORDER LITTLE_ENDIAN 42 | #endif 43 | #endif 44 | 45 | // TODO(dreiss): defval appears to be unused. Look into removing it. 46 | // TODO(dreiss): Make parse_spec_args recursive, and cache the output 47 | // permanently in the object. (Malloc and orphan.) 48 | // TODO(dreiss): Why do we need cStringIO for reading, why not just char*? 49 | // Can cStringIO let us work with a BufferedTransport? 50 | // TODO(dreiss): Don't ignore the rv from cwrite (maybe). 51 | 52 | /* ====== BEGIN UTILITIES ====== */ 53 | 54 | #define INIT_OUTBUF_SIZE 128 55 | 56 | // Stolen out of TProtocol.h. 57 | // It would be a huge pain to have both get this from one place. 58 | typedef enum TType { 59 | T_STOP = 0, 60 | T_VOID = 1, 61 | T_BOOL = 2, 62 | T_BYTE = 3, 63 | T_I08 = 3, 64 | T_I16 = 6, 65 | T_I32 = 8, 66 | T_U64 = 9, 67 | T_I64 = 10, 68 | T_DOUBLE = 4, 69 | T_STRING = 11, 70 | T_UTF7 = 11, 71 | T_STRUCT = 12, 72 | T_MAP = 13, 73 | T_SET = 14, 74 | T_LIST = 15, 75 | T_UTF8 = 16, 76 | T_UTF16 = 17 77 | } TType; 78 | 79 | #ifndef __BYTE_ORDER 80 | # if defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && defined(BIG_ENDIAN) 81 | # define __BYTE_ORDER BYTE_ORDER 82 | # define __LITTLE_ENDIAN LITTLE_ENDIAN 83 | # define __BIG_ENDIAN BIG_ENDIAN 84 | # else 85 | # error "Cannot determine endianness" 86 | # endif 87 | #endif 88 | 89 | // Same comment as the enum. Sorry. 90 | #if __BYTE_ORDER == __BIG_ENDIAN 91 | # define ntohll(n) (n) 92 | # define htonll(n) (n) 93 | #elif __BYTE_ORDER == __LITTLE_ENDIAN 94 | # if defined(__GNUC__) && defined(__GLIBC__) 95 | # include 96 | # define ntohll(n) bswap_64(n) 97 | # define htonll(n) bswap_64(n) 98 | # else /* GNUC & GLIBC */ 99 | # define ntohll(n) ( (((unsigned long long)ntohl(n)) << 32) + ntohl(n >> 32) ) 100 | # define htonll(n) ( (((unsigned long long)htonl(n)) << 32) + htonl(n >> 32) ) 101 | # endif /* GNUC & GLIBC */ 102 | #else /* __BYTE_ORDER */ 103 | # error "Can't define htonll or ntohll!" 104 | #endif 105 | 106 | // Doing a benchmark shows that interning actually makes a difference, amazingly. 107 | #define INTERN_STRING(value) _intern_ ## value 108 | 109 | #define INT_CONV_ERROR_OCCURRED(v) ( ((v) == -1) && PyErr_Occurred() ) 110 | #define CHECK_RANGE(v, min, max) ( ((v) <= (max)) && ((v) >= (min)) ) 111 | 112 | // Py_ssize_t was not defined before Python 2.5 113 | #if (PY_VERSION_HEX < 0x02050000) 114 | typedef int Py_ssize_t; 115 | #endif 116 | 117 | /** 118 | * A cache of the spec_args for a set or list, 119 | * so we don't have to keep calling PyTuple_GET_ITEM. 120 | */ 121 | typedef struct { 122 | TType element_type; 123 | PyObject* typeargs; 124 | } SetListTypeArgs; 125 | 126 | /** 127 | * A cache of the spec_args for a map, 128 | * so we don't have to keep calling PyTuple_GET_ITEM. 129 | */ 130 | typedef struct { 131 | TType ktag; 132 | TType vtag; 133 | PyObject* ktypeargs; 134 | PyObject* vtypeargs; 135 | } MapTypeArgs; 136 | 137 | /** 138 | * A cache of the spec_args for a struct, 139 | * so we don't have to keep calling PyTuple_GET_ITEM. 140 | */ 141 | typedef struct { 142 | PyObject* klass; 143 | PyObject* spec; 144 | } StructTypeArgs; 145 | 146 | /** 147 | * A cache of the item spec from a struct specification, 148 | * so we don't have to keep calling PyTuple_GET_ITEM. 149 | */ 150 | typedef struct { 151 | int tag; 152 | TType type; 153 | PyObject* attrname; 154 | PyObject* typeargs; 155 | PyObject* defval; 156 | } StructItemSpec; 157 | 158 | /** 159 | * A cache of the two key attributes of a CReadableTransport, 160 | * so we don't have to keep calling PyObject_GetAttr. 161 | */ 162 | typedef struct { 163 | PyObject* stringiobuf; 164 | PyObject* refill_callable; 165 | } DecodeBuffer; 166 | 167 | /** Pointer to interned string to speed up attribute lookup. */ 168 | static PyObject* INTERN_STRING(cstringio_buf); 169 | /** Pointer to interned string to speed up attribute lookup. */ 170 | static PyObject* INTERN_STRING(cstringio_refill); 171 | 172 | static inline bool 173 | check_ssize_t_32(Py_ssize_t len) { 174 | // error from getting the int 175 | if (INT_CONV_ERROR_OCCURRED(len)) { 176 | return false; 177 | } 178 | if (!CHECK_RANGE(len, 0, INT32_MAX)) { 179 | PyErr_SetString(PyExc_OverflowError, "string size out of range"); 180 | return false; 181 | } 182 | return true; 183 | } 184 | 185 | static inline bool 186 | parse_pyint(PyObject* o, int32_t* ret, int32_t min, int32_t max) { 187 | long val = PyInt_AsLong(o); 188 | 189 | if (INT_CONV_ERROR_OCCURRED(val)) { 190 | return false; 191 | } 192 | if (!CHECK_RANGE(val, min, max)) { 193 | PyErr_SetString(PyExc_OverflowError, "int out of range"); 194 | return false; 195 | } 196 | 197 | *ret = (int32_t) val; 198 | return true; 199 | } 200 | 201 | 202 | /* --- FUNCTIONS TO PARSE STRUCT SPECIFICATOINS --- */ 203 | 204 | static bool 205 | parse_set_list_args(SetListTypeArgs* dest, PyObject* typeargs) { 206 | if (PyTuple_Size(typeargs) != 2) { 207 | PyErr_SetString(PyExc_TypeError, "expecting tuple of size 2 for list/set type args"); 208 | return false; 209 | } 210 | 211 | dest->element_type = PyInt_AsLong(PyTuple_GET_ITEM(typeargs, 0)); 212 | if (INT_CONV_ERROR_OCCURRED(dest->element_type)) { 213 | return false; 214 | } 215 | 216 | dest->typeargs = PyTuple_GET_ITEM(typeargs, 1); 217 | 218 | return true; 219 | } 220 | 221 | static bool 222 | parse_map_args(MapTypeArgs* dest, PyObject* typeargs) { 223 | if (PyTuple_Size(typeargs) != 4) { 224 | PyErr_SetString(PyExc_TypeError, "expecting 4 arguments for typeargs to map"); 225 | return false; 226 | } 227 | 228 | dest->ktag = PyInt_AsLong(PyTuple_GET_ITEM(typeargs, 0)); 229 | if (INT_CONV_ERROR_OCCURRED(dest->ktag)) { 230 | return false; 231 | } 232 | 233 | dest->vtag = PyInt_AsLong(PyTuple_GET_ITEM(typeargs, 2)); 234 | if (INT_CONV_ERROR_OCCURRED(dest->vtag)) { 235 | return false; 236 | } 237 | 238 | dest->ktypeargs = PyTuple_GET_ITEM(typeargs, 1); 239 | dest->vtypeargs = PyTuple_GET_ITEM(typeargs, 3); 240 | 241 | return true; 242 | } 243 | 244 | static bool 245 | parse_struct_args(StructTypeArgs* dest, PyObject* typeargs) { 246 | if (PyTuple_Size(typeargs) != 2) { 247 | PyErr_SetString(PyExc_TypeError, "expecting tuple of size 2 for struct args"); 248 | return false; 249 | } 250 | 251 | dest->klass = PyTuple_GET_ITEM(typeargs, 0); 252 | dest->spec = PyTuple_GET_ITEM(typeargs, 1); 253 | 254 | return true; 255 | } 256 | 257 | static int 258 | parse_struct_item_spec(StructItemSpec* dest, PyObject* spec_tuple) { 259 | 260 | // i'd like to use ParseArgs here, but it seems to be a bottleneck. 261 | if (PyTuple_Size(spec_tuple) != 5) { 262 | PyErr_SetString(PyExc_TypeError, "expecting 5 arguments for spec tuple"); 263 | return false; 264 | } 265 | 266 | dest->tag = PyInt_AsLong(PyTuple_GET_ITEM(spec_tuple, 0)); 267 | if (INT_CONV_ERROR_OCCURRED(dest->tag)) { 268 | return false; 269 | } 270 | 271 | dest->type = PyInt_AsLong(PyTuple_GET_ITEM(spec_tuple, 1)); 272 | if (INT_CONV_ERROR_OCCURRED(dest->type)) { 273 | return false; 274 | } 275 | 276 | dest->attrname = PyTuple_GET_ITEM(spec_tuple, 2); 277 | dest->typeargs = PyTuple_GET_ITEM(spec_tuple, 3); 278 | dest->defval = PyTuple_GET_ITEM(spec_tuple, 4); 279 | return true; 280 | } 281 | 282 | /* ====== END UTILITIES ====== */ 283 | 284 | 285 | /* ====== BEGIN WRITING FUNCTIONS ====== */ 286 | 287 | /* --- LOW-LEVEL WRITING FUNCTIONS --- */ 288 | 289 | static void writeByte(PyObject* outbuf, int8_t val) { 290 | int8_t net = val; 291 | PycStringIO->cwrite(outbuf, (char*)&net, sizeof(int8_t)); 292 | } 293 | 294 | static void writeI16(PyObject* outbuf, int16_t val) { 295 | int16_t net = (int16_t)htons(val); 296 | PycStringIO->cwrite(outbuf, (char*)&net, sizeof(int16_t)); 297 | } 298 | 299 | static void writeI32(PyObject* outbuf, int32_t val) { 300 | int32_t net = (int32_t)htonl(val); 301 | PycStringIO->cwrite(outbuf, (char*)&net, sizeof(int32_t)); 302 | } 303 | 304 | static void writeI64(PyObject* outbuf, int64_t val) { 305 | int64_t net = (int64_t)htonll(val); 306 | PycStringIO->cwrite(outbuf, (char*)&net, sizeof(int64_t)); 307 | } 308 | 309 | static void writeDouble(PyObject* outbuf, double dub) { 310 | // Unfortunately, bitwise_cast doesn't work in C. Bad C! 311 | union { 312 | double f; 313 | int64_t t; 314 | } transfer; 315 | transfer.f = dub; 316 | writeI64(outbuf, transfer.t); 317 | } 318 | 319 | 320 | /* --- MAIN RECURSIVE OUTPUT FUCNTION -- */ 321 | 322 | static int 323 | output_val(PyObject* output, PyObject* value, TType type, PyObject* typeargs) { 324 | /* 325 | * Refcounting Strategy: 326 | * 327 | * We assume that elements of the thrift_spec tuple are not going to be 328 | * mutated, so we don't ref count those at all. Other than that, we try to 329 | * keep a reference to all the user-created objects while we work with them. 330 | * output_val assumes that a reference is already held. The *caller* is 331 | * responsible for handling references 332 | */ 333 | 334 | switch (type) { 335 | 336 | case T_BOOL: { 337 | int v = PyObject_IsTrue(value); 338 | if (v == -1) { 339 | return false; 340 | } 341 | 342 | writeByte(output, (int8_t) v); 343 | break; 344 | } 345 | case T_I08: { 346 | int32_t val; 347 | 348 | if (!parse_pyint(value, &val, INT8_MIN, INT8_MAX)) { 349 | return false; 350 | } 351 | 352 | writeByte(output, (int8_t) val); 353 | break; 354 | } 355 | case T_I16: { 356 | int32_t val; 357 | 358 | if (!parse_pyint(value, &val, INT16_MIN, INT16_MAX)) { 359 | return false; 360 | } 361 | 362 | writeI16(output, (int16_t) val); 363 | break; 364 | } 365 | case T_I32: { 366 | int32_t val; 367 | 368 | if (!parse_pyint(value, &val, INT32_MIN, INT32_MAX)) { 369 | return false; 370 | } 371 | 372 | writeI32(output, val); 373 | break; 374 | } 375 | case T_I64: { 376 | int64_t nval = PyLong_AsLongLong(value); 377 | 378 | if (INT_CONV_ERROR_OCCURRED(nval)) { 379 | return false; 380 | } 381 | 382 | if (!CHECK_RANGE(nval, INT64_MIN, INT64_MAX)) { 383 | PyErr_SetString(PyExc_OverflowError, "int out of range"); 384 | return false; 385 | } 386 | 387 | writeI64(output, nval); 388 | break; 389 | } 390 | 391 | case T_DOUBLE: { 392 | double nval = PyFloat_AsDouble(value); 393 | if (nval == -1.0 && PyErr_Occurred()) { 394 | return false; 395 | } 396 | 397 | writeDouble(output, nval); 398 | break; 399 | } 400 | 401 | case T_STRING: { 402 | Py_ssize_t len = PyString_Size(value); 403 | 404 | if (!check_ssize_t_32(len)) { 405 | return false; 406 | } 407 | 408 | writeI32(output, (int32_t) len); 409 | PycStringIO->cwrite(output, PyString_AsString(value), (int32_t) len); 410 | break; 411 | } 412 | 413 | case T_LIST: 414 | case T_SET: { 415 | Py_ssize_t len; 416 | SetListTypeArgs parsedargs; 417 | PyObject *item; 418 | PyObject *iterator; 419 | 420 | if (!parse_set_list_args(&parsedargs, typeargs)) { 421 | return false; 422 | } 423 | 424 | len = PyObject_Length(value); 425 | 426 | if (!check_ssize_t_32(len)) { 427 | return false; 428 | } 429 | 430 | writeByte(output, parsedargs.element_type); 431 | writeI32(output, (int32_t) len); 432 | 433 | iterator = PyObject_GetIter(value); 434 | if (iterator == NULL) { 435 | return false; 436 | } 437 | 438 | while ((item = PyIter_Next(iterator))) { 439 | if (!output_val(output, item, parsedargs.element_type, parsedargs.typeargs)) { 440 | Py_DECREF(item); 441 | Py_DECREF(iterator); 442 | return false; 443 | } 444 | Py_DECREF(item); 445 | } 446 | 447 | Py_DECREF(iterator); 448 | 449 | if (PyErr_Occurred()) { 450 | return false; 451 | } 452 | 453 | break; 454 | } 455 | 456 | case T_MAP: { 457 | PyObject *k, *v; 458 | Py_ssize_t pos = 0; 459 | Py_ssize_t len; 460 | 461 | MapTypeArgs parsedargs; 462 | 463 | len = PyDict_Size(value); 464 | if (!check_ssize_t_32(len)) { 465 | return false; 466 | } 467 | 468 | if (!parse_map_args(&parsedargs, typeargs)) { 469 | return false; 470 | } 471 | 472 | writeByte(output, parsedargs.ktag); 473 | writeByte(output, parsedargs.vtag); 474 | writeI32(output, len); 475 | 476 | // TODO(bmaurer): should support any mapping, not just dicts 477 | while (PyDict_Next(value, &pos, &k, &v)) { 478 | // TODO(dreiss): Think hard about whether these INCREFs actually 479 | // turn any unsafe scenarios into safe scenarios. 480 | Py_INCREF(k); 481 | Py_INCREF(v); 482 | 483 | if (!output_val(output, k, parsedargs.ktag, parsedargs.ktypeargs) 484 | || !output_val(output, v, parsedargs.vtag, parsedargs.vtypeargs)) { 485 | Py_DECREF(k); 486 | Py_DECREF(v); 487 | return false; 488 | } 489 | Py_DECREF(k); 490 | Py_DECREF(v); 491 | } 492 | break; 493 | } 494 | 495 | // TODO(dreiss): Consider breaking this out as a function 496 | // the way we did for decode_struct. 497 | case T_STRUCT: { 498 | StructTypeArgs parsedargs; 499 | Py_ssize_t nspec; 500 | Py_ssize_t i; 501 | 502 | if (!parse_struct_args(&parsedargs, typeargs)) { 503 | return false; 504 | } 505 | 506 | nspec = PyTuple_Size(parsedargs.spec); 507 | 508 | if (nspec == -1) { 509 | return false; 510 | } 511 | 512 | for (i = 0; i < nspec; i++) { 513 | StructItemSpec parsedspec; 514 | PyObject* spec_tuple; 515 | PyObject* instval = NULL; 516 | 517 | spec_tuple = PyTuple_GET_ITEM(parsedargs.spec, i); 518 | if (spec_tuple == Py_None) { 519 | continue; 520 | } 521 | 522 | if (!parse_struct_item_spec (&parsedspec, spec_tuple)) { 523 | return false; 524 | } 525 | 526 | instval = PyObject_GetAttr(value, parsedspec.attrname); 527 | 528 | if (!instval) { 529 | return false; 530 | } 531 | 532 | if (instval == Py_None) { 533 | Py_DECREF(instval); 534 | continue; 535 | } 536 | 537 | writeByte(output, (int8_t) parsedspec.type); 538 | writeI16(output, parsedspec.tag); 539 | 540 | if (!output_val(output, instval, parsedspec.type, parsedspec.typeargs)) { 541 | Py_DECREF(instval); 542 | return false; 543 | } 544 | 545 | Py_DECREF(instval); 546 | } 547 | 548 | writeByte(output, (int8_t)T_STOP); 549 | break; 550 | } 551 | 552 | case T_STOP: 553 | case T_VOID: 554 | case T_UTF16: 555 | case T_UTF8: 556 | case T_U64: 557 | default: 558 | PyErr_SetString(PyExc_TypeError, "Unexpected TType"); 559 | return false; 560 | 561 | } 562 | 563 | return true; 564 | } 565 | 566 | 567 | /* --- TOP-LEVEL WRAPPER FOR OUTPUT -- */ 568 | 569 | static PyObject * 570 | encode_binary(PyObject *self, PyObject *args) { 571 | PyObject* enc_obj; 572 | PyObject* type_args; 573 | PyObject* buf; 574 | PyObject* ret = NULL; 575 | 576 | if (!PyArg_ParseTuple(args, "OO", &enc_obj, &type_args)) { 577 | return NULL; 578 | } 579 | 580 | buf = PycStringIO->NewOutput(INIT_OUTBUF_SIZE); 581 | if (output_val(buf, enc_obj, T_STRUCT, type_args)) { 582 | ret = PycStringIO->cgetvalue(buf); 583 | } 584 | 585 | Py_DECREF(buf); 586 | return ret; 587 | } 588 | 589 | /* ====== END WRITING FUNCTIONS ====== */ 590 | 591 | 592 | /* ====== BEGIN READING FUNCTIONS ====== */ 593 | 594 | /* --- LOW-LEVEL READING FUNCTIONS --- */ 595 | 596 | static void 597 | free_decodebuf(DecodeBuffer* d) { 598 | Py_XDECREF(d->stringiobuf); 599 | Py_XDECREF(d->refill_callable); 600 | } 601 | 602 | static bool 603 | decode_buffer_from_obj(DecodeBuffer* dest, PyObject* obj) { 604 | dest->stringiobuf = PyObject_GetAttr(obj, INTERN_STRING(cstringio_buf)); 605 | if (!dest->stringiobuf) { 606 | return false; 607 | } 608 | 609 | if (!PycStringIO_InputCheck(dest->stringiobuf)) { 610 | free_decodebuf(dest); 611 | PyErr_SetString(PyExc_TypeError, "expecting stringio input"); 612 | return false; 613 | } 614 | 615 | dest->refill_callable = PyObject_GetAttr(obj, INTERN_STRING(cstringio_refill)); 616 | 617 | if(!dest->refill_callable) { 618 | free_decodebuf(dest); 619 | return false; 620 | } 621 | 622 | if (!PyCallable_Check(dest->refill_callable)) { 623 | free_decodebuf(dest); 624 | PyErr_SetString(PyExc_TypeError, "expecting callable"); 625 | return false; 626 | } 627 | 628 | return true; 629 | } 630 | 631 | static bool readBytes(DecodeBuffer* input, char** output, int len) { 632 | int read; 633 | 634 | // TODO(dreiss): Don't fear the malloc. Think about taking a copy of 635 | // the partial read instead of forcing the transport 636 | // to prepend it to its buffer. 637 | 638 | read = PycStringIO->cread(input->stringiobuf, output, len); 639 | 640 | if (read == len) { 641 | return true; 642 | } else if (read == -1) { 643 | return false; 644 | } else { 645 | PyObject* newiobuf; 646 | 647 | // using building functions as this is a rare codepath 648 | newiobuf = PyObject_CallFunction( 649 | input->refill_callable, "s#i", *output, read, len, NULL); 650 | if (newiobuf == NULL) { 651 | return false; 652 | } 653 | 654 | // must do this *AFTER* the call so that we don't deref the io buffer 655 | Py_CLEAR(input->stringiobuf); 656 | input->stringiobuf = newiobuf; 657 | 658 | read = PycStringIO->cread(input->stringiobuf, output, len); 659 | 660 | if (read == len) { 661 | return true; 662 | } else if (read == -1) { 663 | return false; 664 | } else { 665 | // TODO(dreiss): This could be a valid code path for big binary blobs. 666 | PyErr_SetString(PyExc_TypeError, 667 | "refill claimed to have refilled the buffer, but didn't!!"); 668 | return false; 669 | } 670 | } 671 | } 672 | 673 | static int8_t readByte(DecodeBuffer* input) { 674 | char* buf; 675 | if (!readBytes(input, &buf, sizeof(int8_t))) { 676 | return -1; 677 | } 678 | 679 | return *(int8_t*) buf; 680 | } 681 | 682 | static int16_t readI16(DecodeBuffer* input) { 683 | char* buf; 684 | if (!readBytes(input, &buf, sizeof(int16_t))) { 685 | return -1; 686 | } 687 | 688 | return (int16_t) ntohs(*(int16_t*) buf); 689 | } 690 | 691 | static int32_t readI32(DecodeBuffer* input) { 692 | char* buf; 693 | if (!readBytes(input, &buf, sizeof(int32_t))) { 694 | return -1; 695 | } 696 | return (int32_t) ntohl(*(int32_t*) buf); 697 | } 698 | 699 | 700 | static int64_t readI64(DecodeBuffer* input) { 701 | char* buf; 702 | if (!readBytes(input, &buf, sizeof(int64_t))) { 703 | return -1; 704 | } 705 | 706 | return (int64_t) ntohll(*(int64_t*) buf); 707 | } 708 | 709 | static double readDouble(DecodeBuffer* input) { 710 | union { 711 | int64_t f; 712 | double t; 713 | } transfer; 714 | 715 | transfer.f = readI64(input); 716 | if (transfer.f == -1) { 717 | return -1; 718 | } 719 | return transfer.t; 720 | } 721 | 722 | static bool 723 | checkTypeByte(DecodeBuffer* input, TType expected) { 724 | TType got = readByte(input); 725 | if (INT_CONV_ERROR_OCCURRED(got)) { 726 | return false; 727 | } 728 | 729 | if (expected != got) { 730 | PyErr_SetString(PyExc_TypeError, "got wrong ttype while reading field"); 731 | return false; 732 | } 733 | return true; 734 | } 735 | 736 | static bool 737 | skip(DecodeBuffer* input, TType type) { 738 | #define SKIPBYTES(n) \ 739 | do { \ 740 | if (!readBytes(input, &dummy_buf, (n))) { \ 741 | return false; \ 742 | } \ 743 | } while(0) 744 | 745 | char* dummy_buf; 746 | 747 | switch (type) { 748 | 749 | case T_BOOL: 750 | case T_I08: SKIPBYTES(1); break; 751 | case T_I16: SKIPBYTES(2); break; 752 | case T_I32: SKIPBYTES(4); break; 753 | case T_I64: 754 | case T_DOUBLE: SKIPBYTES(8); break; 755 | 756 | case T_STRING: { 757 | // TODO(dreiss): Find out if these check_ssize_t32s are really necessary. 758 | int len = readI32(input); 759 | if (!check_ssize_t_32(len)) { 760 | return false; 761 | } 762 | SKIPBYTES(len); 763 | break; 764 | } 765 | 766 | case T_LIST: 767 | case T_SET: { 768 | TType etype; 769 | int len, i; 770 | 771 | etype = readByte(input); 772 | if (etype == -1) { 773 | return false; 774 | } 775 | 776 | len = readI32(input); 777 | if (!check_ssize_t_32(len)) { 778 | return false; 779 | } 780 | 781 | for (i = 0; i < len; i++) { 782 | if (!skip(input, etype)) { 783 | return false; 784 | } 785 | } 786 | break; 787 | } 788 | 789 | case T_MAP: { 790 | TType ktype, vtype; 791 | int len, i; 792 | 793 | ktype = readByte(input); 794 | if (ktype == -1) { 795 | return false; 796 | } 797 | 798 | vtype = readByte(input); 799 | if (vtype == -1) { 800 | return false; 801 | } 802 | 803 | len = readI32(input); 804 | if (!check_ssize_t_32(len)) { 805 | return false; 806 | } 807 | 808 | for (i = 0; i < len; i++) { 809 | if (!(skip(input, ktype) && skip(input, vtype))) { 810 | return false; 811 | } 812 | } 813 | break; 814 | } 815 | 816 | case T_STRUCT: { 817 | while (true) { 818 | TType type; 819 | 820 | type = readByte(input); 821 | if (type == -1) { 822 | return false; 823 | } 824 | 825 | if (type == T_STOP) 826 | break; 827 | 828 | SKIPBYTES(2); // tag 829 | if (!skip(input, type)) { 830 | return false; 831 | } 832 | } 833 | break; 834 | } 835 | 836 | case T_STOP: 837 | case T_VOID: 838 | case T_UTF16: 839 | case T_UTF8: 840 | case T_U64: 841 | default: 842 | PyErr_SetString(PyExc_TypeError, "Unexpected TType"); 843 | return false; 844 | 845 | } 846 | 847 | return true; 848 | 849 | #undef SKIPBYTES 850 | } 851 | 852 | 853 | /* --- HELPER FUNCTION FOR DECODE_VAL --- */ 854 | 855 | static PyObject* 856 | decode_val(DecodeBuffer* input, TType type, PyObject* typeargs); 857 | 858 | static bool 859 | decode_struct(DecodeBuffer* input, PyObject* output, PyObject* spec_seq) { 860 | int spec_seq_len = PyTuple_Size(spec_seq); 861 | if (spec_seq_len == -1) { 862 | return false; 863 | } 864 | 865 | while (true) { 866 | TType type; 867 | int16_t tag; 868 | PyObject* item_spec; 869 | PyObject* fieldval = NULL; 870 | StructItemSpec parsedspec; 871 | 872 | type = readByte(input); 873 | if (type == -1) { 874 | return false; 875 | } 876 | if (type == T_STOP) { 877 | break; 878 | } 879 | tag = readI16(input); 880 | if (INT_CONV_ERROR_OCCURRED(tag)) { 881 | return false; 882 | } 883 | if (tag >= 0 && tag < spec_seq_len) { 884 | item_spec = PyTuple_GET_ITEM(spec_seq, tag); 885 | } else { 886 | item_spec = Py_None; 887 | } 888 | 889 | if (item_spec == Py_None) { 890 | if (!skip(input, type)) { 891 | return false; 892 | } else { 893 | continue; 894 | } 895 | } 896 | 897 | if (!parse_struct_item_spec(&parsedspec, item_spec)) { 898 | return false; 899 | } 900 | if (parsedspec.type != type) { 901 | if (!skip(input, type)) { 902 | PyErr_SetString(PyExc_TypeError, "struct field had wrong type while reading and can't be skipped"); 903 | return false; 904 | } else { 905 | continue; 906 | } 907 | } 908 | 909 | fieldval = decode_val(input, parsedspec.type, parsedspec.typeargs); 910 | if (fieldval == NULL) { 911 | return false; 912 | } 913 | 914 | if (PyObject_SetAttr(output, parsedspec.attrname, fieldval) == -1) { 915 | Py_DECREF(fieldval); 916 | return false; 917 | } 918 | Py_DECREF(fieldval); 919 | } 920 | return true; 921 | } 922 | 923 | 924 | /* --- MAIN RECURSIVE INPUT FUCNTION --- */ 925 | 926 | // Returns a new reference. 927 | static PyObject* 928 | decode_val(DecodeBuffer* input, TType type, PyObject* typeargs) { 929 | switch (type) { 930 | 931 | case T_BOOL: { 932 | int8_t v = readByte(input); 933 | if (INT_CONV_ERROR_OCCURRED(v)) { 934 | return NULL; 935 | } 936 | 937 | switch (v) { 938 | case 0: Py_RETURN_FALSE; 939 | case 1: Py_RETURN_TRUE; 940 | // Don't laugh. This is a potentially serious issue. 941 | default: PyErr_SetString(PyExc_TypeError, "boolean out of range"); return NULL; 942 | } 943 | break; 944 | } 945 | case T_I08: { 946 | int8_t v = readByte(input); 947 | if (INT_CONV_ERROR_OCCURRED(v)) { 948 | return NULL; 949 | } 950 | 951 | return PyInt_FromLong(v); 952 | } 953 | case T_I16: { 954 | int16_t v = readI16(input); 955 | if (INT_CONV_ERROR_OCCURRED(v)) { 956 | return NULL; 957 | } 958 | return PyInt_FromLong(v); 959 | } 960 | case T_I32: { 961 | int32_t v = readI32(input); 962 | if (INT_CONV_ERROR_OCCURRED(v)) { 963 | return NULL; 964 | } 965 | return PyInt_FromLong(v); 966 | } 967 | 968 | case T_I64: { 969 | int64_t v = readI64(input); 970 | if (INT_CONV_ERROR_OCCURRED(v)) { 971 | return NULL; 972 | } 973 | // TODO(dreiss): Find out if we can take this fastpath always when 974 | // sizeof(long) == sizeof(long long). 975 | if (CHECK_RANGE(v, LONG_MIN, LONG_MAX)) { 976 | return PyInt_FromLong((long) v); 977 | } 978 | 979 | return PyLong_FromLongLong(v); 980 | } 981 | 982 | case T_DOUBLE: { 983 | double v = readDouble(input); 984 | if (v == -1.0 && PyErr_Occurred()) { 985 | return false; 986 | } 987 | return PyFloat_FromDouble(v); 988 | } 989 | 990 | case T_STRING: { 991 | Py_ssize_t len = readI32(input); 992 | char* buf; 993 | if (!readBytes(input, &buf, len)) { 994 | return NULL; 995 | } 996 | 997 | return PyString_FromStringAndSize(buf, len); 998 | } 999 | 1000 | case T_LIST: 1001 | case T_SET: { 1002 | SetListTypeArgs parsedargs; 1003 | int32_t len; 1004 | PyObject* ret = NULL; 1005 | int i; 1006 | 1007 | if (!parse_set_list_args(&parsedargs, typeargs)) { 1008 | return NULL; 1009 | } 1010 | 1011 | if (!checkTypeByte(input, parsedargs.element_type)) { 1012 | return NULL; 1013 | } 1014 | 1015 | len = readI32(input); 1016 | if (!check_ssize_t_32(len)) { 1017 | return NULL; 1018 | } 1019 | 1020 | ret = PyList_New(len); 1021 | if (!ret) { 1022 | return NULL; 1023 | } 1024 | 1025 | for (i = 0; i < len; i++) { 1026 | PyObject* item = decode_val(input, parsedargs.element_type, parsedargs.typeargs); 1027 | if (!item) { 1028 | Py_DECREF(ret); 1029 | return NULL; 1030 | } 1031 | PyList_SET_ITEM(ret, i, item); 1032 | } 1033 | 1034 | // TODO(dreiss): Consider biting the bullet and making two separate cases 1035 | // for list and set, avoiding this post facto conversion. 1036 | if (type == T_SET) { 1037 | PyObject* setret; 1038 | #if (PY_VERSION_HEX < 0x02050000) 1039 | // hack needed for older versions 1040 | setret = PyObject_CallFunctionObjArgs((PyObject*)&PySet_Type, ret, NULL); 1041 | #else 1042 | // official version 1043 | setret = PySet_New(ret); 1044 | #endif 1045 | Py_DECREF(ret); 1046 | return setret; 1047 | } 1048 | return ret; 1049 | } 1050 | 1051 | case T_MAP: { 1052 | int32_t len; 1053 | int i; 1054 | MapTypeArgs parsedargs; 1055 | PyObject* ret = NULL; 1056 | 1057 | if (!parse_map_args(&parsedargs, typeargs)) { 1058 | return NULL; 1059 | } 1060 | 1061 | if (!checkTypeByte(input, parsedargs.ktag)) { 1062 | return NULL; 1063 | } 1064 | if (!checkTypeByte(input, parsedargs.vtag)) { 1065 | return NULL; 1066 | } 1067 | 1068 | len = readI32(input); 1069 | if (!check_ssize_t_32(len)) { 1070 | return false; 1071 | } 1072 | 1073 | ret = PyDict_New(); 1074 | if (!ret) { 1075 | goto error; 1076 | } 1077 | 1078 | for (i = 0; i < len; i++) { 1079 | PyObject* k = NULL; 1080 | PyObject* v = NULL; 1081 | k = decode_val(input, parsedargs.ktag, parsedargs.ktypeargs); 1082 | if (k == NULL) { 1083 | goto loop_error; 1084 | } 1085 | v = decode_val(input, parsedargs.vtag, parsedargs.vtypeargs); 1086 | if (v == NULL) { 1087 | goto loop_error; 1088 | } 1089 | if (PyDict_SetItem(ret, k, v) == -1) { 1090 | goto loop_error; 1091 | } 1092 | 1093 | Py_DECREF(k); 1094 | Py_DECREF(v); 1095 | continue; 1096 | 1097 | // Yuck! Destructors, anyone? 1098 | loop_error: 1099 | Py_XDECREF(k); 1100 | Py_XDECREF(v); 1101 | goto error; 1102 | } 1103 | 1104 | return ret; 1105 | 1106 | error: 1107 | Py_XDECREF(ret); 1108 | return NULL; 1109 | } 1110 | 1111 | case T_STRUCT: { 1112 | StructTypeArgs parsedargs; 1113 | if (!parse_struct_args(&parsedargs, typeargs)) { 1114 | return NULL; 1115 | } 1116 | 1117 | PyObject* ret = PyObject_CallObject(parsedargs.klass, NULL); 1118 | if (!ret) { 1119 | return NULL; 1120 | } 1121 | 1122 | if (!decode_struct(input, ret, parsedargs.spec)) { 1123 | Py_DECREF(ret); 1124 | return NULL; 1125 | } 1126 | 1127 | return ret; 1128 | } 1129 | 1130 | case T_STOP: 1131 | case T_VOID: 1132 | case T_UTF16: 1133 | case T_UTF8: 1134 | case T_U64: 1135 | default: 1136 | PyErr_SetString(PyExc_TypeError, "Unexpected TType"); 1137 | return NULL; 1138 | } 1139 | } 1140 | 1141 | 1142 | /* --- TOP-LEVEL WRAPPER FOR INPUT -- */ 1143 | 1144 | static PyObject* 1145 | decode_binary(PyObject *self, PyObject *args) { 1146 | PyObject* output_obj = NULL; 1147 | PyObject* transport = NULL; 1148 | PyObject* typeargs = NULL; 1149 | StructTypeArgs parsedargs; 1150 | DecodeBuffer input = {}; 1151 | 1152 | if (!PyArg_ParseTuple(args, "OOO", &output_obj, &transport, &typeargs)) { 1153 | return NULL; 1154 | } 1155 | 1156 | if (!parse_struct_args(&parsedargs, typeargs)) { 1157 | return NULL; 1158 | } 1159 | 1160 | if (!decode_buffer_from_obj(&input, transport)) { 1161 | return NULL; 1162 | } 1163 | 1164 | if (!decode_struct(&input, output_obj, parsedargs.spec)) { 1165 | free_decodebuf(&input); 1166 | return NULL; 1167 | } 1168 | 1169 | free_decodebuf(&input); 1170 | 1171 | Py_RETURN_NONE; 1172 | } 1173 | 1174 | /* ====== END READING FUNCTIONS ====== */ 1175 | 1176 | 1177 | /* -- PYTHON MODULE SETUP STUFF --- */ 1178 | 1179 | static PyMethodDef ThriftFastBinaryMethods[] = { 1180 | 1181 | {"encode_binary", encode_binary, METH_VARARGS, ""}, 1182 | {"decode_binary", decode_binary, METH_VARARGS, ""}, 1183 | 1184 | {NULL, NULL, 0, NULL} /* Sentinel */ 1185 | }; 1186 | 1187 | PyMODINIT_FUNC 1188 | initfastbinary(void) { 1189 | #define INIT_INTERN_STRING(value) \ 1190 | do { \ 1191 | INTERN_STRING(value) = PyString_InternFromString(#value); \ 1192 | if(!INTERN_STRING(value)) return; \ 1193 | } while(0) 1194 | 1195 | INIT_INTERN_STRING(cstringio_buf); 1196 | INIT_INTERN_STRING(cstringio_refill); 1197 | #undef INIT_INTERN_STRING 1198 | 1199 | PycString_IMPORT; 1200 | if (PycStringIO == NULL) return; 1201 | 1202 | (void) Py_InitModule("thrift.protocol.fastbinary", ThriftFastBinaryMethods); 1203 | } 1204 | --------------------------------------------------------------------------------