diff options
Diffstat (limited to 'python/google/protobuf/internal/api_implementation.py')
-rwxr-xr-x | python/google/protobuf/internal/api_implementation.py | 74 |
1 files changed, 70 insertions, 4 deletions
diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py index ffcf7511..ab9e7812 100755 --- a/python/google/protobuf/internal/api_implementation.py +++ b/python/google/protobuf/internal/api_implementation.py @@ -32,6 +32,7 @@ """ import os +import warnings import sys try: @@ -60,10 +61,18 @@ if _api_version < 0: # Still unspecified? del _use_fast_cpp_protos _api_version = 2 except ImportError: - if _proto_extension_modules_exist_in_build: - if sys.version_info[0] >= 3: # Python 3 defaults to C++ impl v2. - _api_version = 2 - # TODO(b/17427486): Make Python 2 default to C++ impl v2. + try: + # pylint: disable=g-import-not-at-top + from google.protobuf.internal import use_pure_python + del use_pure_python # Avoids a pylint error and namespace pollution. + except ImportError: + # TODO(b/74017912): It's unsafe to enable :use_fast_cpp_protos by default; + # it can cause data loss if you have any Python-only extensions to any + # message passed back and forth with C++ code. + # + # TODO(b/17427486): Once that bug is fixed, we want to make both Python 2 + # and Python 3 default to `_api_version = 2` (C++ implementation V2). + pass _default_implementation_type = ( 'python' if _api_version <= 0 else 'cpp') @@ -78,6 +87,11 @@ _implementation_type = os.getenv('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION', if _implementation_type != 'python': _implementation_type = 'cpp' +if 'PyPy' in sys.version and _implementation_type == 'cpp': + warnings.warn('PyPy does not work yet with cpp protocol buffers. ' + 'Falling back to the python implementation.') + _implementation_type = 'python' + # This environment variable can be used to switch between the two # 'cpp' implementations, overriding the compile-time constants in the # _api_implementation module. Right now only '2' is supported. Any other @@ -94,6 +108,27 @@ if _implementation_version_str != '2': _implementation_version = int(_implementation_version_str) +# Detect if serialization should be deterministic by default +try: + # The presence of this module in a build allows the proto implementation to + # be upgraded merely via build deps. + # + # NOTE: Merely importing this automatically enables deterministic proto + # serialization for C++ code, but we still need to export it as a boolean so + # that we can do the same for `_implementation_type == 'python'`. + # + # NOTE2: It is possible for C++ code to enable deterministic serialization by + # default _without_ affecting Python code, if the C++ implementation is not in + # use by this module. That is intended behavior, so we don't actually expose + # this boolean outside of this module. + # + # pylint: disable=g-import-not-at-top,unused-import + from google.protobuf import enable_deterministic_proto_serialization + _python_deterministic_proto_serialization = True +except ImportError: + _python_deterministic_proto_serialization = False + + # Usage of this function is discouraged. Clients shouldn't care which # implementation of the API is in use. Note that there is no guarantee # that differences between APIs will be maintained. @@ -105,3 +140,34 @@ def Type(): # See comment on 'Type' above. def Version(): return _implementation_version + + +# For internal use only +def IsPythonDefaultSerializationDeterministic(): + return _python_deterministic_proto_serialization + +# DO NOT USE: For migration and testing only. Will be removed when Proto3 +# defaults to preserve unknowns. +if _implementation_type == 'cpp': + try: + # pylint: disable=g-import-not-at-top + from google.protobuf.pyext import _message + + def GetPythonProto3PreserveUnknownsDefault(): + return _message.GetPythonProto3PreserveUnknownsDefault() + + def SetPythonProto3PreserveUnknownsDefault(preserve): + _message.SetPythonProto3PreserveUnknownsDefault(preserve) + except ImportError: + # Unrecognized cpp implementation. Skipping the unknown fields APIs. + pass +else: + _python_proto3_preserve_unknowns_default = True + + def GetPythonProto3PreserveUnknownsDefault(): + return _python_proto3_preserve_unknowns_default + + def SetPythonProto3PreserveUnknownsDefault(preserve): + global _python_proto3_preserve_unknowns_default + _python_proto3_preserve_unknowns_default = preserve + |