浏览代码

Hue - Upgrade Apache Thrift to 0.16.0, Thrift SASL 0.4.3, due to high CVEs (#3057)

Prakash Ranade 3 年之前
父节点
当前提交
b629542f40
共有 57 个文件被更改,包括 591 次插入180 次删除
  1. 0 16
      desktop/core/ext-py/thrift-0.13.0/LICENSE
  2. 0 5
      desktop/core/ext-py/thrift-0.13.0/MANIFEST.in
  3. 0 25
      desktop/core/ext-py/thrift-0.13.0/README.md
  4. 1 0
      desktop/core/ext-py/thrift-0.16.0/MANIFEST.in
  5. 26 18
      desktop/core/ext-py/thrift-0.16.0/PKG-INFO
  6. 35 0
      desktop/core/ext-py/thrift-0.16.0/README.md
  7. 3 0
      desktop/core/ext-py/thrift-0.16.0/setup.cfg
  8. 20 23
      desktop/core/ext-py/thrift-0.16.0/setup.py
  9. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/TMultiplexedProcessor.py
  10. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/TRecursive.py
  11. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/TSCons.py
  12. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/TSerialization.py
  13. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/TTornado.py
  14. 1 12
      desktop/core/ext-py/thrift-0.16.0/src/Thrift.py
  15. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/__init__.py
  16. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/compat.py
  17. 1 0
      desktop/core/ext-py/thrift-0.16.0/src/ext/binary.cpp
  18. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/ext/binary.h
  19. 1 0
      desktop/core/ext-py/thrift-0.16.0/src/ext/compact.cpp
  20. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/ext/compact.h
  21. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/ext/endian.h
  22. 22 22
      desktop/core/ext-py/thrift-0.16.0/src/ext/module.cpp
  23. 1 1
      desktop/core/ext-py/thrift-0.16.0/src/ext/protocol.h
  24. 42 42
      desktop/core/ext-py/thrift-0.16.0/src/ext/protocol.tcc
  25. 1 1
      desktop/core/ext-py/thrift-0.16.0/src/ext/types.cpp
  26. 2 2
      desktop/core/ext-py/thrift-0.16.0/src/ext/types.h
  27. 4 0
      desktop/core/ext-py/thrift-0.16.0/src/protocol/TBase.py
  28. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/protocol/TBinaryProtocol.py
  29. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/protocol/TCompactProtocol.py
  30. 12 5
      desktop/core/ext-py/thrift-0.16.0/src/protocol/THeaderProtocol.py
  31. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/protocol/TJSONProtocol.py
  32. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/protocol/TMultiplexedProtocol.py
  33. 8 2
      desktop/core/ext-py/thrift-0.16.0/src/protocol/TProtocol.py
  34. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/protocol/TProtocolDecorator.py
  35. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/protocol/__init__.py
  36. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/server/THttpServer.py
  37. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/server/TNonblockingServer.py
  38. 5 0
      desktop/core/ext-py/thrift-0.16.0/src/server/TProcessPoolServer.py
  39. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/server/TServer.py
  40. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/server/__init__.py
  41. 2 2
      desktop/core/ext-py/thrift-0.16.0/src/transport/THeaderTransport.py
  42. 4 0
      desktop/core/ext-py/thrift-0.16.0/src/transport/THttpClient.py
  43. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/transport/TSSLSocket.py
  44. 26 2
      desktop/core/ext-py/thrift-0.16.0/src/transport/TSocket.py
  45. 3 0
      desktop/core/ext-py/thrift-0.16.0/src/transport/TTransport.py
  46. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/transport/TTwisted.py
  47. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/transport/TZlibTransport.py
  48. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/transport/__init__.py
  49. 0 0
      desktop/core/ext-py/thrift-0.16.0/src/transport/sslcompat.py
  50. 57 0
      desktop/core/ext-py/thrift-0.16.0/test/test_socket.py
  51. 0 0
      desktop/core/ext-py/thrift-0.16.0/test/test_sslsocket.py
  52. 22 0
      desktop/core/ext-py/thrift_sasl-0.4.3/PKG-INFO
  53. 4 0
      desktop/core/ext-py/thrift_sasl-0.4.3/README.md
  54. 4 0
      desktop/core/ext-py/thrift_sasl-0.4.3/setup.cfg
  55. 52 0
      desktop/core/ext-py/thrift_sasl-0.4.3/setup.py
  56. 230 0
      desktop/core/ext-py/thrift_sasl-0.4.3/thrift_sasl/__init__.py
  57. 2 2
      desktop/core/requirements.txt

+ 0 - 16
desktop/core/ext-py/thrift-0.13.0/LICENSE

@@ -1,16 +0,0 @@
-Licensed to the Apache Software Foundation (ASF) under one
-or more contributor license agreements. See the NOTICE file
-distributed with this work for additional information
-regarding copyright ownership. The ASF licenses this file
-to you under the Apache License, Version 2.0 (the
-"License"); you may not use this file except in compliance
-with the License. You may obtain a copy of the License at
-
-    http://www.apache.org/licenses/LICENSE-2.0
-
-Unless required by applicable law or agreed to in writing,
-software distributed under the License is distributed on an
-"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-KIND, either express or implied. See the License for the
-specific language governing permissions and limitations
-under the License.

+ 0 - 5
desktop/core/ext-py/thrift-0.13.0/MANIFEST.in

@@ -1,5 +0,0 @@
-include LICENSE
-include src/ext/*
-global-exclude __pycache__
-global-exclude *.py[co]
-

+ 0 - 25
desktop/core/ext-py/thrift-0.13.0/README.md

@@ -1,25 +0,0 @@
-Thrift Python Software Library
-
-Thrift is a lightweight, language-independent software stack for
-point-to-point RPC implementation.
-Thrift provides clean abstractions and implementations for data transport,
-data serialization, and application level processing. The code generation
-system takes a simple definition language as input and generates code
-across programming languages that uses the abstracted stack to build
-interoperable RPC clients and servers.
-
-Thrift is provided as a set of Python packages. The top level package is
-thrift, and there are subpackages for the protocol, transport, and server
-code. Each package contains modules using standard Thrift naming conventions
-(i.e. TProtocol, TTransport) and implementations in corresponding modules
-(i.e. TSocket).  There is also a subpackage reflection, which contains
-the generated code for the reflection structures.
-
-The Python libraries can be installed manually using the provided setup.py
-file, or automatically using the install hook provided via autoconf/automake.
-To use the latter, become superuser and do make install.
-
-For more information:
-
-https://thrift.apache.org/
-https://www.github.com/apache/thrift/

+ 1 - 0
desktop/core/ext-py/thrift-0.16.0/MANIFEST.in

@@ -0,0 +1 @@
+include src/ext/*

+ 26 - 18
desktop/core/ext-py/thrift-0.13.0/PKG-INFO → desktop/core/ext-py/thrift-0.16.0/PKG-INFO

@@ -1,20 +1,35 @@
 Metadata-Version: 2.1
 Name: thrift
-Version: 0.13.0
+Version: 0.16.0
 Summary: Python bindings for the Apache Thrift RPC system
-Home-page: https://thrift.apache.org
+Home-page: http://thrift.apache.org
 Author: Apache Thrift Developers
 Author-email: dev@thrift.apache.org
-License: Apache Software License, Version 2
+License: Apache License 2.0
 Description: Thrift Python Software Library
         
-        Thrift is a lightweight, language-independent software stack for
-        point-to-point RPC implementation.
-        Thrift provides clean abstractions and implementations for data transport,
-        data serialization, and application level processing. The code generation
-        system takes a simple definition language as input and generates code
-        across programming languages that uses the abstracted stack to build
-        interoperable RPC clients and servers.
+        License
+        =======
+        
+        Licensed to the Apache Software Foundation (ASF) under one
+        or more contributor license agreements. See the NOTICE file
+        distributed with this work for additional information
+        regarding copyright ownership. The ASF licenses this file
+        to you under the Apache License, Version 2.0 (the
+        "License"); you may not use this file except in compliance
+        with the License. You may obtain a copy of the License at
+        
+          http://www.apache.org/licenses/LICENSE-2.0
+        
+        Unless required by applicable law or agreed to in writing,
+        software distributed under the License is distributed on an
+        "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+        KIND, either express or implied. See the License for the
+        specific language governing permissions and limitations
+        under the License.
+        
+        Using Thrift with Python
+        ========================
         
         Thrift is provided as a set of Python packages. The top level package is
         thrift, and there are subpackages for the protocol, transport, and server
@@ -26,24 +41,17 @@ Description: Thrift Python Software Library
         The Python libraries can be installed manually using the provided setup.py
         file, or automatically using the install hook provided via autoconf/automake.
         To use the latter, become superuser and do make install.
-        
-        For more information:
-        
-        https://thrift.apache.org/
-        https://www.github.com/apache/thrift/
 Platform: UNKNOWN
 Classifier: Development Status :: 5 - Production/Stable
 Classifier: Environment :: Console
 Classifier: Intended Audience :: Developers
-Classifier: License :: OSI Approved :: Apache Software License
 Classifier: Programming Language :: Python
 Classifier: Programming Language :: Python :: 2
 Classifier: Programming Language :: Python :: 3
-Classifier: Topic :: Software Development :: Code Generators
 Classifier: Topic :: Software Development :: Libraries
 Classifier: Topic :: System :: Networking
 Description-Content-Type: text/markdown
+Provides-Extra: all
 Provides-Extra: ssl
 Provides-Extra: tornado
 Provides-Extra: twisted
-Provides-Extra: all

+ 35 - 0
desktop/core/ext-py/thrift-0.16.0/README.md

@@ -0,0 +1,35 @@
+Thrift Python Software Library
+
+License
+=======
+
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you under the Apache License, Version 2.0 (the
+"License"); you may not use this file except in compliance
+with the License. You may obtain a copy of the License at
+
+  http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing,
+software distributed under the License is distributed on an
+"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+KIND, either express or implied. See the License for the
+specific language governing permissions and limitations
+under the License.
+
+Using Thrift with Python
+========================
+
+Thrift is provided as a set of Python packages. The top level package is
+thrift, and there are subpackages for the protocol, transport, and server
+code. Each package contains modules using standard Thrift naming conventions
+(i.e. TProtocol, TTransport) and implementations in corresponding modules
+(i.e. TSocket).  There is also a subpackage reflection, which contains
+the generated code for the reflection structures.
+
+The Python libraries can be installed manually using the provided setup.py
+file, or automatically using the install hook provided via autoconf/automake.
+To use the latter, become superuser and do make install.

+ 3 - 0
desktop/core/ext-py/thrift-0.13.0/setup.cfg → desktop/core/ext-py/thrift-0.16.0/setup.cfg

@@ -1,6 +1,9 @@
 [install]
 optimize = 1
 
+[metadata]
+description_file = README.md
+
 [flake8]
 max-line-length = 100
 

+ 20 - 23
desktop/core/ext-py/thrift-0.13.0/setup.py → desktop/core/ext-py/thrift-0.16.0/setup.py

@@ -18,9 +18,8 @@
 # specific language governing permissions and limitations
 # under the License.
 #
-import os
-import sys
 
+import sys
 try:
     from setuptools import setup, Extension
 except Exception:
@@ -30,6 +29,7 @@ from distutils.command.build_ext import build_ext
 from distutils.errors import CCompilerError, DistutilsExecError, DistutilsPlatformError
 
 # Fix to build sdist under vagrant
+import os
 if 'vagrant' in str(os.environ):
     try:
         del os.link
@@ -48,20 +48,6 @@ class BuildFailed(Exception):
     pass
 
 
-def read_file(path):
-    """
-    Return the contents of a file
-
-    Arguments:
-      - path: path to the file
-
-    Returns:
-      - contents of the file
-    """
-    with open(path, 'r') as desc_file:
-        return desc_file.read().rstrip()
-
-
 class ve_build_ext(build_ext):
     def run(self):
         try:
@@ -76,11 +62,26 @@ class ve_build_ext(build_ext):
             raise BuildFailed()
 
 
+def read_file(path):
+    """
+    Return the contents of a file
+
+    Arguments:
+      - path: path to the file
+
+    Returns:
+      - contents of the file
+    """
+    with open(path, "r") as desc_file:
+        return desc_file.read().rstrip()
+
+
 def run_setup(with_binary):
     if with_binary:
         extensions = dict(
             ext_modules=[
                 Extension('thrift.protocol.fastbinary',
+                          extra_compile_args=['-std=c++11'],
                           sources=[
                               'src/ext/module.cpp',
                               'src/ext/types.cpp',
@@ -104,17 +105,15 @@ def run_setup(with_binary):
     twisted_deps = ['twisted']
 
     setup(name='thrift',
-          version='0.13.0',
+          version='0.16.0',
           description='Python bindings for the Apache Thrift RPC system',
-          # causes problems publishing
-          # license=read_file("LICENSE"),
           long_description=read_file("README.md"),
           long_description_content_type="text/markdown",
           author='Apache Thrift Developers',
           author_email='dev@thrift.apache.org',
-          url='https://thrift.apache.org',
+          url='http://thrift.apache.org',
+          license='Apache License 2.0',
           install_requires=['six>=1.7.2'],
-          license='Apache Software License, Version 2',
           extras_require={
               'ssl': ssl_deps,
               'tornado': tornado_deps,
@@ -132,11 +131,9 @@ def run_setup(with_binary):
               'Development Status :: 5 - Production/Stable',
               'Environment :: Console',
               'Intended Audience :: Developers',
-              'License :: OSI Approved :: Apache Software License',
               'Programming Language :: Python',
               'Programming Language :: Python :: 2',
               'Programming Language :: Python :: 3',
-              'Topic :: Software Development :: Code Generators',
               'Topic :: Software Development :: Libraries',
               'Topic :: System :: Networking'
           ],

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/TMultiplexedProcessor.py → desktop/core/ext-py/thrift-0.16.0/src/TMultiplexedProcessor.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/TRecursive.py → desktop/core/ext-py/thrift-0.16.0/src/TRecursive.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/TSCons.py → desktop/core/ext-py/thrift-0.16.0/src/TSCons.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/TSerialization.py → desktop/core/ext-py/thrift-0.16.0/src/TSerialization.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/TTornado.py → desktop/core/ext-py/thrift-0.16.0/src/TTornado.py


+ 1 - 12
desktop/core/ext-py/thrift-0.13.0/src/Thrift.py → desktop/core/ext-py/thrift-0.16.0/src/Thrift.py

@@ -17,8 +17,6 @@
 # under the License.
 #
 
-import sys
-
 
 class TType(object):
     STOP = 0
@@ -90,18 +88,9 @@ class TProcessor(object):
 class TException(Exception):
     """Base class for all thrift exceptions."""
 
-    # BaseException.message is deprecated in Python v[2.6,3.0)
-    if (2, 6, 0) <= sys.version_info < (3, 0):
-        def _get_message(self):
-            return self._message
-
-        def _set_message(self, message):
-            self._message = message
-        message = property(_get_message, _set_message)
-
     def __init__(self, message=None):
         Exception.__init__(self, message)
-        self.message = message
+        super(TException, self).__setattr__("message", message)
 
 
 class TApplicationException(TException):

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/__init__.py → desktop/core/ext-py/thrift-0.16.0/src/__init__.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/compat.py → desktop/core/ext-py/thrift-0.16.0/src/compat.py


+ 1 - 0
desktop/core/ext-py/thrift-0.13.0/src/ext/binary.cpp → desktop/core/ext-py/thrift-0.16.0/src/ext/binary.cpp

@@ -17,6 +17,7 @@
  * under the License.
  */
 
+#define PY_SSIZE_T_CLEAN
 #include "ext/binary.h"
 namespace apache {
 namespace thrift {

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/ext/binary.h → desktop/core/ext-py/thrift-0.16.0/src/ext/binary.h


+ 1 - 0
desktop/core/ext-py/thrift-0.13.0/src/ext/compact.cpp → desktop/core/ext-py/thrift-0.16.0/src/ext/compact.cpp

@@ -17,6 +17,7 @@
  * under the License.
  */
 
+#define PY_SSIZE_T_CLEAN
 #include "ext/compact.h"
 
 namespace apache {

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/ext/compact.h → desktop/core/ext-py/thrift-0.16.0/src/ext/compact.h


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/ext/endian.h → desktop/core/ext-py/thrift-0.16.0/src/ext/endian.h


+ 22 - 22
desktop/core/ext-py/thrift-0.13.0/src/ext/module.cpp → desktop/core/ext-py/thrift-0.16.0/src/ext/module.cpp

@@ -48,20 +48,20 @@ namespace py {
 template <typename T>
 static PyObject* encode_impl(PyObject* args) {
   if (!args)
-    return NULL;
+    return nullptr;
 
-  PyObject* enc_obj = NULL;
-  PyObject* type_args = NULL;
+  PyObject* enc_obj = nullptr;
+  PyObject* type_args = nullptr;
   if (!PyArg_ParseTuple(args, "OO", &enc_obj, &type_args)) {
-    return NULL;
+    return nullptr;
   }
   if (!enc_obj || !type_args) {
-    return NULL;
+    return nullptr;
   }
 
   T protocol;
   if (!protocol.prepareEncodeBuffer() || !protocol.encodeValue(enc_obj, T_STRUCT, type_args)) {
-    return NULL;
+    return nullptr;
   }
 
   return protocol.getEncodedValue();
@@ -79,11 +79,11 @@ static inline long as_long_then_delete(PyObject* value, long default_value) {
 
 template <typename T>
 static PyObject* decode_impl(PyObject* args) {
-  PyObject* output_obj = NULL;
-  PyObject* oprot = NULL;
-  PyObject* typeargs = NULL;
+  PyObject* output_obj = nullptr;
+  PyObject* oprot = nullptr;
+  PyObject* typeargs = nullptr;
   if (!PyArg_ParseTuple(args, "OOO", &output_obj, &oprot, &typeargs)) {
-    return NULL;
+    return nullptr;
   }
 
   T protocol;
@@ -96,16 +96,16 @@ static PyObject* decode_impl(PyObject* args) {
                           default_limit));
   ScopedPyObject transport(PyObject_GetAttr(oprot, INTERN_STRING(trans)));
   if (!transport) {
-    return NULL;
+    return nullptr;
   }
 
   StructTypeArgs parsedargs;
   if (!parse_struct_args(&parsedargs, typeargs)) {
-    return NULL;
+    return nullptr;
   }
 
   if (!protocol.prepareDecodeBufferFromTransport(transport.get())) {
-    return NULL;
+    return nullptr;
   }
 
   return protocol.readStruct(output_obj, parsedargs.klass, parsedargs.spec);
@@ -141,22 +141,22 @@ static PyMethodDef ThriftFastBinaryMethods[] = {
     {"decode_binary", decode_binary, METH_VARARGS, ""},
     {"encode_compact", encode_compact, METH_VARARGS, ""},
     {"decode_compact", decode_compact, METH_VARARGS, ""},
-    {NULL, NULL, 0, NULL} /* Sentinel */
+    {nullptr, nullptr, 0, nullptr} /* Sentinel */
 };
 
 #if PY_MAJOR_VERSION >= 3
 
 static struct PyModuleDef ThriftFastBinaryDef = {PyModuleDef_HEAD_INIT,
                                                  "thrift.protocol.fastbinary",
-                                                 NULL,
+                                                 nullptr,
                                                  0,
                                                  ThriftFastBinaryMethods,
-                                                 NULL,
-                                                 NULL,
-                                                 NULL,
-                                                 NULL};
+                                                 nullptr,
+                                                 nullptr,
+                                                 nullptr,
+                                                 nullptr};
 
-#define INITERROR return NULL;
+#define INITERROR return nullptr;
 
 PyObject* PyInit_fastbinary() {
 
@@ -167,7 +167,7 @@ PyObject* PyInit_fastbinary() {
 void initfastbinary() {
 
   PycString_IMPORT;
-  if (PycStringIO == NULL)
+  if (PycStringIO == nullptr)
     INITERROR
 
 #endif
@@ -193,7 +193,7 @@ void initfastbinary() {
 #else
       Py_InitModule("thrift.protocol.fastbinary", ThriftFastBinaryMethods);
 #endif
-  if (module == NULL)
+  if (module == nullptr)
     INITERROR;
 
 #if PY_MAJOR_VERSION >= 3

+ 1 - 1
desktop/core/ext-py/thrift-0.13.0/src/ext/protocol.h → desktop/core/ext-py/thrift-0.16.0/src/ext/protocol.h

@@ -35,7 +35,7 @@ public:
   ProtocolBase()
     : stringLimit_((std::numeric_limits<int32_t>::max)()),
       containerLimit_((std::numeric_limits<int32_t>::max)()),
-      output_(NULL) {}
+      output_(nullptr) {}
   inline virtual ~ProtocolBase();
 
   bool prepareDecodeBufferFromTransport(PyObject* trans);

+ 42 - 42
desktop/core/ext-py/thrift-0.13.0/src/ext/protocol.tcc → desktop/core/ext-py/thrift-0.16.0/src/ext/protocol.tcc

@@ -48,7 +48,7 @@ inline EncodeBuffer* new_encode_buffer(size_t size) {
     PycString_IMPORT;
   }
   if (!PycStringIO) {
-    return NULL;
+    return nullptr;
   }
   return PycStringIO->NewOutput(size);
 }
@@ -83,7 +83,7 @@ PyObject* ProtocolBase<Impl>::getEncodedValue() {
     PycString_IMPORT;
   }
   if (!PycStringIO) {
-    return NULL;
+    return nullptr;
   }
   return PycStringIO->cgetvalue(output_);
 }
@@ -174,7 +174,7 @@ inline bool ProtocolBase<Impl>::writeBuffer(char* data, size_t size) {
   if (output_->buf.capacity() < need) {
     try {
       output_->buf.reserve(need);
-    } catch (std::bad_alloc& ex) {
+    } catch (std::bad_alloc&) {
       PyErr_SetString(PyExc_MemoryError, "Failed to allocate write buffer");
       return false;
     }
@@ -277,7 +277,7 @@ bool ProtocolBase<Impl>::readBytes(char** output, int len) {
   } else {
     // using building functions as this is a rare codepath
     ScopedPyObject newiobuf(PyObject_CallFunction(input_.refill_callable.get(), refill_signature,
-                                                  *output, rlen, len, NULL));
+                                                  *output, rlen, len, nullptr));
     if (!newiobuf) {
       return false;
     }
@@ -332,7 +332,7 @@ bool ProtocolBase<Impl>::prepareDecodeBufferFromTransport(PyObject* trans) {
 template <typename Impl>
 bool ProtocolBase<Impl>::prepareEncodeBuffer() {
   output_ = detail::new_encode_buffer(INIT_OUTBUF_SIZE);
-  return output_ != NULL;
+  return output_ != nullptr;
 }
 
 template <typename Impl>
@@ -484,8 +484,8 @@ bool ProtocolBase<Impl>::encodeValue(PyObject* value, TType type, PyObject* type
       return false;
     }
     Py_ssize_t pos = 0;
-    PyObject* k = NULL;
-    PyObject* v = NULL;
+    PyObject* k = nullptr;
+    PyObject* v = nullptr;
     // TODO(bmaurer): should support any mapping, not just dicts
     while (PyDict_Next(value, &pos, &k, &v)) {
       if (!encodeValue(k, parsedargs.ktag, parsedargs.ktypeargs)
@@ -647,7 +647,7 @@ PyObject* ProtocolBase<Impl>::decodeValue(TType type, PyObject* typeargs) {
   case T_BOOL: {
     bool v = 0;
     if (!impl()->readBool(v)) {
-      return NULL;
+      return nullptr;
     }
     if (v) {
       Py_RETURN_TRUE;
@@ -658,21 +658,21 @@ PyObject* ProtocolBase<Impl>::decodeValue(TType type, PyObject* typeargs) {
   case T_I08: {
     int8_t v = 0;
     if (!impl()->readI8(v)) {
-      return NULL;
+      return nullptr;
     }
     return PyInt_FromLong(v);
   }
   case T_I16: {
     int16_t v = 0;
     if (!impl()->readI16(v)) {
-      return NULL;
+      return nullptr;
     }
     return PyInt_FromLong(v);
   }
   case T_I32: {
     int32_t v = 0;
     if (!impl()->readI32(v)) {
-      return NULL;
+      return nullptr;
     }
     return PyInt_FromLong(v);
   }
@@ -680,7 +680,7 @@ PyObject* ProtocolBase<Impl>::decodeValue(TType type, PyObject* typeargs) {
   case T_I64: {
     int64_t v = 0;
     if (!impl()->readI64(v)) {
-      return NULL;
+      return nullptr;
     }
     // TODO(dreiss): Find out if we can take this fastpath always when
     //               sizeof(long) == sizeof(long long).
@@ -693,19 +693,19 @@ PyObject* ProtocolBase<Impl>::decodeValue(TType type, PyObject* typeargs) {
   case T_DOUBLE: {
     double v = 0.0;
     if (!impl()->readDouble(v)) {
-      return NULL;
+      return nullptr;
     }
     return PyFloat_FromDouble(v);
   }
 
   case T_STRING: {
-    char* buf = NULL;
+    char* buf = nullptr;
     int len = impl()->readString(&buf);
     if (len < 0) {
-      return NULL;
+      return nullptr;
     }
     if (isUtf8(typeargs)) {
-      return PyUnicode_DecodeUTF8(buf, len, 0);
+      return PyUnicode_DecodeUTF8(buf, len, "replace");
     } else {
       return PyBytes_FromStringAndSize(buf, len);
     }
@@ -715,28 +715,28 @@ PyObject* ProtocolBase<Impl>::decodeValue(TType type, PyObject* typeargs) {
   case T_SET: {
     SetListTypeArgs parsedargs;
     if (!parse_set_list_args(&parsedargs, typeargs)) {
-      return NULL;
+      return nullptr;
     }
 
     TType etype = T_STOP;
     int32_t len = impl()->readListBegin(etype);
     if (len < 0) {
-      return NULL;
+      return nullptr;
     }
     if (len > 0 && !checkType(etype, parsedargs.element_type)) {
-      return NULL;
+      return nullptr;
     }
 
     bool use_tuple = type == T_LIST && parsedargs.immutable;
     ScopedPyObject ret(use_tuple ? PyTuple_New(len) : PyList_New(len));
     if (!ret) {
-      return NULL;
+      return nullptr;
     }
 
     for (int i = 0; i < len; i++) {
       PyObject* item = decodeValue(etype, parsedargs.typeargs);
       if (!item) {
-        return NULL;
+        return nullptr;
       }
       if (use_tuple) {
         PyTuple_SET_ITEM(ret.get(), i, item);
@@ -758,32 +758,32 @@ PyObject* ProtocolBase<Impl>::decodeValue(TType type, PyObject* typeargs) {
   case T_MAP: {
     MapTypeArgs parsedargs;
     if (!parse_map_args(&parsedargs, typeargs)) {
-      return NULL;
+      return nullptr;
     }
 
     TType ktype = T_STOP;
     TType vtype = T_STOP;
     uint32_t len = impl()->readMapBegin(ktype, vtype);
     if (len > 0 && (!checkType(ktype, parsedargs.ktag) || !checkType(vtype, parsedargs.vtag))) {
-      return NULL;
+      return nullptr;
     }
 
     ScopedPyObject ret(PyDict_New());
     if (!ret) {
-      return NULL;
+      return nullptr;
     }
 
     for (uint32_t i = 0; i < len; i++) {
       ScopedPyObject k(decodeValue(ktype, parsedargs.ktypeargs));
       if (!k) {
-        return NULL;
+        return nullptr;
       }
       ScopedPyObject v(decodeValue(vtype, parsedargs.vtypeargs));
       if (!v) {
-        return NULL;
+        return nullptr;
       }
       if (PyDict_SetItem(ret.get(), k.get(), v.get()) == -1) {
-        return NULL;
+        return nullptr;
       }
     }
 
@@ -792,12 +792,12 @@ PyObject* ProtocolBase<Impl>::decodeValue(TType type, PyObject* typeargs) {
         ThriftModule = PyImport_ImportModule("thrift.Thrift");
       }
       if (!ThriftModule) {
-        return NULL;
+        return nullptr;
       }
 
       ScopedPyObject cls(PyObject_GetAttr(ThriftModule, INTERN_STRING(TFrozenDict)));
       if (!cls) {
-        return NULL;
+        return nullptr;
       }
 
       ScopedPyObject arg(PyTuple_New(1));
@@ -811,7 +811,7 @@ PyObject* ProtocolBase<Impl>::decodeValue(TType type, PyObject* typeargs) {
   case T_STRUCT: {
     StructTypeArgs parsedargs;
     if (!parse_struct_args(&parsedargs, typeargs)) {
-      return NULL;
+      return nullptr;
     }
     return readStruct(Py_None, parsedargs.klass, parsedargs.spec);
   }
@@ -823,7 +823,7 @@ PyObject* ProtocolBase<Impl>::decodeValue(TType type, PyObject* typeargs) {
   case T_U64:
   default:
     PyErr_Format(PyExc_TypeError, "Unexpected TType for decodeValue: %d", type);
-    return NULL;
+    return nullptr;
   }
 }
 
@@ -833,26 +833,26 @@ PyObject* ProtocolBase<Impl>::readStruct(PyObject* output, PyObject* klass, PyOb
   bool immutable = output == Py_None;
   ScopedPyObject kwargs;
   if (spec_seq_len == -1) {
-    return NULL;
+    return nullptr;
   }
 
   if (immutable) {
     kwargs.reset(PyDict_New());
     if (!kwargs) {
       PyErr_SetString(PyExc_TypeError, "failed to prepare kwargument storage");
-      return NULL;
+      return nullptr;
     }
   }
 
   detail::ReadStructScope<Impl> scope = detail::readStructScope(this);
   if (!scope) {
-    return NULL;
+    return nullptr;
   }
   while (true) {
     TType type = T_STOP;
     int16_t tag;
     if (!impl()->readFieldBegin(type, tag)) {
-      return NULL;
+      return nullptr;
     }
     if (type == T_STOP) {
       break;
@@ -860,7 +860,7 @@ PyObject* ProtocolBase<Impl>::readStruct(PyObject* output, PyObject* klass, PyOb
     if (tag < 0 || tag >= spec_seq_len) {
       if (!skip(type)) {
         PyErr_SetString(PyExc_TypeError, "Error while skipping unknown field");
-        return NULL;
+        return nullptr;
       }
       continue;
     }
@@ -869,38 +869,38 @@ PyObject* ProtocolBase<Impl>::readStruct(PyObject* output, PyObject* klass, PyOb
     if (item_spec == Py_None) {
       if (!skip(type)) {
         PyErr_SetString(PyExc_TypeError, "Error while skipping unknown field");
-        return NULL;
+        return nullptr;
       }
       continue;
     }
     StructItemSpec parsedspec;
     if (!parse_struct_item_spec(&parsedspec, item_spec)) {
-      return NULL;
+      return nullptr;
     }
     if (parsedspec.type != type) {
       if (!skip(type)) {
         PyErr_Format(PyExc_TypeError, "struct field had wrong type: expected %d but got %d",
                      parsedspec.type, type);
-        return NULL;
+        return nullptr;
       }
       continue;
     }
 
     ScopedPyObject fieldval(decodeValue(parsedspec.type, parsedspec.typeargs));
     if (!fieldval) {
-      return NULL;
+      return nullptr;
     }
 
     if ((immutable && PyDict_SetItem(kwargs.get(), parsedspec.attrname, fieldval.get()) == -1)
         || (!immutable && PyObject_SetAttr(output, parsedspec.attrname, fieldval.get()) == -1)) {
-      return NULL;
+      return nullptr;
     }
   }
   if (immutable) {
     ScopedPyObject args(PyTuple_New(0));
     if (!args) {
       PyErr_SetString(PyExc_TypeError, "failed to prepare argument storage");
-      return NULL;
+      return nullptr;
     }
     return PyObject_Call(klass, args.get(), kwargs.get());
   }

+ 1 - 1
desktop/core/ext-py/thrift-0.13.0/src/ext/types.cpp → desktop/core/ext-py/thrift-0.16.0/src/ext/types.cpp

@@ -24,7 +24,7 @@ namespace apache {
 namespace thrift {
 namespace py {
 
-PyObject* ThriftModule = NULL;
+PyObject* ThriftModule = nullptr;
 
 #if PY_MAJOR_VERSION < 3
 char refill_signature[] = {'s', '#', 'i'};

+ 2 - 2
desktop/core/ext-py/thrift-0.13.0/src/ext/types.h → desktop/core/ext-py/thrift-0.16.0/src/ext/types.h

@@ -83,7 +83,7 @@ enum TType {
 // replace with unique_ptr when we're OK with C++11
 class ScopedPyObject {
 public:
-  ScopedPyObject() : obj_(NULL) {}
+  ScopedPyObject() : obj_(nullptr) {}
   explicit ScopedPyObject(PyObject* py_object) : obj_(py_object) {}
   ~ScopedPyObject() {
     if (obj_)
@@ -98,7 +98,7 @@ public:
   }
   PyObject* release() throw() {
     PyObject* tmp = obj_;
-    obj_ = NULL;
+    obj_ = nullptr;
     return tmp;
   }
   void swap(ScopedPyObject& other) throw() {

+ 4 - 0
desktop/core/ext-py/thrift-0.13.0/src/protocol/TBase.py → desktop/core/ext-py/thrift-0.16.0/src/protocol/TBase.py

@@ -80,3 +80,7 @@ class TFrozenBase(TBase):
                                       [self.__class__, self.thrift_spec])
         else:
             return iprot.readStruct(cls, cls.thrift_spec, True)
+
+
+class TFrozenExceptionBase(TFrozenBase, TExceptionBase):
+    pass

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/protocol/TBinaryProtocol.py → desktop/core/ext-py/thrift-0.16.0/src/protocol/TBinaryProtocol.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/protocol/TCompactProtocol.py → desktop/core/ext-py/thrift-0.16.0/src/protocol/TCompactProtocol.py


+ 12 - 5
desktop/core/ext-py/thrift-0.13.0/src/protocol/THeaderProtocol.py → desktop/core/ext-py/thrift-0.16.0/src/protocol/THeaderProtocol.py

@@ -35,7 +35,9 @@ class THeaderProtocol(TProtocolBase):
 
     THeaderProtocol frames other Thrift protocols and adds support for optional
     out-of-band headers. The currently supported subprotocols are
-    TBinaryProtocol and TCompactProtocol.
+    TBinaryProtocol and TCompactProtocol. When used as a client, the
+    subprotocol to frame can be chosen with the `default_protocol` parameter to
+    the constructor.
 
     It's also possible to apply transforms to the encoded message payload. The
     only transform currently supported is to gzip.
@@ -53,14 +55,14 @@ class THeaderProtocol(TProtocolBase):
 
     """
 
-    def __init__(self, transport, allowed_client_types):
+    def __init__(self, transport, allowed_client_types, default_protocol=THeaderSubprotocolID.BINARY):
         # much of the actual work for THeaderProtocol happens down in
         # THeaderTransport since we need to do low-level shenanigans to detect
         # if the client is sending us headers or one of the headerless formats
         # we support. this wraps the real transport with the one that does all
         # the magic.
         if not isinstance(transport, THeaderTransport):
-            transport = THeaderTransport(transport, allowed_client_types)
+            transport = THeaderTransport(transport, allowed_client_types, default_protocol)
         super(THeaderProtocol, self).__init__(transport)
         self._set_protocol()
 
@@ -218,8 +220,13 @@ class THeaderProtocol(TProtocolBase):
 
 
 class THeaderProtocolFactory(TProtocolFactory):
-    def __init__(self, allowed_client_types=(THeaderClientType.HEADERS,)):
+    def __init__(
+        self,
+        allowed_client_types=(THeaderClientType.HEADERS,),
+        default_protocol=THeaderSubprotocolID.BINARY,
+    ):
         self.allowed_client_types = allowed_client_types
+        self.default_protocol = default_protocol
 
     def getProtocol(self, trans):
-        return THeaderProtocol(trans, self.allowed_client_types)
+        return THeaderProtocol(trans, self.allowed_client_types, self.default_protocol)

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/protocol/TJSONProtocol.py → desktop/core/ext-py/thrift-0.16.0/src/protocol/TJSONProtocol.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/protocol/TMultiplexedProtocol.py → desktop/core/ext-py/thrift-0.16.0/src/protocol/TMultiplexedProtocol.py


+ 8 - 2
desktop/core/ext-py/thrift-0.13.0/src/protocol/TProtocol.py → desktop/core/ext-py/thrift-0.16.0/src/protocol/TProtocol.py

@@ -303,8 +303,14 @@ class TProtocolBase(object):
 
     def readContainerStruct(self, spec):
         (obj_class, obj_spec) = spec
-        obj = obj_class()
-        obj.read(self)
+
+        # If obj_class.read is a classmethod (e.g. in frozen structs),
+        # call it as such.
+        if getattr(obj_class.read, '__self__', None) is obj_class:
+            obj = obj_class.read(self)
+        else:
+            obj = obj_class()
+            obj.read(self)
         return obj
 
     def readContainerMap(self, spec):

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/protocol/TProtocolDecorator.py → desktop/core/ext-py/thrift-0.16.0/src/protocol/TProtocolDecorator.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/protocol/__init__.py → desktop/core/ext-py/thrift-0.16.0/src/protocol/__init__.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/server/THttpServer.py → desktop/core/ext-py/thrift-0.16.0/src/server/THttpServer.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/server/TNonblockingServer.py → desktop/core/ext-py/thrift-0.16.0/src/server/TNonblockingServer.py


+ 5 - 0
desktop/core/ext-py/thrift-0.13.0/src/server/TProcessPoolServer.py → desktop/core/ext-py/thrift-0.16.0/src/server/TProcessPoolServer.py

@@ -42,6 +42,11 @@ class TProcessPoolServer(TServer):
         self.stopCondition = Condition()
         self.postForkCallback = None
 
+    def __getstate__(self):
+        state = self.__dict__.copy()
+        state['workers'] = None
+        return state
+
     def setPostForkCallback(self, callback):
         if not callable(callback):
             raise TypeError("This is not a callback!")

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/server/TServer.py → desktop/core/ext-py/thrift-0.16.0/src/server/TServer.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/server/__init__.py → desktop/core/ext-py/thrift-0.16.0/src/server/__init__.py


+ 2 - 2
desktop/core/ext-py/thrift-0.13.0/src/transport/THeaderTransport.py → desktop/core/ext-py/thrift-0.16.0/src/transport/THeaderTransport.py

@@ -87,7 +87,7 @@ def _writeString(trans, value):
 
 
 class THeaderTransport(TTransportBase, CReadableTransport):
-    def __init__(self, transport, allowed_client_types):
+    def __init__(self, transport, allowed_client_types, default_protocol=THeaderSubprotocolID.BINARY):
         self._transport = transport
         self._client_type = THeaderClientType.HEADERS
         self._allowed_client_types = allowed_client_types
@@ -101,7 +101,7 @@ class THeaderTransport(TTransportBase, CReadableTransport):
 
         self.flags = 0
         self.sequence_id = 0
-        self._protocol_id = THeaderSubprotocolID.BINARY
+        self._protocol_id = default_protocol
         self._max_frame_size = HARD_MAX_FRAME_SIZE
 
     def isOpen(self):

+ 4 - 0
desktop/core/ext-py/thrift-0.13.0/src/transport/THttpClient.py → desktop/core/ext-py/thrift-0.16.0/src/transport/THttpClient.py

@@ -185,3 +185,7 @@ class THttpClient(TTransportBase):
         self.code = self.__http_response.status
         self.message = self.__http_response.reason
         self.headers = self.__http_response.msg
+
+        # Saves the cookie sent by the server response
+        if 'Set-Cookie' in self.headers:
+            self.__http.putheader('Cookie', self.headers['Set-Cookie'])

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/transport/TSSLSocket.py → desktop/core/ext-py/thrift-0.16.0/src/transport/TSSLSocket.py


+ 26 - 2
desktop/core/ext-py/thrift-0.13.0/src/transport/TSocket.py → desktop/core/ext-py/thrift-0.16.0/src/transport/TSocket.py

@@ -39,7 +39,7 @@ class TSocketBase(TTransportBase):
                                       self._socket_family,
                                       socket.SOCK_STREAM,
                                       0,
-                                      socket.AI_PASSIVE | socket.AI_ADDRCONFIG)
+                                      socket.AI_PASSIVE)
 
     def close(self):
         if self.handle:
@@ -74,7 +74,31 @@ class TSocket(TSocketBase):
         self.handle = h
 
     def isOpen(self):
-        return self.handle is not None
+        if self.handle is None:
+            return False
+
+        # this lets us cheaply see if the other end of the socket is still
+        # connected. if disconnected, we'll get EOF back (expressed as zero
+        # bytes of data) otherwise we'll get one byte or an error indicating
+        # we'd have to block for data.
+        #
+        # note that we're not doing this with socket.MSG_DONTWAIT because 1)
+        # it's linux-specific and 2) gevent-patched sockets hide EAGAIN from us
+        # when timeout is non-zero.
+        original_timeout = self.handle.gettimeout()
+        try:
+            self.handle.settimeout(0)
+            try:
+                peeked_bytes = self.handle.recv(1, socket.MSG_PEEK)
+            except (socket.error, OSError) as exc:  # on modern python this is just BlockingIOError
+                if exc.errno in (errno.EWOULDBLOCK, errno.EAGAIN):
+                    return True
+                return False
+        finally:
+            self.handle.settimeout(original_timeout)
+
+        # the length will be zero if we got EOF (indicating connection closed)
+        return len(peeked_bytes) == 1
 
     def setTimeout(self, ms):
         if ms is None:

+ 3 - 0
desktop/core/ext-py/thrift-0.13.0/src/transport/TTransport.py → desktop/core/ext-py/thrift-0.16.0/src/transport/TTransport.py

@@ -398,6 +398,9 @@ class TSaslClientTransport(TTransportBase, CReadableTransport):
                     "Bad SASL negotiation status: %d (%s)"
                     % (status, challenge))
 
+    def isOpen(self):
+        return self.transport.isOpen()
+
     def send_sasl_msg(self, status, body):
         header = pack(">BI", status, len(body))
         self.transport.write(header + body)

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/transport/TTwisted.py → desktop/core/ext-py/thrift-0.16.0/src/transport/TTwisted.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/transport/TZlibTransport.py → desktop/core/ext-py/thrift-0.16.0/src/transport/TZlibTransport.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/transport/__init__.py → desktop/core/ext-py/thrift-0.16.0/src/transport/__init__.py


+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/src/transport/sslcompat.py → desktop/core/ext-py/thrift-0.16.0/src/transport/sslcompat.py


+ 57 - 0
desktop/core/ext-py/thrift-0.16.0/test/test_socket.py

@@ -0,0 +1,57 @@
+import errno
+import unittest
+
+from test_sslsocket import ServerAcceptor
+
+import _import_local_thrift  # noqa
+
+from thrift.transport.TSocket import TServerSocket
+from thrift.transport.TSocket import TSocket
+from thrift.transport.TTransport import TTransportException
+
+
+class TSocketTest(unittest.TestCase):
+    def test_isOpen_checks_for_readability(self):
+        # https://docs.python.org/3/library/socket.html#notes-on-socket-timeouts
+        # https://docs.python.org/3/library/socket.html#socket.socket.settimeout
+        timeouts = [
+            None,  # blocking mode
+            0,  # non-blocking mode
+            1.0,  # timeout mode
+        ]
+
+        for timeout in timeouts:
+            acc = ServerAcceptor(TServerSocket(port=0))
+            acc.start()
+
+            sock = TSocket(host="localhost", port=acc.port)
+            sock.open()
+            sock.setTimeout(timeout)
+
+            # the socket shows as open immediately after connecting
+            self.assertTrue(sock.isOpen())
+
+            # and remains open during usage
+            sock.write(b"hello")
+            self.assertTrue(sock.isOpen())
+            while True:
+                try:
+                    sock.read(5)
+                except TTransportException as exc:
+                    if exc.inner.errno == errno.EAGAIN:
+                        # try again when we're in non-blocking mode
+                        continue
+                    raise
+                break
+            self.assertTrue(sock.isOpen())
+
+            # once the server side closes, it no longer shows open
+            acc.client.close()  # this also blocks until the other thread is done
+            acc.close()
+            self.assertFalse(sock.isOpen())
+
+            sock.close()
+
+
+if __name__ == "__main__":
+    unittest.main()

+ 0 - 0
desktop/core/ext-py/thrift-0.13.0/test/test_sslsocket.py → desktop/core/ext-py/thrift-0.16.0/test/test_sslsocket.py


+ 22 - 0
desktop/core/ext-py/thrift_sasl-0.4.3/PKG-INFO

@@ -0,0 +1,22 @@
+Metadata-Version: 1.1
+Name: thrift_sasl
+Version: 0.4.3
+Summary: Thrift SASL Python module that implements SASL transports for Thrift (`TSaslClientTransport`).
+Home-page: https://github.com/cloudera/thrift_sasl
+Author: UNKNOWN
+Author-email: UNKNOWN
+License: Apache License, Version 2.0
+Description: Thrift SASL Python module that implements SASL transports for Thrift (`TSaslClientTransport`).
+Keywords: thrift sasl transport
+Platform: UNKNOWN
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.6
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9

+ 4 - 0
desktop/core/ext-py/thrift_sasl-0.4.3/README.md

@@ -0,0 +1,4 @@
+# thrift_sasl.py
+
+Thrift SASL Python module that implements SASL transports for Thrift
+(`TSaslClientTransport`).

+ 4 - 0
desktop/core/ext-py/thrift_sasl-0.4.3/setup.cfg

@@ -0,0 +1,4 @@
+[egg_info]
+tag_build = 
+tag_date = 0
+

+ 52 - 0
desktop/core/ext-py/thrift_sasl-0.4.3/setup.py

@@ -0,0 +1,52 @@
+# Copyright 2015 Cloudera Inc.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+#     http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+from __future__ import absolute_import
+
+from setuptools import setup
+
+
+description = ("Thrift SASL Python module that implements SASL transports for "
+               "Thrift (`TSaslClientTransport`).")
+
+setup(
+    name='thrift_sasl',
+    version='0.4.3',
+    description=description,
+    long_description=description,
+    url='https://github.com/cloudera/thrift_sasl',
+    setup_requires=['setuptools>=20.5'],
+    install_requires=[
+        # Python 3 support was added to thrift in version 0.10.0.
+        "thrift>=0.10.0;python_version>='3.0'",
+        "thrift>=0.9.3;python_version<'3.0'",
+        "pure-sasl>=0.6.2",
+        "six>=1.13.0"
+    ],
+    packages=['thrift_sasl'],
+    keywords='thrift sasl transport',
+    license='Apache License, Version 2.0',
+    classifiers=[
+        'Programming Language :: Python :: 2',
+        'Programming Language :: Python :: 2.6',
+        'Programming Language :: Python :: 2.7',
+        'Programming Language :: Python :: 3',
+        'Programming Language :: Python :: 3.3',
+        'Programming Language :: Python :: 3.4',
+        'Programming Language :: Python :: 3.5',
+        'Programming Language :: Python :: 3.6',
+        'Programming Language :: Python :: 3.7',
+        'Programming Language :: Python :: 3.8',
+        'Programming Language :: Python :: 3.9']
+)

+ 230 - 0
desktop/core/ext-py/thrift_sasl-0.4.3/thrift_sasl/__init__.py

@@ -0,0 +1,230 @@
+# Licensed to the Apache Software Foundation (ASF) under one
+# or more contributor license agreements. See the NOTICE file
+# distributed with this work for additional information
+# regarding copyright ownership. The ASF licenses this file
+# to you under the Apache License, Version 2.0 (the
+# "License"); you may not use this file except in compliance
+# with the License. You may obtain a copy of the License at
+#
+#   http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing,
+# software distributed under the License is distributed on an
+# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+# KIND, either express or implied. See the License for the
+# specific language governing permissions and limitations
+# under the License.
+#
+""" SASL transports for Thrift. """
+
+# Initially copied from the Impala repo
+
+from __future__ import absolute_import
+
+import six
+import sys
+import struct
+
+from thrift.transport.TTransport import (TTransportException, TTransportBase, CReadableTransport)
+
+# TODO: Check whether the following distinction is necessary. Does not appear to
+# break anything when `io.BytesIO` is used everywhere, but there may be some edge
+# cases where things break down.
+if sys.version_info[0] == 3:
+    from io import BytesIO as BufferIO
+else:
+    from cStringIO import StringIO as BufferIO
+
+
+class TSaslClientTransport(TTransportBase, CReadableTransport):
+  START = 1
+  OK = 2
+  BAD = 3
+  ERROR = 4
+  COMPLETE = 5
+
+  def __init__(self, sasl_client_factory, mechanism, trans):
+    """
+    @param sasl_client_factory: a callable that returns a new sasl.Client object
+    @param mechanism: the SASL mechanism (e.g. "GSSAPI")
+    @param trans: the underlying transport over which to communicate.
+    """
+    self._trans = trans
+    self.sasl_client_factory = sasl_client_factory
+    self.sasl = None
+    self.mechanism = mechanism
+    self.__wbuf = BufferIO()
+    self.__rbuf = BufferIO()
+    self.opened = False
+    self.encode = None
+
+  def isOpen(self):
+    try:
+      is_open = self._trans.isOpen # Thrift
+    except AttributeError:
+      is_open = self._trans.is_open # thriftpy
+
+    return is_open()
+
+  def is_open(self):
+    return self.isOpen()
+
+  def open(self):
+    if not self.isOpen():
+      self._trans.open()
+
+    if self.sasl is not None:
+      raise TTransportException(
+        type=TTransportException.NOT_OPEN,
+        message="Already open!")
+    self.sasl = self.sasl_client_factory()
+
+    ret, chosen_mech, initial_response = self.sasl.start(self.mechanism)
+    if not ret:
+      raise TTransportException(type=TTransportException.NOT_OPEN,
+        message=("Could not start SASL: %s" % self.sasl.getError()))
+
+    # Send initial response
+    self._send_message(self.START, chosen_mech)
+    self._send_message(self.OK, initial_response)
+
+    # SASL negotiation loop
+    while True:
+      status, payload = self._recv_sasl_message()
+      if status not in (self.OK, self.COMPLETE):
+        raise TTransportException(type=TTransportException.NOT_OPEN,
+          message=("Bad status: %d (%s)" % (status, payload)))
+      if status == self.COMPLETE:
+        break
+      ret, response = self.sasl.step(payload)
+      if not ret:
+        raise TTransportException(type=TTransportException.NOT_OPEN,
+          message=("Bad SASL result: %s" % (self.sasl.getError())))
+      self._send_message(self.OK, response)
+
+  def _send_message(self, status, body):
+    header = struct.pack(">BI", status, len(body))
+    body = six.ensure_binary(body)
+    self._trans.write(header + body)
+    self._trans.flush()
+
+  def _recv_sasl_message(self):
+    header = self._trans_read_all(5)
+    status, length = struct.unpack(">BI", header)
+    if length > 0:
+      payload = self._trans_read_all(length)
+    else:
+      payload = ""
+    return status, payload
+
+  def write(self, data):
+    self.__wbuf.write(data)
+
+  def flush(self):
+    buffer = self.__wbuf.getvalue()
+    # The first time we flush data, we send it to sasl.encode()
+    # If the length doesn't change, then we must be using a QOP
+    # of auth and we should no longer call sasl.encode(), otherwise
+    # we encode every time.
+    if self.encode == None:
+      success, encoded = self.sasl.encode(buffer)
+      if not success:
+        raise TTransportException(type=TTransportException.UNKNOWN,
+                                  message=self.sasl.getError())
+      if (len(encoded)==len(buffer)):
+        self.encode = False
+        self._flushPlain(buffer)
+      else:
+        self.encode = True
+        self._trans.write(encoded)
+    elif self.encode:
+      self._flushEncoded(buffer)
+    else:
+      self._flushPlain(buffer)
+
+    self._trans.flush()
+    self.__wbuf = BufferIO()
+
+  def _flushEncoded(self, buffer):
+    # sasl.ecnode() does the encoding and adds the length header, so nothing
+    # to do but call it and write the result.
+    success, encoded = self.sasl.encode(buffer)
+    if not success:
+      raise TTransportException(type=TTransportException.UNKNOWN,
+                                message=self.sasl.getError())
+    self._trans.write(encoded)
+
+  def _flushPlain(self, buffer):
+    # When we have QOP of auth, sasl.encode() will pass the input to the output
+    # but won't put a length header, so we have to do that.
+
+    # Note stolen from TFramedTransport:
+    # N.B.: Doing this string concatenation is WAY cheaper than making
+    # two separate calls to the underlying socket object. Socket writes in
+    # Python turn out to be REALLY expensive, but it seems to do a pretty
+    # good job of managing string buffer operations without excessive copies
+    self._trans.write(struct.pack(">I", len(buffer)) + buffer)
+
+  def read(self, sz):
+    ret = self.__rbuf.read(sz)
+    if len(ret) == sz:
+      return ret
+
+    self._read_frame()
+    return ret + self.__rbuf.read(sz - len(ret))
+
+  def _read_frame(self):
+    header = self._trans_read_all(4)
+    (length,) = struct.unpack(">I", header)
+    if self.encode:
+      # If the frames are encoded (i.e. you're using a QOP of auth-int or
+      # auth-conf), then make sure to include the header in the bytes you send to
+      # sasl.decode()
+      encoded = header + self._trans_read_all(length)
+      success, decoded = self.sasl.decode(encoded)
+      if not success:
+        raise TTransportException(type=TTransportException.UNKNOWN,
+                                  message=self.sasl.getError())
+    else:
+      # If the frames are not encoded, just pass it through
+      decoded = self._trans_read_all(length)
+    self.__rbuf = BufferIO(decoded)
+
+  def _trans_read_all(self, sz):
+    try:
+      read_all = self._trans.readAll # Thrift
+    except AttributeError:
+      def read_all(sz): # thriftpy
+        buff = b''
+        have = 0
+        while have < sz:
+          chunk = self._trans.read(sz - have)
+          have += len(chunk)
+          buff += chunk
+
+          if len(chunk) == 0:
+            raise TTransportException(type=TTransportException.END_OF_FILE,
+                                      message="End of file reading from transport")
+
+        return buff
+    return read_all(sz)
+
+  def close(self):
+    self._trans.close()
+    self.sasl = None
+
+  # Implement the CReadableTransport interface.
+  # Stolen shamelessly from TFramedTransport
+  @property
+  def cstringio_buf(self):
+    return self.__rbuf
+
+  def cstringio_refill(self, prefix, reqlen):
+    # self.__rbuf will already be empty here because fastbinary doesn't
+    # ask for a refill until the previous buffer is empty.  Therefore,
+    # we can start reading new frames immediately.
+    while len(prefix) < reqlen:
+      self._read_frame()
+      prefix += self.__rbuf.getvalue()
+    self.__rbuf = BufferIO(prefix)
+    return self.__rbuf

+ 2 - 2
desktop/core/requirements.txt

@@ -68,8 +68,8 @@ SQLAlchemy==1.3.8
 sqlparse==0.4.2
 tablib==0.13.0
 tabulate==0.8.9
-thrift==0.13.0
-thrift-sasl==0.4.2
+thrift==0.16.0
+thrift-sasl==0.4.3
 git+https://github.com/gethue/django-babel.git
 werkzeug==2.0.1  # Should remove it here and from devtools.mk
 django-utils-six==2.0