123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142 |
- # Protocol Buffers - Google's data interchange format
- # Copyright 2008 Google Inc. All rights reserved.
- #
- # Use of this source code is governed by a BSD-style
- # license that can be found in the LICENSE file or at
- # https://developers.google.com/open-source/licenses/bsd
- """Determine which implementation of the protobuf API is used in this process.
- """
- import importlib
- import os
- import sys
- import warnings
- _GOOGLE3_PYTHON_UPB_DEFAULT = True
- def _ApiVersionToImplementationType(api_version):
- if api_version == 2:
- return 'cpp'
- if api_version == 1:
- raise ValueError('api_version=1 is no longer supported.')
- if api_version == 0:
- return 'python'
- return None
- _implementation_type = None
- try:
- # pylint: disable=g-import-not-at-top
- from google.protobuf.internal import _api_implementation
- # The compile-time constants in the _api_implementation module can be used to
- # switch to a certain implementation of the Python API at build time.
- _implementation_type = _ApiVersionToImplementationType(
- _api_implementation.api_version)
- except ImportError:
- pass # Unspecified by compiler flags.
- def _CanImport(mod_name):
- try:
- mod = importlib.import_module(mod_name)
- # Work around a known issue in the classic bootstrap .par import hook.
- if not mod:
- raise ImportError(mod_name + ' import succeeded but was None')
- return True
- except ImportError:
- return False
- if _implementation_type is None:
- if _CanImport('google._upb._message'):
- _implementation_type = 'upb'
- elif _CanImport('google.protobuf.pyext._message'):
- _implementation_type = 'cpp'
- else:
- _implementation_type = 'python'
- # This environment variable can be used to switch to a certain implementation
- # of the Python API, overriding the compile-time constants in the
- # _api_implementation module. Right now only 'python', 'cpp' and 'upb' are
- # valid values. Any other value will raise error.
- _implementation_type = os.getenv('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION',
- _implementation_type)
- if _implementation_type not in ('python', 'cpp', 'upb'):
- raise ValueError('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION {0} is not '
- 'supported. Please set to \'python\', \'cpp\' or '
- '\'upb\'.'.format(_implementation_type))
- 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'
- _c_module = None
- if _implementation_type == 'cpp':
- try:
- # pylint: disable=g-import-not-at-top
- from google.protobuf.pyext import _message
- sys.modules['google3.net.proto2.python.internal.cpp._message'] = _message
- _c_module = _message
- del _message
- except ImportError:
- # TODO: fail back to python
- warnings.warn(
- 'Selected implementation cpp is not available.')
- pass
- if _implementation_type == 'upb':
- try:
- # pylint: disable=g-import-not-at-top
- from google._upb import _message
- _c_module = _message
- del _message
- except ImportError:
- warnings.warn('Selected implementation upb is not available. '
- 'Falling back to the python implementation.')
- _implementation_type = 'python'
- pass
- # 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.
- # Please don't use this function if possible.
- def Type():
- return _implementation_type
- # See comment on 'Type' above.
- # TODO: Remove the API, it returns a constant. b/228102101
- def Version():
- return 2
- # For internal use only
- def IsPythonDefaultSerializationDeterministic():
- return _python_deterministic_proto_serialization
|