blob: ab9e7812c5a599ab0de556b0bb7746c10237a014 [file] [log] [blame]
Brian Silverman9c614bc2016-02-15 20:20:02 -05001# Protocol Buffers - Google's data interchange format
2# Copyright 2008 Google Inc. All rights reserved.
3# https://developers.google.com/protocol-buffers/
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are
7# met:
8#
9# * Redistributions of source code must retain the above copyright
10# notice, this list of conditions and the following disclaimer.
11# * Redistributions in binary form must reproduce the above
12# copyright notice, this list of conditions and the following disclaimer
13# in the documentation and/or other materials provided with the
14# distribution.
15# * Neither the name of Google Inc. nor the names of its
16# contributors may be used to endorse or promote products derived from
17# this software without specific prior written permission.
18#
19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
30
31"""Determine which implementation of the protobuf API is used in this process.
32"""
33
34import os
Austin Schuh40c16522018-10-28 20:27:54 -070035import warnings
Brian Silverman9c614bc2016-02-15 20:20:02 -050036import sys
37
38try:
39 # pylint: disable=g-import-not-at-top
40 from google.protobuf.internal import _api_implementation
41 # The compile-time constants in the _api_implementation module can be used to
42 # switch to a certain implementation of the Python API at build time.
43 _api_version = _api_implementation.api_version
44 _proto_extension_modules_exist_in_build = True
45except ImportError:
46 _api_version = -1 # Unspecified by compiler flags.
47 _proto_extension_modules_exist_in_build = False
48
49if _api_version == 1:
50 raise ValueError('api_version=1 is no longer supported.')
51if _api_version < 0: # Still unspecified?
52 try:
53 # The presence of this module in a build allows the proto implementation to
54 # be upgraded merely via build deps rather than a compiler flag or the
55 # runtime environment variable.
56 # pylint: disable=g-import-not-at-top
57 from google.protobuf import _use_fast_cpp_protos
58 # Work around a known issue in the classic bootstrap .par import hook.
59 if not _use_fast_cpp_protos:
60 raise ImportError('_use_fast_cpp_protos import succeeded but was None')
61 del _use_fast_cpp_protos
62 _api_version = 2
63 except ImportError:
Austin Schuh40c16522018-10-28 20:27:54 -070064 try:
65 # pylint: disable=g-import-not-at-top
66 from google.protobuf.internal import use_pure_python
67 del use_pure_python # Avoids a pylint error and namespace pollution.
68 except ImportError:
69 # TODO(b/74017912): It's unsafe to enable :use_fast_cpp_protos by default;
70 # it can cause data loss if you have any Python-only extensions to any
71 # message passed back and forth with C++ code.
72 #
73 # TODO(b/17427486): Once that bug is fixed, we want to make both Python 2
74 # and Python 3 default to `_api_version = 2` (C++ implementation V2).
75 pass
Brian Silverman9c614bc2016-02-15 20:20:02 -050076
77_default_implementation_type = (
78 'python' if _api_version <= 0 else 'cpp')
79
80# This environment variable can be used to switch to a certain implementation
81# of the Python API, overriding the compile-time constants in the
82# _api_implementation module. Right now only 'python' and 'cpp' are valid
83# values. Any other value will be ignored.
84_implementation_type = os.getenv('PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION',
85 _default_implementation_type)
86
87if _implementation_type != 'python':
88 _implementation_type = 'cpp'
89
Austin Schuh40c16522018-10-28 20:27:54 -070090if 'PyPy' in sys.version and _implementation_type == 'cpp':
91 warnings.warn('PyPy does not work yet with cpp protocol buffers. '
92 'Falling back to the python implementation.')
93 _implementation_type = 'python'
94
Brian Silverman9c614bc2016-02-15 20:20:02 -050095# This environment variable can be used to switch between the two
96# 'cpp' implementations, overriding the compile-time constants in the
97# _api_implementation module. Right now only '2' is supported. Any other
98# value will cause an error to be raised.
99_implementation_version_str = os.getenv(
100 'PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION', '2')
101
102if _implementation_version_str != '2':
103 raise ValueError(
104 'unsupported PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION_VERSION: "' +
105 _implementation_version_str + '" (supported versions: 2)'
106 )
107
108_implementation_version = int(_implementation_version_str)
109
110
Austin Schuh40c16522018-10-28 20:27:54 -0700111# Detect if serialization should be deterministic by default
112try:
113 # The presence of this module in a build allows the proto implementation to
114 # be upgraded merely via build deps.
115 #
116 # NOTE: Merely importing this automatically enables deterministic proto
117 # serialization for C++ code, but we still need to export it as a boolean so
118 # that we can do the same for `_implementation_type == 'python'`.
119 #
120 # NOTE2: It is possible for C++ code to enable deterministic serialization by
121 # default _without_ affecting Python code, if the C++ implementation is not in
122 # use by this module. That is intended behavior, so we don't actually expose
123 # this boolean outside of this module.
124 #
125 # pylint: disable=g-import-not-at-top,unused-import
126 from google.protobuf import enable_deterministic_proto_serialization
127 _python_deterministic_proto_serialization = True
128except ImportError:
129 _python_deterministic_proto_serialization = False
130
131
Brian Silverman9c614bc2016-02-15 20:20:02 -0500132# Usage of this function is discouraged. Clients shouldn't care which
133# implementation of the API is in use. Note that there is no guarantee
134# that differences between APIs will be maintained.
135# Please don't use this function if possible.
136def Type():
137 return _implementation_type
138
139
140# See comment on 'Type' above.
141def Version():
142 return _implementation_version
Austin Schuh40c16522018-10-28 20:27:54 -0700143
144
145# For internal use only
146def IsPythonDefaultSerializationDeterministic():
147 return _python_deterministic_proto_serialization
148
149# DO NOT USE: For migration and testing only. Will be removed when Proto3
150# defaults to preserve unknowns.
151if _implementation_type == 'cpp':
152 try:
153 # pylint: disable=g-import-not-at-top
154 from google.protobuf.pyext import _message
155
156 def GetPythonProto3PreserveUnknownsDefault():
157 return _message.GetPythonProto3PreserveUnknownsDefault()
158
159 def SetPythonProto3PreserveUnknownsDefault(preserve):
160 _message.SetPythonProto3PreserveUnknownsDefault(preserve)
161 except ImportError:
162 # Unrecognized cpp implementation. Skipping the unknown fields APIs.
163 pass
164else:
165 _python_proto3_preserve_unknowns_default = True
166
167 def GetPythonProto3PreserveUnknownsDefault():
168 return _python_proto3_preserve_unknowns_default
169
170 def SetPythonProto3PreserveUnknownsDefault(preserve):
171 global _python_proto3_preserve_unknowns_default
172 _python_proto3_preserve_unknowns_default = preserve
173