aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--BUILD52
-rw-r--r--WORKSPACE33
-rw-r--r--csharp/.gitignore1
-rw-r--r--csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs22
-rw-r--r--csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs28
-rw-r--r--csharp/src/Google.Protobuf/CodedInputStream.cs46
-rw-r--r--csharp/src/Google.Protobuf/CodedOutputStream.cs67
-rw-r--r--protobuf.bzl84
-rwxr-xr-xpython/google/__init__.py5
-rwxr-xr-xpython/google/protobuf/__init__.py6
-rw-r--r--python/google/protobuf/pyext/__init__.py4
-rwxr-xr-xpython/setup.py1
-rw-r--r--util/python/BUILD12
13 files changed, 245 insertions, 116 deletions
diff --git a/BUILD b/BUILD
index c4de1c4c..9cbddd5b 100644
--- a/BUILD
+++ b/BUILD
@@ -22,7 +22,6 @@ load(
"protobuf",
"cc_proto_library",
"py_proto_library",
- "internal_copied_filegroup",
"internal_protobuf_py_tests",
)
@@ -484,25 +483,7 @@ java_library(
# Python support
################################################################################
-# Hack:
-# protoc generated files contain imports like:
-# "from google.protobuf.xxx import yyy"
-# However, the sources files of the python runtime are not directly under
-# "google/protobuf" (they are under python/google/protobuf). We workaround
-# this by copying runtime source files into the desired location to workaround
-# the import issue. Ideally py_library should support something similiar to the
-# "include" attribute in cc_library to inject the PYTHON_PATH for all libraries
-# that depend on the target.
-#
-# If you use python protobuf as a third_party library in your bazel managed
-# project:
-# 1) Please import the whole package to //google/protobuf in your
-# project. Otherwise, bazel disallows generated files out of the current
-# package, thus we won't be able to copy protobuf runtime files into
-# //google/protobuf/.
-# 2) The runtime also requires "six" for Python2/3 compatibility, please see the
-# WORKSPACE file and bind "six" to your workspace as well.
-internal_copied_filegroup(
+py_library(
name = "python_srcs",
srcs = glob(
[
@@ -514,7 +495,7 @@ internal_copied_filegroup(
"python/google/protobuf/internal/test_util.py",
],
),
- include = "python",
+ imports = ["python"],
)
cc_binary(
@@ -527,7 +508,7 @@ cc_binary(
linkstatic = 1,
deps = select({
"//conditions:default": [],
- ":use_fast_cpp_protos": ["//util/python:python_headers"],
+ ":use_fast_cpp_protos": ["//external:python_headers"],
}),
)
@@ -553,7 +534,7 @@ cc_binary(
":protobuf",
] + select({
"//conditions:default": [],
- ":use_fast_cpp_protos": ["//util/python:python_headers"],
+ ":use_fast_cpp_protos": ["//external:python_headers"],
}),
)
@@ -584,23 +565,14 @@ py_proto_library(
}),
default_runtime = "",
protoc = ":protoc",
- py_extra_srcs = [":python_srcs"],
- py_libs = ["//external:six"],
+ py_libs = [
+ ":python_srcs",
+ "//external:six"
+ ],
srcs_version = "PY2AND3",
visibility = ["//visibility:public"],
)
-internal_copied_filegroup(
- name = "python_test_srcs",
- srcs = glob(
- [
- "python/google/protobuf/internal/*_test.py",
- "python/google/protobuf/internal/test_util.py",
- ],
- ),
- include = "python",
-)
-
py_proto_library(
name = "python_common_test_protos",
srcs = LITE_TEST_PROTOS + TEST_PROTOS,
@@ -624,7 +596,13 @@ py_proto_library(
py_library(
name = "python_tests",
- srcs = [":python_test_srcs"],
+ srcs = glob(
+ [
+ "python/google/protobuf/internal/*_test.py",
+ "python/google/protobuf/internal/test_util.py",
+ ],
+ ),
+ imports = ["python"],
srcs_version = "PY2AND3",
deps = [
":protobuf_python",
diff --git a/WORKSPACE b/WORKSPACE
index c3f18cc7..1e8e0a7f 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -1,28 +1,33 @@
new_http_archive(
- name = "gmock_archive",
- url = "https://googlemock.googlecode.com/files/gmock-1.7.0.zip",
- sha256 = "26fcbb5925b74ad5fc8c26b0495dfc96353f4d553492eb97e85a8a6d2f43095b",
- build_file = "gmock.BUILD",
+ name = "gmock_archive",
+ url = "https://googlemock.googlecode.com/files/gmock-1.7.0.zip",
+ sha256 = "26fcbb5925b74ad5fc8c26b0495dfc96353f4d553492eb97e85a8a6d2f43095b",
+ build_file = "gmock.BUILD",
)
new_http_archive(
- name = "six_archive",
- url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55",
- sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a",
- build_file = "six.BUILD",
+ name = "six_archive",
+ url = "https://pypi.python.org/packages/source/s/six/six-1.10.0.tar.gz#md5=34eed507548117b2ab523ab14b2f8b55",
+ sha256 = "105f8d68616f8248e24bf0e9372ef04d3cc10104f1980f54d57b2ce73a5ad56a",
+ build_file = "six.BUILD",
)
bind(
- name = "gtest",
- actual = "@gmock_archive//:gtest",
+ name = "python_headers",
+ actual = "//util/python:python_headers",
)
bind(
- name = "gtest_main",
- actual = "@gmock_archive//:gtest_main",
+ name = "gtest",
+ actual = "@gmock_archive//:gtest",
)
bind(
- name = "six",
- actual = "@six_archive//:six",
+ name = "gtest_main",
+ actual = "@gmock_archive//:gtest_main",
+)
+
+bind(
+ name = "six",
+ actual = "@six_archive//:six",
)
diff --git a/csharp/.gitignore b/csharp/.gitignore
index 07ea90ac..c88f741e 100644
--- a/csharp/.gitignore
+++ b/csharp/.gitignore
@@ -33,3 +33,4 @@ mono/.libs
mono/*.exe
mono/*.dll
lib/protoc.exe
+*.ncrunch*
diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
index 0e7cf04e..239d3c9a 100644
--- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
@@ -572,5 +572,27 @@ namespace Google.Protobuf
Assert.Throws<ArgumentOutOfRangeException>(() => CodedInputStream.CreateWithLimits(stream, 0, 1));
Assert.Throws<ArgumentOutOfRangeException>(() => CodedInputStream.CreateWithLimits(stream, 1, 0));
}
+
+ [Test]
+ public void Dispose_DisposesUnderlyingStream()
+ {
+ var memoryStream = new MemoryStream();
+ Assert.IsTrue(memoryStream.CanRead);
+ using (var cis = new CodedInputStream(memoryStream))
+ {
+ }
+ Assert.IsFalse(memoryStream.CanRead); // Disposed
+ }
+
+ [Test]
+ public void Dispose_WithLeaveOpen()
+ {
+ var memoryStream = new MemoryStream();
+ Assert.IsTrue(memoryStream.CanRead);
+ using (var cos = new CodedOutputStream(memoryStream, true))
+ {
+ }
+ Assert.IsTrue(memoryStream.CanRead); // We left the stream open
+ }
}
} \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
index 3297fe87..48bf6d60 100644
--- a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
@@ -387,5 +387,33 @@ namespace Google.Protobuf
Assert.IsTrue(cin.IsAtEnd);
}
}
+
+ [Test]
+ public void Dispose_DisposesUnderlyingStream()
+ {
+ var memoryStream = new MemoryStream();
+ Assert.IsTrue(memoryStream.CanWrite);
+ using (var cos = new CodedOutputStream(memoryStream))
+ {
+ cos.WriteRawByte(0);
+ Assert.AreEqual(0, memoryStream.Position); // Not flushed yet
+ }
+ Assert.AreEqual(1, memoryStream.ToArray().Length); // Flushed data from CodedOutputStream to MemoryStream
+ Assert.IsFalse(memoryStream.CanWrite); // Disposed
+ }
+
+ [Test]
+ public void Dispose_WithLeaveOpen()
+ {
+ var memoryStream = new MemoryStream();
+ Assert.IsTrue(memoryStream.CanWrite);
+ using (var cos = new CodedOutputStream(memoryStream, true))
+ {
+ cos.WriteRawByte(0);
+ Assert.AreEqual(0, memoryStream.Position); // Not flushed yet
+ }
+ Assert.AreEqual(1, memoryStream.Position); // Flushed data from CodedOutputStream to MemoryStream
+ Assert.IsTrue(memoryStream.CanWrite); // We left the stream open
+ }
}
} \ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/CodedInputStream.cs b/csharp/src/Google.Protobuf/CodedInputStream.cs
index 1c02d951..ce6856d6 100644
--- a/csharp/src/Google.Protobuf/CodedInputStream.cs
+++ b/csharp/src/Google.Protobuf/CodedInputStream.cs
@@ -51,9 +51,15 @@ namespace Google.Protobuf
/// and <see cref="MapField{TKey, TValue}"/> to serialize such fields.
/// </para>
/// </remarks>
- public sealed class CodedInputStream
+ public sealed class CodedInputStream : IDisposable
{
/// <summary>
+ /// Whether to leave the underlying stream open when disposing of this stream.
+ /// This is always true when there's no stream.
+ /// </summary>
+ private readonly bool leaveOpen;
+
+ /// <summary>
/// Buffer of data read from the stream or provided at construction time.
/// </summary>
private readonly byte[] buffer;
@@ -120,7 +126,7 @@ namespace Google.Protobuf
}
/// <summary>
- /// Creates a new CodedInputStream that reads from the given byte array slice.
+ /// Creates a new <see cref="CodedInputStream"/> that reads from the given byte array slice.
/// </summary>
public CodedInputStream(byte[] buffer, int offset, int length)
: this(null, ProtoPreconditions.CheckNotNull(buffer, "buffer"), offset, offset + length)
@@ -136,14 +142,28 @@ namespace Google.Protobuf
}
/// <summary>
- /// Creates a new CodedInputStream reading data from the given stream.
+ /// Creates a new <see cref="CodedInputStream"/> reading data from the given stream, which will be disposed
+ /// when the returned object is disposed.
/// </summary>
- public CodedInputStream(Stream input) : this(input, new byte[BufferSize], 0, 0)
+ /// <param name="input">The stream to read from.</param>
+ public CodedInputStream(Stream input) : this(input, false)
{
- ProtoPreconditions.CheckNotNull(input, "input");
}
/// <summary>
+ /// Creates a new <see cref="CodedInputStream"/> reading data from the given stream.
+ /// </summary>
+ /// <param name="input">The stream to read from.</param>
+ /// <param name="leaveOpen"><c>true</c> to leave <paramref name="input"/> open when the returned
+ /// <c cref="CodedInputStream"/> is disposed; <c>false</c> to dispose of the given stream when the
+ /// returned object is disposed.</param>
+ public CodedInputStream(Stream input, bool leaveOpen)
+ : this(ProtoPreconditions.CheckNotNull(input, "input"), new byte[BufferSize], 0, 0)
+ {
+ this.leaveOpen = leaveOpen;
+ }
+
+ /// <summary>
/// Creates a new CodedInputStream reading data from the given
/// stream and buffer, using the default limits.
/// </summary>
@@ -246,6 +266,22 @@ namespace Google.Protobuf
/// </value>
public int RecursionLimit { get { return recursionLimit; } }
+ /// <summary>
+ /// Disposes of this instance, potentially closing any underlying stream.
+ /// </summary>
+ /// <remarks>
+ /// As there is no flushing to perform here, disposing of a <see cref="CodedInputStream"/> which
+ /// was constructed with the <c>leaveOpen</c> option parameter set to <c>true</c> (or one which
+ /// was constructed to read from a byte array) has no effect.
+ /// </remarks>
+ public void Dispose()
+ {
+ if (!leaveOpen)
+ {
+ input.Dispose();
+ }
+ }
+
#region Validation
/// <summary>
/// Verifies that the last call to ReadTag() returned tag 0 - in other words,
diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.cs b/csharp/src/Google.Protobuf/CodedOutputStream.cs
index d6355f03..6211aac3 100644
--- a/csharp/src/Google.Protobuf/CodedOutputStream.cs
+++ b/csharp/src/Google.Protobuf/CodedOutputStream.cs
@@ -55,7 +55,7 @@ namespace Google.Protobuf
/// and <c>MapField&lt;TKey, TValue&gt;</c> to serialize such fields.
/// </para>
/// </remarks>
- public sealed partial class CodedOutputStream
+ public sealed partial class CodedOutputStream : IDisposable
{
// "Local" copy of Encoding.UTF8, for efficiency. (Yes, it makes a difference.)
internal static readonly Encoding Utf8Encoding = Encoding.UTF8;
@@ -65,6 +65,7 @@ namespace Google.Protobuf
/// </summary>
public static readonly int DefaultBufferSize = 4096;
+ private readonly bool leaveOpen;
private readonly byte[] buffer;
private readonly int limit;
private int position;
@@ -91,20 +92,44 @@ namespace Google.Protobuf
this.buffer = buffer;
this.position = offset;
this.limit = offset + length;
+ leaveOpen = true; // Simple way of avoiding trying to dispose of a null reference
}
- private CodedOutputStream(Stream output, byte[] buffer)
+ private CodedOutputStream(Stream output, byte[] buffer, bool leaveOpen)
{
- this.output = output;
+ this.output = ProtoPreconditions.CheckNotNull(output, nameof(output));
this.buffer = buffer;
this.position = 0;
this.limit = buffer.Length;
+ this.leaveOpen = leaveOpen;
+ }
+
+ /// <summary>
+ /// Creates a new <see cref="CodedOutputStream" /> which write to the given stream, and disposes of that
+ /// stream when the returned <c>CodedOutputStream</c> is disposed.
+ /// </summary>
+ /// <param name="output">The stream to write to. It will be disposed when the returned <c>CodedOutputStream is disposed.</c></param>
+ public CodedOutputStream(Stream output) : this(output, DefaultBufferSize, false)
+ {
+ }
+
+ /// <summary>
+ /// Creates a new CodedOutputStream which write to the given stream and uses
+ /// the specified buffer size.
+ /// </summary>
+ /// <param name="output">The stream to write to. It will be disposed when the returned <c>CodedOutputStream is disposed.</c></param>
+ /// <param name="bufferSize">The size of buffer to use internally.</param>
+ public CodedOutputStream(Stream output, int bufferSize) : this(output, new byte[bufferSize], false)
+ {
}
/// <summary>
/// Creates a new CodedOutputStream which write to the given stream.
/// </summary>
- public CodedOutputStream(Stream output) : this(output, DefaultBufferSize)
+ /// <param name="output">The stream to write to.</param>
+ /// <param name="leaveOpen">If <c>true</c>, <paramref name="output"/> is left open when the returned <c>CodedOutputStream</c> is disposed;
+ /// if <c>false</c>, the provided stream is disposed as well.</param>
+ public CodedOutputStream(Stream output, bool leaveOpen) : this(output, DefaultBufferSize, leaveOpen)
{
}
@@ -112,9 +137,13 @@ namespace Google.Protobuf
/// Creates a new CodedOutputStream which write to the given stream and uses
/// the specified buffer size.
/// </summary>
- public CodedOutputStream(Stream output, int bufferSize) : this(output, new byte[bufferSize])
+ /// <param name="output">The stream to write to.</param>
+ /// <param name="bufferSize">The size of buffer to use internally.</param>
+ /// <param name="leaveOpen">If <c>true</c>, <paramref name="output"/> is left open when the returned <c>CodedOutputStream</c> is disposed;
+ /// if <c>false</c>, the provided stream is disposed as well.</param>
+ public CodedOutputStream(Stream output, int bufferSize, bool leaveOpen) : this(output, new byte[bufferSize], leaveOpen)
{
- }
+ }
#endregion
/// <summary>
@@ -660,6 +689,30 @@ namespace Google.Protobuf
}
/// <summary>
+ /// Flushes any buffered data and optionally closes the underlying stream, if any.
+ /// </summary>
+ /// <remarks>
+ /// <para>
+ /// By default, any underlying stream is closed by this method. To configure this behaviour,
+ /// use a constructor overload with a <c>leaveOpen</c> parameter. If this instance does not
+ /// have an underlying stream, this method does nothing.
+ /// </para>
+ /// <para>
+ /// For the sake of efficiency, calling this method does not prevent future write calls - but
+ /// if a later write ends up writing to a stream which has been disposed, that is likely to
+ /// fail. It is recommend that you not call any other methods after this.
+ /// </para>
+ /// </remarks>
+ public void Dispose()
+ {
+ Flush();
+ if (!leaveOpen)
+ {
+ output.Dispose();
+ }
+ }
+
+ /// <summary>
/// Flushes any buffered data to the underlying stream (if there is one).
/// </summary>
public void Flush()
@@ -705,4 +758,4 @@ namespace Google.Protobuf
}
}
}
-} \ No newline at end of file
+}
diff --git a/protobuf.bzl b/protobuf.bzl
index f674a6c6..71eaba22 100644
--- a/protobuf.bzl
+++ b/protobuf.bzl
@@ -15,9 +15,13 @@ def _GenDir(ctx):
return _GetPath(ctx, ctx.attr.includes[0])
return _GetPath(ctx, ctx.label.package + '/' + ctx.attr.includes[0])
-def _CcOuts(srcs):
- return [s[:-len(".proto")] + ".pb.h" for s in srcs] + \
- [s[:-len(".proto")] + ".pb.cc" for s in srcs]
+def _CcOuts(srcs, use_grpc_plugin=False):
+ ret = [s[:-len(".proto")] + ".pb.h" for s in srcs] + \
+ [s[:-len(".proto")] + ".pb.cc" for s in srcs]
+ if use_grpc_plugin:
+ ret += [s[:-len(".proto")] + ".grpc.pb.h" for s in srcs] + \
+ [s[:-len(".proto")] + ".grpc.pb.cc" for s in srcs]
+ return ret
def _PyOuts(srcs):
return [s[:-len(".proto")] + "_pb2.py" for s in srcs]
@@ -63,6 +67,10 @@ def _proto_gen_impl(ctx):
if ctx.attr.gen_py:
args += ["--python_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
+ if ctx.executable.grpc_cpp_plugin:
+ args += ["--plugin=protoc-gen-grpc=" + ctx.executable.grpc_cpp_plugin.path]
+ args += ["--grpc_out=" + ctx.var["GENDIR"] + "/" + gen_dir]
+
if args:
ctx.action(
inputs=srcs + deps,
@@ -90,6 +98,11 @@ _proto_gen = rule(
single_file = True,
mandatory = True,
),
+ "grpc_cpp_plugin": attr.label(
+ cfg = HOST_CFG,
+ executable = True,
+ single_file = True,
+ ),
"gen_cc": attr.bool(),
"gen_py": attr.bool(),
"outs": attr.output_list(),
@@ -104,9 +117,10 @@ def cc_proto_library(
deps=[],
cc_libs=[],
include=None,
- protoc="//google/protobuf:protoc",
+ protoc="//:protoc",
internal_bootstrap_hack=False,
- default_runtime="//google/protobuf:protobuf",
+ use_grpc_plugin=False,
+ default_runtime="//:protobuf",
**kargs):
"""Bazel rule to create a C++ protobuf library from proto source files
@@ -126,6 +140,8 @@ def cc_proto_library(
for bootstraping. When it is set to True, no files will be generated.
The rule will simply be a provider for .proto files, so that other
cc_proto_library can depend on it.
+ use_grpc_plugin: a flag to indicate whether to call the grpc C++ plugin
+ when processing the proto files.
default_runtime: the implicitly default runtime which will be depended on by
the generated cc_library target.
**kargs: other keyword arguments that are passed to cc_library.
@@ -153,13 +169,19 @@ def cc_proto_library(
**kargs)
return
- outs = _CcOuts(srcs)
+ grpc_cpp_plugin = None
+ if use_grpc_plugin:
+ grpc_cpp_plugin = "//external:grpc_cpp_plugin"
+
+ outs = _CcOuts(srcs, use_grpc_plugin)
+
_proto_gen(
name=name + "_genproto",
srcs=srcs,
deps=[s + "_genproto" for s in deps],
includes=includes,
protoc=protoc,
+ grpc_cpp_plugin=grpc_cpp_plugin,
gen_cc=1,
outs=outs,
visibility=["//visibility:public"],
@@ -167,6 +189,8 @@ def cc_proto_library(
if default_runtime and not default_runtime in cc_libs:
cc_libs += [default_runtime]
+ if use_grpc_plugin:
+ cc_libs += ["//external:grpc_lib"]
native.cc_library(
name=name,
@@ -175,37 +199,6 @@ def cc_proto_library(
includes=includes,
**kargs)
-
-def internal_copied_filegroup(
- name,
- srcs,
- include,
- **kargs):
- """Bazel rule to fix sources file to workaround with python path issues.
-
- Args:
- name: the name of the internal_copied_filegroup rule, which will be the
- name of the generated filegroup.
- srcs: the source files to be copied.
- include: the expected import root of the source.
- **kargs: extra arguments that will be passed into the filegroup.
- """
- outs = [_RelativeOutputPath(s, include) for s in srcs]
-
- native.genrule(
- name=name+"_genrule",
- srcs=srcs,
- outs=outs,
- cmd=" && ".join(["cp $(location %s) $(location %s)" %
- (s, _RelativeOutputPath(s, include))
- for s in srcs]))
-
- native.filegroup(
- name=name,
- srcs=outs,
- **kargs)
-
-
def py_proto_library(
name,
srcs=[],
@@ -213,8 +206,8 @@ def py_proto_library(
py_libs=[],
py_extra_srcs=[],
include=None,
- default_runtime="//google/protobuf:protobuf_python",
- protoc="//google/protobuf:protoc",
+ default_runtime="//:protobuf_python",
+ protoc="//:protoc",
**kargs):
"""Bazel rule to create a Python protobuf library from proto source files
@@ -254,15 +247,6 @@ def py_proto_library(
visibility=["//visibility:public"],
)
- if include != None:
- # Copy the output files to the desired location to make the import work.
- internal_copied_filegroup_name=name + "_internal_copied_filegroup"
- internal_copied_filegroup(
- name=internal_copied_filegroup_name,
- srcs=outs,
- include=include)
- outs=[internal_copied_filegroup_name]
-
if default_runtime and not default_runtime in py_libs + deps:
py_libs += [default_runtime]
@@ -270,6 +254,7 @@ def py_proto_library(
name=name,
srcs=outs+py_extra_srcs,
deps=py_libs+deps,
+ imports=includes,
**kargs)
def internal_protobuf_py_tests(
@@ -286,8 +271,7 @@ def internal_protobuf_py_tests(
"""
for m in modules:
- s = _RelativeOutputPath(
- "python/google/protobuf/internal/%s.py" % m, "python")
+ s = "python/google/protobuf/internal/%s.py" % m
native.py_test(
name="py_%s" % m,
srcs=[s],
diff --git a/python/google/__init__.py b/python/google/__init__.py
index de40ea7c..55856141 100755
--- a/python/google/__init__.py
+++ b/python/google/__init__.py
@@ -1 +1,4 @@
-__import__('pkg_resources').declare_namespace(__name__)
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/python/google/protobuf/__init__.py b/python/google/protobuf/__init__.py
index 533821c1..5d244191 100755
--- a/python/google/protobuf/__init__.py
+++ b/python/google/protobuf/__init__.py
@@ -31,3 +31,9 @@
# Copyright 2007 Google Inc. All Rights Reserved.
__version__ = '3.0.0b2'
+
+if __name__ != '__main__':
+ try:
+ __import__('pkg_resources').declare_namespace(__name__)
+ except ImportError:
+ __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/python/google/protobuf/pyext/__init__.py b/python/google/protobuf/pyext/__init__.py
index e69de29b..55856141 100644
--- a/python/google/protobuf/pyext/__init__.py
+++ b/python/google/protobuf/pyext/__init__.py
@@ -0,0 +1,4 @@
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except ImportError:
+ __path__ = __import__('pkgutil').extend_path(__path__, __name__)
diff --git a/python/setup.py b/python/setup.py
index 6ea3bad7..24ac53db 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -210,7 +210,6 @@ if __name__ == '__main__':
"Programming Language :: Python :: 3.3",
"Programming Language :: Python :: 3.4",
],
- namespace_packages=['google'],
packages=find_packages(
exclude=[
'import_test_package',
diff --git a/util/python/BUILD b/util/python/BUILD
index 358c381c..3ac03856 100644
--- a/util/python/BUILD
+++ b/util/python/BUILD
@@ -1,7 +1,17 @@
# This is a placeholder for python headers. Projects needing to use
# fast cpp protos in protobuf's python interface should build with
# --define=use_fast_cpp_protos=true, and in addition, provide
-# //util/python:python_headers dependency that in turn provides Python.h.
+# //external:python_headers dependency that in turn provides Python.h.
+#
+# Projects that include protobuf using a Bazel external repository will need to
+# add a workspace rule to their WORKSPACE files to add an external workspace
+# that includes the Python headers. For example, the protobuf WORKSPACE file
+# includes the following local_repository rule that points to this directory:
+#
+# new_local_repository(
+# name = "python",
+# path = __workspace_dir__ + "/util/python",
+# )
cc_library(
name = "python_headers",
visibility = ["//visibility:public"],