Fixes for Python/C++ implementation in open-source:

  * Rosy hack doesn't apply (that test should be removed
    for the open-source release).

  * Added our own copy of parameterized.py (the open-source
    version of Google Apputils doesn't contain it).

  * The C++ Descriptor object didn't implement extension_ranges.

  * Had to implement a hack around returning EncodeError, to
    work around the module-loading behavior of the test runner.
diff --git a/Makefile.am b/Makefile.am
index 1c64b71..de8ad96 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -197,7 +197,6 @@
 python_EXTRA_DIST=                                                           \
   python/google/protobuf/internal/api_implementation.cc                      \
   python/google/protobuf/internal/api_implementation.py                      \
-  python/google/protobuf/internal/api_implementation_default_test.py         \
   python/google/protobuf/internal/containers.py                              \
   python/google/protobuf/internal/cpp_message.py                             \
   python/google/protobuf/internal/decoder.py                                 \
@@ -221,6 +220,7 @@
   python/google/protobuf/internal/more_extensions.proto                      \
   python/google/protobuf/internal/more_extensions_dynamic.proto              \
   python/google/protobuf/internal/more_messages.proto                        \
+  python/google/protobuf/internal/_parameterized.py                          \
   python/google/protobuf/internal/proto_builder_test.py                      \
   python/google/protobuf/internal/python_message.py                          \
   python/google/protobuf/internal/reflection_test.py                         \
@@ -242,16 +242,17 @@
   python/google/protobuf/pyext/cpp_message.py                                \
   python/google/protobuf/pyext/descriptor.h                                  \
   python/google/protobuf/pyext/descriptor.cc                                 \
-  python/google/protobuf/pyext/descriptor_cpp2_test.py                       \
+  python/google/protobuf/pyext/descriptor_pool.h                             \
+  python/google/protobuf/pyext/descriptor_pool.cc                            \
+  python/google/protobuf/pyext/descriptor_containers.h                       \
+  python/google/protobuf/pyext/descriptor_containers.cc                      \
   python/google/protobuf/pyext/extension_dict.h                              \
   python/google/protobuf/pyext/extension_dict.cc                             \
   python/google/protobuf/pyext/message.h                                     \
   python/google/protobuf/pyext/message.cc                                    \
-  python/google/protobuf/pyext/message_factory_cpp2_test.py                  \
   python/google/protobuf/pyext/proto2_api_test.proto                         \
   python/google/protobuf/pyext/python.proto                                  \
   python/google/protobuf/pyext/python_protobuf.h                             \
-  python/google/protobuf/pyext/reflection_cpp2_generated_test.py             \
   python/google/protobuf/pyext/repeated_composite_container.h                \
   python/google/protobuf/pyext/repeated_composite_container.cc               \
   python/google/protobuf/pyext/repeated_scalar_container.h                   \
diff --git a/python/google/protobuf/internal/_parameterized.py b/python/google/protobuf/internal/_parameterized.py
new file mode 100755
index 0000000..6ed2330
--- /dev/null
+++ b/python/google/protobuf/internal/_parameterized.py
@@ -0,0 +1,438 @@
+#! /usr/bin/python
+#
+# Protocol Buffers - Google's data interchange format
+# Copyright 2008 Google Inc.  All rights reserved.
+# https://developers.google.com/protocol-buffers/
+#
+# Redistribution and use in source and binary forms, with or without
+# modification, are permitted provided that the following conditions are
+# met:
+#
+#     * Redistributions of source code must retain the above copyright
+# notice, this list of conditions and the following disclaimer.
+#     * Redistributions in binary form must reproduce the above
+# copyright notice, this list of conditions and the following disclaimer
+# in the documentation and/or other materials provided with the
+# distribution.
+#     * Neither the name of Google Inc. nor the names of its
+# contributors may be used to endorse or promote products derived from
+# this software without specific prior written permission.
+#
+# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+"""Adds support for parameterized tests to Python's unittest TestCase class.
+
+A parameterized test is a method in a test case that is invoked with different
+argument tuples.
+
+A simple example:
+
+  class AdditionExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+       (1, 2, 3),
+       (4, 5, 9),
+       (1, 1, 3))
+    def testAddition(self, op1, op2, result):
+      self.assertEquals(result, op1 + op2)
+
+
+Each invocation is a separate test case and properly isolated just
+like a normal test method, with its own setUp/tearDown cycle. In the
+example above, there are three separate testcases, one of which will
+fail due to an assertion error (1 + 1 != 3).
+
+Parameters for invididual test cases can be tuples (with positional parameters)
+or dictionaries (with named parameters):
+
+  class AdditionExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+       {'op1': 1, 'op2': 2, 'result': 3},
+       {'op1': 4, 'op2': 5, 'result': 9},
+    )
+    def testAddition(self, op1, op2, result):
+      self.assertEquals(result, op1 + op2)
+
+If a parameterized test fails, the error message will show the
+original test name (which is modified internally) and the arguments
+for the specific invocation, which are part of the string returned by
+the shortDescription() method on test cases.
+
+The id method of the test, used internally by the unittest framework,
+is also modified to show the arguments. To make sure that test names
+stay the same across several invocations, object representations like
+
+  >>> class Foo(object):
+  ...  pass
+  >>> repr(Foo())
+  '<__main__.Foo object at 0x23d8610>'
+
+are turned into '<__main__.Foo>'. For even more descriptive names,
+especially in test logs, you can use the NamedParameters decorator. In
+this case, only tuples are supported, and the first parameters has to
+be a string (or an object that returns an apt name when converted via
+str()):
+
+  class NamedExample(parameterized.ParameterizedTestCase):
+    @parameterized.NamedParameters(
+       ('Normal', 'aa', 'aaa', True),
+       ('EmptyPrefix', '', 'abc', True),
+       ('BothEmpty', '', '', True))
+    def testStartsWith(self, prefix, string, result):
+      self.assertEquals(result, strings.startswith(prefix))
+
+Named tests also have the benefit that they can be run individually
+from the command line:
+
+  $ testmodule.py NamedExample.testStartsWithNormal
+  .
+  --------------------------------------------------------------------
+  Ran 1 test in 0.000s
+
+  OK
+
+Parameterized Classes
+=====================
+If invocation arguments are shared across test methods in a single
+ParameterizedTestCase class, instead of decorating all test methods
+individually, the class itself can be decorated:
+
+  @parameterized.Parameters(
+    (1, 2, 3)
+    (4, 5, 9))
+  class ArithmeticTest(parameterized.ParameterizedTestCase):
+    def testAdd(self, arg1, arg2, result):
+      self.assertEqual(arg1 + arg2, result)
+
+    def testSubtract(self, arg2, arg2, result):
+      self.assertEqual(result - arg1, arg2)
+
+Inputs from Iterables
+=====================
+If parameters should be shared across several test cases, or are dynamically
+created from other sources, a single non-tuple iterable can be passed into
+the decorator. This iterable will be used to obtain the test cases:
+
+  class AdditionExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+      c.op1, c.op2, c.result for c in testcases
+    )
+    def testAddition(self, op1, op2, result):
+      self.assertEquals(result, op1 + op2)
+
+
+Single-Argument Test Methods
+============================
+If a test method takes only one argument, the single argument does not need to
+be wrapped into a tuple:
+
+  class NegativeNumberExample(parameterized.ParameterizedTestCase):
+    @parameterized.Parameters(
+       -1, -3, -4, -5
+    )
+    def testIsNegative(self, arg):
+      self.assertTrue(IsNegative(arg))
+"""
+
+__author__ = 'tmarek@google.com (Torsten Marek)'
+
+import collections
+import functools
+import re
+import types
+import unittest
+import uuid
+
+from google.apputils import basetest
+
+ADDR_RE = re.compile(r'\<([a-zA-Z0-9_\-\.]+) object at 0x[a-fA-F0-9]+\>')
+_SEPARATOR = uuid.uuid1().hex
+_FIRST_ARG = object()
+_ARGUMENT_REPR = object()
+
+
+def _CleanRepr(obj):
+  return ADDR_RE.sub(r'<\1>', repr(obj))
+
+
+# Helper function formerly from the unittest module, removed from it in
+# Python 2.7.
+def _StrClass(cls):
+  return '%s.%s' % (cls.__module__, cls.__name__)
+
+
+def _NonStringIterable(obj):
+  return (isinstance(obj, collections.Iterable) and not
+          isinstance(obj, basestring))
+
+
+def _FormatParameterList(testcase_params):
+  if isinstance(testcase_params, collections.Mapping):
+    return ', '.join('%s=%s' % (argname, _CleanRepr(value))
+                     for argname, value in testcase_params.iteritems())
+  elif _NonStringIterable(testcase_params):
+    return ', '.join(map(_CleanRepr, testcase_params))
+  else:
+    return _FormatParameterList((testcase_params,))
+
+
+class _ParameterizedTestIter(object):
+  """Callable and iterable class for producing new test cases."""
+
+  def __init__(self, test_method, testcases, naming_type):
+    """Returns concrete test functions for a test and a list of parameters.
+
+    The naming_type is used to determine the name of the concrete
+    functions as reported by the unittest framework. If naming_type is
+    _FIRST_ARG, the testcases must be tuples, and the first element must
+    have a string representation that is a valid Python identifier.
+
+    Args:
+      test_method: The decorated test method.
+      testcases: (list of tuple/dict) A list of parameter
+                 tuples/dicts for individual test invocations.
+      naming_type: The test naming type, either _NAMED or _ARGUMENT_REPR.
+    """
+    self._test_method = test_method
+    self.testcases = testcases
+    self._naming_type = naming_type
+
+  def __call__(self, *args, **kwargs):
+    raise RuntimeError('You appear to be running a parameterized test case '
+                       'without having inherited from parameterized.'
+                       'ParameterizedTestCase. This is bad because none of '
+                       'your test cases are actually being run.')
+
+  def __iter__(self):
+    test_method = self._test_method
+    naming_type = self._naming_type
+
+    def MakeBoundParamTest(testcase_params):
+      @functools.wraps(test_method)
+      def BoundParamTest(self):
+        if isinstance(testcase_params, collections.Mapping):
+          test_method(self, **testcase_params)
+        elif _NonStringIterable(testcase_params):
+          test_method(self, *testcase_params)
+        else:
+          test_method(self, testcase_params)
+
+      if naming_type is _FIRST_ARG:
+        # Signal the metaclass that the name of the test function is unique
+        # and descriptive.
+        BoundParamTest.__x_use_name__ = True
+        BoundParamTest.__name__ += str(testcase_params[0])
+        testcase_params = testcase_params[1:]
+      elif naming_type is _ARGUMENT_REPR:
+        # __x_extra_id__ is used to pass naming information to the __new__
+        # method of TestGeneratorMetaclass.
+        # The metaclass will make sure to create a unique, but nondescriptive
+        # name for this test.
+        BoundParamTest.__x_extra_id__ = '(%s)' % (
+            _FormatParameterList(testcase_params),)
+      else:
+        raise RuntimeError('%s is not a valid naming type.' % (naming_type,))
+
+      BoundParamTest.__doc__ = '%s(%s)' % (
+          BoundParamTest.__name__, _FormatParameterList(testcase_params))
+      if test_method.__doc__:
+        BoundParamTest.__doc__ += '\n%s' % (test_method.__doc__,)
+      return BoundParamTest
+    return (MakeBoundParamTest(c) for c in self.testcases)
+
+
+def _IsSingletonList(testcases):
+  """True iff testcases contains only a single non-tuple element."""
+  return len(testcases) == 1 and not isinstance(testcases[0], tuple)
+
+
+def _ModifyClass(class_object, testcases, naming_type):
+  assert not getattr(class_object, '_id_suffix', None), (
+      'Cannot add parameters to %s,'
+      ' which already has parameterized methods.' % (class_object,))
+  class_object._id_suffix = id_suffix = {}
+  for name, obj in class_object.__dict__.items():
+    if (name.startswith(unittest.TestLoader.testMethodPrefix)
+        and isinstance(obj, types.FunctionType)):
+      delattr(class_object, name)
+      methods = {}
+      _UpdateClassDictForParamTestCase(
+          methods, id_suffix, name,
+          _ParameterizedTestIter(obj, testcases, naming_type))
+      for name, meth in methods.iteritems():
+        setattr(class_object, name, meth)
+
+
+def _ParameterDecorator(naming_type, testcases):
+  """Implementation of the parameterization decorators.
+
+  Args:
+    naming_type: The naming type.
+    testcases: Testcase parameters.
+
+  Returns:
+    A function for modifying the decorated object.
+  """
+  def _Apply(obj):
+    if isinstance(obj, type):
+      _ModifyClass(
+          obj,
+          list(testcases) if not isinstance(testcases, collections.Sequence)
+          else testcases,
+          naming_type)
+      return obj
+    else:
+      return _ParameterizedTestIter(obj, testcases, naming_type)
+
+  if _IsSingletonList(testcases):
+    assert _NonStringIterable(testcases[0]), (
+        'Single parameter argument must be a non-string iterable')
+    testcases = testcases[0]
+
+  return _Apply
+
+
+def Parameters(*testcases):
+  """A decorator for creating parameterized tests.
+
+  See the module docstring for a usage example.
+  Args:
+    *testcases: Parameters for the decorated method, either a single
+                iterable, or a list of tuples/dicts/objects (for tests
+                with only one argument).
+
+  Returns:
+     A test generator to be handled by TestGeneratorMetaclass.
+  """
+  return _ParameterDecorator(_ARGUMENT_REPR, testcases)
+
+
+def NamedParameters(*testcases):
+  """A decorator for creating parameterized tests.
+
+  See the module docstring for a usage example. The first element of
+  each parameter tuple should be a string and will be appended to the
+  name of the test method.
+
+  Args:
+    *testcases: Parameters for the decorated method, either a single
+                iterable, or a list of tuples.
+
+  Returns:
+     A test generator to be handled by TestGeneratorMetaclass.
+  """
+  return _ParameterDecorator(_FIRST_ARG, testcases)
+
+
+class TestGeneratorMetaclass(type):
+  """Metaclass for test cases with test generators.
+
+  A test generator is an iterable in a testcase that produces callables. These
+  callables must be single-argument methods. These methods are injected into
+  the class namespace and the original iterable is removed. If the name of the
+  iterable conforms to the test pattern, the injected methods will be picked
+  up as tests by the unittest framework.
+
+  In general, it is supposed to be used in conjuction with the
+  Parameters decorator.
+  """
+
+  def __new__(mcs, class_name, bases, dct):
+    dct['_id_suffix'] = id_suffix = {}
+    for name, obj in dct.items():
+      if (name.startswith(unittest.TestLoader.testMethodPrefix) and
+          _NonStringIterable(obj)):
+        iterator = iter(obj)
+        dct.pop(name)
+        _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator)
+
+    return type.__new__(mcs, class_name, bases, dct)
+
+
+def _UpdateClassDictForParamTestCase(dct, id_suffix, name, iterator):
+  """Adds individual test cases to a dictionary.
+
+  Args:
+    dct: The target dictionary.
+    id_suffix: The dictionary for mapping names to test IDs.
+    name: The original name of the test case.
+    iterator: The iterator generating the individual test cases.
+  """
+  for idx, func in enumerate(iterator):
+    assert callable(func), 'Test generators must yield callables, got %r' % (
+        func,)
+    if getattr(func, '__x_use_name__', False):
+      new_name = func.__name__
+    else:
+      new_name = '%s%s%d' % (name, _SEPARATOR, idx)
+    assert new_name not in dct, (
+        'Name of parameterized test case "%s" not unique' % (new_name,))
+    dct[new_name] = func
+    id_suffix[new_name] = getattr(func, '__x_extra_id__', '')
+
+
+class ParameterizedTestCase(basetest.TestCase):
+  """Base class for test cases using the Parameters decorator."""
+  __metaclass__ = TestGeneratorMetaclass
+
+  def _OriginalName(self):
+    return self._testMethodName.split(_SEPARATOR)[0]
+
+  def __str__(self):
+    return '%s (%s)' % (self._OriginalName(), _StrClass(self.__class__))
+
+  def id(self):  # pylint: disable=invalid-name
+    """Returns the descriptive ID of the test.
+
+    This is used internally by the unittesting framework to get a name
+    for the test to be used in reports.
+
+    Returns:
+      The test id.
+    """
+    return '%s.%s%s' % (_StrClass(self.__class__),
+                        self._OriginalName(),
+                        self._id_suffix.get(self._testMethodName, ''))
+
+
+def CoopParameterizedTestCase(other_base_class):
+  """Returns a new base class with a cooperative metaclass base.
+
+  This enables the ParameterizedTestCase to be used in combination
+  with other base classes that have custom metaclasses, such as
+  mox.MoxTestBase.
+
+  Only works with metaclasses that do not override type.__new__.
+
+  Example:
+
+    import google3
+    import mox
+
+    from google3.testing.pybase import parameterized
+
+    class ExampleTest(parameterized.CoopParameterizedTestCase(mox.MoxTestBase)):
+      ...
+
+  Args:
+    other_base_class: (class) A test case base class.
+
+  Returns:
+    A new class object.
+  """
+  metaclass = type(
+      'CoopMetaclass',
+      (other_base_class.__metaclass__,
+       TestGeneratorMetaclass), {})
+  return metaclass(
+      'CoopParameterizedTestCase',
+      (other_base_class, ParameterizedTestCase), {})
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index 7ab814c..4d4de51 100755
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -51,10 +51,10 @@
 import unittest
 
 from google.apputils import basetest
-from google.apputils.pybase import parameterized
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_proto3_arena_pb2
 from google.protobuf.internal import api_implementation
+from google.protobuf.internal import _parameterized
 from google.protobuf.internal import test_util
 from google.protobuf import message
 
@@ -72,7 +72,7 @@
   return isinf(val) and (val < 0)
 
 
-@parameterized.Parameters(
+@_parameterized.Parameters(
     (unittest_pb2),
     (unittest_proto3_arena_pb2))
 class MessageTest(basetest.TestCase):
@@ -982,7 +982,6 @@
     # This is still an incomplete proto - so serializing should fail
     self.assertRaises(message.EncodeError, unpickled_message.SerializeToString)
 
-
   # TODO(haberman): this isn't really a proto2-specific test except that this
   # message has a required field in it.  Should probably be factored out so
   # that we can test the other parts with proto3.
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 8ac76c6..a62d984 100755
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -1803,16 +1803,6 @@
     self.assertRaises(TypeError,
                       unittest_pb2.TestAllTypes().__getattribute__, 42)
 
-  @basetest.unittest.skipIf(
-      api_implementation.Type() != 'cpp' or api_implementation.Version() != 2,
-      'CPPv2-specific test')
-  def testRosyHack(self):
-    from google.protobuf.pyext import _message
-    from google3.gdata.rosy.proto import core_api2_pb2
-    from google3.gdata.rosy.proto import core_pb2
-    self.assertEqual(_message.Message, core_pb2.PageSelection.__base__)
-    self.assertEqual(_message.Message, core_api2_pb2.PageSelection.__base__)
-
 
 #  Since we had so many tests for protocol buffer equality, we broke these out
 #  into separate TestCase classes.
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 68ab965..b307620 100755
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -37,12 +37,12 @@
 import re
 
 from google.apputils import basetest
-from google.apputils.pybase import parameterized
 
 from google.protobuf import unittest_mset_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_proto3_arena_pb2
 from google.protobuf.internal import api_implementation
+from google.protobuf.internal import _parameterized
 from google.protobuf.internal import test_util
 from google.protobuf import text_format
 
@@ -72,7 +72,7 @@
     return text
 
 
-@parameterized.Parameters(
+@_parameterized.Parameters(
     (unittest_pb2),
     (unittest_proto3_arena_pb2))
 class TextFormatTest(TextFormatBase):
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py
index 88ed9f4..de2f569 100755
--- a/python/google/protobuf/message.py
+++ b/python/google/protobuf/message.py
@@ -36,7 +36,6 @@
 
 __author__ = 'robinson@google.com (Will Robinson)'
 
-
 class Error(Exception): pass
 class DecodeError(Error): pass
 class EncodeError(Error): pass
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index d9b90dd..6890cd0 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -433,6 +433,20 @@
   }
 }
 
+static PyObject* GetExtensionRanges(PyBaseDescriptor *self, void *closure) {
+  const Descriptor* descriptor = _GetDescriptor(self);
+  PyObject* range_list = PyList_New(descriptor->extension_range_count());
+
+  for (int i = 0; i < descriptor->extension_range_count(); i++) {
+    const Descriptor::ExtensionRange* range = descriptor->extension_range(i);
+    PyObject* start = PyInt_FromLong(range->start);
+    PyObject* end = PyInt_FromLong(range->end);
+    PyList_SetItem(range_list, i, PyTuple_Pack(2, start, end));
+  }
+
+  return range_list;
+}
+
 static PyObject* GetContainingType(PyBaseDescriptor *self, void *closure) {
   const Descriptor* containing_type =
       _GetDescriptor(self)->containing_type();
@@ -512,6 +526,7 @@
   { C("nested_types_by_name"), (getter)GetNestedTypesByName, NULL, "Nested types by name", NULL},
   { C("extensions"), (getter)GetExtensions, NULL, "Extensions Sequence", NULL},
   { C("extensions_by_name"), (getter)GetExtensionsByName, NULL, "Extensions by name", NULL},
+  { C("extension_ranges"), (getter)GetExtensionRanges, NULL, "Extension ranges", NULL},
   { C("enum_types"), (getter)GetEnumsSeq, NULL, "Enum sequence", NULL},
   { C("enum_types_by_name"), (getter)GetEnumTypesByName, NULL, "Enum types by name", NULL},
   { C("enum_values_by_name"), (getter)GetEnumValuesByName, NULL, "Enum values by name", NULL},
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index 137f5d5..c48f94c 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -1264,7 +1264,27 @@
     if (joined == NULL) {
       return NULL;
     }
-    PyErr_Format(EncodeError_class, "Message %s is missing required fields: %s",
+
+    // TODO(haberman): this is a (hopefully temporary) hack.  The unit testing
+    // infrastructure reloads all pure-Python modules for every test, but not
+    // C++ modules (because that's generally impossible:
+    // http://bugs.python.org/issue1144263).  But if we cache EncodeError, we'll
+    // return the EncodeError from a previous load of the module, which won't
+    // match a user's attempt to catch EncodeError.  So we have to look it up
+    // again every time.
+    ScopedPyObjectPtr message_module(PyImport_ImportModule(
+        "google.protobuf.message"));
+    if (message_module.get() == NULL) {
+      return NULL;
+    }
+
+    ScopedPyObjectPtr encode_error(
+        PyObject_GetAttrString(message_module, "EncodeError"));
+    if (encode_error.get() == NULL) {
+      return NULL;
+    }
+    PyErr_Format(encode_error.get(),
+                 "Message %s is missing required fields: %s",
                  GetMessageName(self).c_str(), PyString_AsString(joined));
     return NULL;
   }
@@ -2284,8 +2304,8 @@
 
 PyTypeObject CMessage_Type = {
   PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  "google.protobuf.internal."
-  "cpp._message.CMessage",             // tp_name
+  "google.protobuf."
+  "pyext._message.CMessage",           // tp_name
   sizeof(CMessage),                    // tp_basicsize
   0,                                   //  tp_itemsize
   (destructor)cmessage::Dealloc,       //  tp_dealloc
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 49ef799..abc859d 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -732,8 +732,8 @@
 
 PyTypeObject RepeatedCompositeContainer_Type = {
   PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  "google.protobuf.internal."
-  "cpp._message.RepeatedCompositeContainer",  // tp_name
+  "google.protobuf.pyext."
+  "_message.RepeatedCompositeContainer",  // tp_name
   sizeof(RepeatedCompositeContainer),     // tp_basicsize
   0,                                   //  tp_itemsize
   (destructor)repeated_composite_container::Dealloc,  //  tp_dealloc
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index 9f8075b..1747459 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -769,8 +769,8 @@
 
 PyTypeObject RepeatedScalarContainer_Type = {
   PyVarObject_HEAD_INIT(&PyType_Type, 0)
-  "google.protobuf.internal."
-  "cpp._message.RepeatedScalarContainer",  // tp_name
+  "google.protobuf."
+  "pyext._message.RepeatedScalarContainer",  // tp_name
   sizeof(RepeatedScalarContainer),     // tp_basicsize
   0,                                   //  tp_itemsize
   (destructor)repeated_scalar_container::Dealloc,  //  tp_dealloc
diff --git a/src/Makefile.am b/src/Makefile.am
index 0f0bd08..deb0f8a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -307,6 +307,7 @@
   google/protobuf/io/gzip_stream_unittest.sh                   \
   google/protobuf/testdata/golden_message                      \
   google/protobuf/testdata/golden_message_oneof_implemented    \
+  google/protobuf/testdata/golden_message_proto3               \
   google/protobuf/testdata/golden_packed_fields_message        \
   google/protobuf/testdata/bad_utf8_string                     \
   google/protobuf/testdata/text_format_unittest_data.txt       \