Added a GitHub Action to test Python+upb on Windows, and fixed a couple of bugs this revealed.

PiperOrigin-RevId: 446322046
diff --git a/.github/workflows/python_tests.yml b/.github/workflows/python_tests.yml
index 4c5098b..8f27939 100644
--- a/.github/workflows/python_tests.yml
+++ b/.github/workflows/python_tests.yml
@@ -9,13 +9,12 @@
       - main
   workflow_dispatch:
 
-env:
-  DOCKER_IMAGE: gcr.io/protobuf-build/bazel/linux@sha256:05a41edee21f620445ca01c46b9d33be2e4d06c3d8adced4341ac5abea754baa
-
 jobs:
   build_wheels:
     name: Build Wheels
     runs-on: ubuntu-latest
+    env:
+      DOCKER_IMAGE: gcr.io/protobuf-build/bazel/linux@sha256:05a41edee21f620445ca01c46b9d33be2e4d06c3d8adced4341ac5abea754baa
 
     steps:
       - name: Set up Cloud SDK
@@ -32,7 +31,7 @@
         run: docker pull $DOCKER_IMAGE
       - uses: actions/checkout@v2
       - name: Build Wheels
-        run: cd ${{ github.workspace }} && docker run -v$PWD:/workspace $DOCKER_IMAGE build --crosstool_top=@com_google_protobuf//toolchain:clang_suite --symlink_prefix=/ -c opt python/dist
+        run: cd ${{ github.workspace }} && docker run -v$PWD:/workspace $DOCKER_IMAGE build --crosstool_top=@com_google_protobuf//toolchain:clang_suite --symlink_prefix=/ -c dbg python/dist python/dist:test_wheel
       - name: Move Wheels
         run: mkdir wheels && find _build/out -name 'protobuf*.whl' -exec mv '{}' wheels ';'
       - uses: actions/upload-artifact@v3
@@ -69,6 +68,12 @@
           source env/bin/activate || source env/Scripts/activate
           echo "VIRTUAL ENV:" $VIRTUAL_ENV
       - name: Install Wheels
-        run: pip install -vvv --no-index --find-links wheels protobuf
+        run: pip install -vvv --no-index --find-links wheels protobuf protobuftests
       - name: Test that module is importable
         run: python -c 'from google._upb import _message; assert "google._upb._message.MessageMeta" in str(_message.MessageMeta)'
+      - name: Run the unit tests
+        run: |
+          TESTS=$(pip show -f protobuftests | grep pb_unit_tests.*py$ | sed 's,/,.,g' | sed 's,\\,.,g' | sed -E 's,.py$,,g')
+          for test in $TESTS; do
+            python -m unittest -v $test
+          done
diff --git a/bazel/protobuf.patch b/bazel/protobuf.patch
new file mode 100644
index 0000000..0de47b2
--- /dev/null
+++ b/bazel/protobuf.patch
@@ -0,0 +1,55 @@
+--- BUILD
++++ BUILD
+@@ -896,6 +896,10 @@ py_library(
+         [
+             "python/google/protobuf/**/*.py",
+         ],
++        exclude = [
++            "python/google/protobuf/internal/*_test.py",
++            "python/google/protobuf/internal/test_util.py",
++        ]
+     ),
+     imports = ["python"],
+     srcs_version = "PY2AND3",
+
+--- python/google/protobuf/internal/test_util.py
++++ python/google/protobuf/internal/test_util.py
+@@ -39,6 +39,7 @@ __author__ = 'robinson@google.com (Will Robinson)'
+ import numbers
+ import operator
+ import os.path
++import pathlib
+ 
+ from google.protobuf import unittest_import_pb2
+ from google.protobuf import unittest_pb2
+@@ -617,17 +618,22 @@ def ExpectAllFieldsSet(test_case, message):
+                           message.default_import_enum)
+ 
+ 
++def _SearchUp(path, filename):
++  path = pathlib.Path(path).resolve()
++  for parent in [path] + list(path.parents):
++    file_path = parent / ('src/google/protobuf/testdata/' + filename)
++    if file_path.exists():
++      # Found it.  Load the golden file from the testdata directory.
++      return file_path.open('rb')
++  return None
++
+ def GoldenFile(filename):
+   """Finds the given golden file and returns a file object representing it."""
+ 
+   # Search up the directory tree looking for the C++ protobuf source code.
+-  path = '.'
+-  while os.path.exists(path):
+-    if os.path.exists(os.path.join(path, 'src/google/protobuf')):
+-      # Found it.  Load the golden file from the testdata directory.
+-      full_path = os.path.join(path, 'src/google/protobuf/testdata', filename)
+-      return open(full_path, 'rb')
+-    path = os.path.join(path, '..')
++  f = _SearchUp('.', filename) or _SearchUp(__file__, filename)
++  if f:
++      return f
+ 
+   # Search internally.
+   path = '.'
+
diff --git a/bazel/system_python.bzl b/bazel/system_python.bzl
index 6434354..7e2dac9 100644
--- a/bazel/system_python.bzl
+++ b/bazel/system_python.bzl
@@ -77,7 +77,7 @@
     python3 = repository_ctx.which("python3")
     python_version = _get_python_version(repository_ctx)
     repository_ctx.file("BUILD.bazel", _build_file.format(python3))
-    repository_ctx.file("version.bzl", "SYSTEM_PYTHON_VERSION = {}".format(python_version))
+    repository_ctx.file("version.bzl", "SYSTEM_PYTHON_VERSION = '{}'".format(python_version))
 
 # The system_python() repository rule exposes Python headers from the system.
 #
diff --git a/bazel/workspace_deps.bzl b/bazel/workspace_deps.bzl
index 6301f5f..a20a49e 100644
--- a/bazel/workspace_deps.bzl
+++ b/bazel/workspace_deps.bzl
@@ -25,6 +25,7 @@
         name = "com_google_protobuf",
         repo = "https://github.com/protocolbuffers/protobuf",
         commit = "ec79d0d328c7e6cea15cc27fbeb9b018ca289590",
+        patches = ["//bazel:protobuf.patch"],
     )
 
     rules_python_version = "740825b7f74930c62f44af95c9a4c1bd428d2c53"  # Latest @ 2021-06-23
diff --git a/python/dist/BUILD.bazel b/python/dist/BUILD.bazel
index 9ee1f29..b868f86 100644
--- a/python/dist/BUILD.bazel
+++ b/python/dist/BUILD.bazel
@@ -28,6 +28,7 @@
 load("@bazel_skylib//lib:selects.bzl", "selects")
 load("@com_google_protobuf//:protobuf_version.bzl", "PROTOBUF_VERSION")
 load("@rules_python//python:packaging.bzl", "py_wheel")
+load("@system_python//:version.bzl", "SYSTEM_PYTHON_VERSION")
 
 licenses(["notice"])
 
@@ -102,7 +103,7 @@
         "//python:full_api_3.8": "cp38",
         "//python:full_api_3.9": "cp39",
         "//python:limited_api_3.10": "cp310",
-        "//conditions:default": "system",
+        "//conditions:default": "cp" + SYSTEM_PYTHON_VERSION,
     }),
     strip_path_prefixes = [
         "python/dist/",
@@ -119,6 +120,23 @@
     ],
 )
 
+py_wheel(
+    name = "test_wheel",
+    abi = "none",
+    distribution = "protobuftests",
+    platform = "any",
+    python_tag = "py3",
+    strip_path_prefixes = ["python/"],
+    version = PROTOBUF_VERSION,
+    deps = [
+        "//python/pb_unit_tests:test_files",
+        "@com_google_protobuf//:python_common_test_protos",
+        "@com_google_protobuf//:python_specific_test_protos",
+        "@com_google_protobuf//:python_test_srcs",
+        "@com_google_protobuf//:testdata",
+    ],
+)
+
 py_dist(
     name = "dist",
     binary_wheel = ":binary_wheel",
diff --git a/python/minimal_test.py b/python/minimal_test.py
index 6924ace..3c0df48 100644
--- a/python/minimal_test.py
+++ b/python/minimal_test.py
@@ -29,16 +29,16 @@
 
 import unittest
 from google.protobuf.pyext import _message
-from google.protobuf.internal import api_implementation
+from google3.net.proto2.python.internal import api_implementation
 from google.protobuf import unittest_pb2
 from google.protobuf import map_unittest_pb2
 from google.protobuf import descriptor_pool
 from google.protobuf import text_format
 from google.protobuf import message_factory
 from google.protobuf import message
-from google.protobuf.internal import factory_test1_pb2
-from google.protobuf.internal import factory_test2_pb2
-from google.protobuf.internal import more_extensions_pb2
+from google3.net.proto2.python.internal import factory_test1_pb2
+from google3.net.proto2.python.internal import factory_test2_pb2
+from google3.net.proto2.python.internal import more_extensions_pb2
 from google.protobuf import descriptor_pb2
 
 class TestMessageExtension(unittest.TestCase):
diff --git a/python/pb_unit_tests/BUILD b/python/pb_unit_tests/BUILD
index 9369c05..992354a 100644
--- a/python/pb_unit_tests/BUILD
+++ b/python/pb_unit_tests/BUILD
@@ -62,3 +62,9 @@
 pyproto_test_wrapper(name = "well_known_types_test")
 
 pyproto_test_wrapper(name = "wire_format_test")
+
+filegroup(
+    name = "test_files",
+    srcs = glob(["*.py"]),
+    visibility = ["//python/dist:__pkg__"],
+)
diff --git a/python/pb_unit_tests/descriptor_database_test_wrapper.py b/python/pb_unit_tests/descriptor_database_test_wrapper.py
index 125533e..8cabf0f 100644
--- a/python/pb_unit_tests/descriptor_database_test_wrapper.py
+++ b/python/pb_unit_tests/descriptor_database_test_wrapper.py
@@ -23,8 +23,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import descriptor_database_test
+from google.protobuf.internal.descriptor_database_test import *
 import unittest
 
 if __name__ == '__main__':
-  unittest.main(module=descriptor_database_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/descriptor_pool_test_wrapper.py b/python/pb_unit_tests/descriptor_pool_test_wrapper.py
index bb15306..ee95d6f 100644
--- a/python/pb_unit_tests/descriptor_pool_test_wrapper.py
+++ b/python/pb_unit_tests/descriptor_pool_test_wrapper.py
@@ -24,22 +24,22 @@
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 import unittest
-from google.protobuf.internal import descriptor_pool_test
+from google.protobuf.internal.descriptor_pool_test import *
 
 # This is testing that certain methods unconditionally throw TypeError.
 # In the new extension we simply don't define them at all.
-descriptor_pool_test.AddDescriptorTest.testAddTypeError.__unittest_expecting_failure__ = True
+AddDescriptorTest.testAddTypeError.__unittest_expecting_failure__ = True
 
-descriptor_pool_test.SecondaryDescriptorFromDescriptorDB.testErrorCollector.__unittest_expecting_failure__ = True
+SecondaryDescriptorFromDescriptorDB.testErrorCollector.__unittest_expecting_failure__ = True
 
 # begin:github_only
 if __name__ == '__main__':
-  unittest.main(module=descriptor_pool_test, verbosity=2)
+  unittest.main(verbosity=2)
 # end:github_only
 
 # begin:google_only
-# descriptor_pool_test.CreateDescriptorPoolTest.testComplexNestingWithProtoFileParser.__unittest_expecting_failure__ = True
+# CreateDescriptorPoolTest.testComplexNestingWithProtoFileParser.__unittest_expecting_failure__ = True
 # from absl import app
 # if __name__ == '__main__':
-#   app.run(lambda argv: unittest.main(module=descriptor_pool_test, verbosity=2))
+#   app.run(lambda argv: unittest.main(verbosity=2))
 # end:google_only
diff --git a/python/pb_unit_tests/descriptor_test_wrapper.py b/python/pb_unit_tests/descriptor_test_wrapper.py
index 0dcaa76..06f01a6 100644
--- a/python/pb_unit_tests/descriptor_test_wrapper.py
+++ b/python/pb_unit_tests/descriptor_test_wrapper.py
@@ -23,24 +23,24 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import descriptor_test
+from google.protobuf.internal.descriptor_test import *
 import unittest
 
 # Our behavior here matches pure-Python, which does not allow
 # foo.enum_values_by_name.get([]).  We reject it because we return a true
 # dict (like pure Python), which does not allow hashing by a list.
-descriptor_test.GeneratedDescriptorTest.testDescriptor.__unittest_expecting_failure__ = True
+GeneratedDescriptorTest.testDescriptor.__unittest_expecting_failure__ = True
 
 # These fail because they attempt to add fields with conflicting JSON names.
 # We don't want to support this going forward.
-descriptor_test.MakeDescriptorTest.testCamelcaseName.__unittest_expecting_failure__ = True
-descriptor_test.MakeDescriptorTest.testJsonName.__unittest_expecting_failure__ = True
+MakeDescriptorTest.testCamelcaseName.__unittest_expecting_failure__ = True
+MakeDescriptorTest.testJsonName.__unittest_expecting_failure__ = True
 
 # We pass this test, but the error message is slightly different.
 # Our error message is better.
-descriptor_test.NewDescriptorTest.testImmutableCppDescriptor.__unittest_expecting_failure__ = True
+NewDescriptorTest.testImmutableCppDescriptor.__unittest_expecting_failure__ = True
 
-descriptor_test.DescriptorTest.testGetDebugString.__unittest_expecting_failure__ = True
+DescriptorTest.testGetDebugString.__unittest_expecting_failure__ = True
 
 if __name__ == '__main__':
-  unittest.main(module=descriptor_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/generator_test_wrapper.py b/python/pb_unit_tests/generator_test_wrapper.py
index c0fb964..8eed165 100644
--- a/python/pb_unit_tests/generator_test_wrapper.py
+++ b/python/pb_unit_tests/generator_test_wrapper.py
@@ -23,8 +23,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import generator_test
+from google.protobuf.internal.generator_test import *
 import unittest
 
 if __name__ == '__main__':
-  unittest.main(module=generator_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/json_format_test_wrapper.py b/python/pb_unit_tests/json_format_test_wrapper.py
index 5e9e69d..876e44d 100644
--- a/python/pb_unit_tests/json_format_test_wrapper.py
+++ b/python/pb_unit_tests/json_format_test_wrapper.py
@@ -23,8 +23,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import json_format_test
+from google.protobuf.internal.json_format_test import *
 import unittest
 
 if __name__ == '__main__':
-  unittest.main(module=json_format_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/keywords_test_wrapper.py b/python/pb_unit_tests/keywords_test_wrapper.py
index 1863b88..54034fe 100644
--- a/python/pb_unit_tests/keywords_test_wrapper.py
+++ b/python/pb_unit_tests/keywords_test_wrapper.py
@@ -23,8 +23,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import keywords_test
+from google.protobuf.internal.keywords_test import *
 import unittest
 
 if __name__ == '__main__':
-  unittest.main(module=keywords_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/message_factory_test_wrapper.py b/python/pb_unit_tests/message_factory_test_wrapper.py
index ad000a5..8318dcd 100644
--- a/python/pb_unit_tests/message_factory_test_wrapper.py
+++ b/python/pb_unit_tests/message_factory_test_wrapper.py
@@ -23,15 +23,15 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import message_factory_test
+from google.protobuf.internal.message_factory_test import *
 import unittest
 
-message_factory_test.MessageFactoryTest.testCreatePrototypeOverride.__unittest_expecting_failure__ = True
-message_factory_test.MessageFactoryTest.testDuplicateExtensionNumber.__unittest_expecting_failure__ = True
-message_factory_test.MessageFactoryTest.testGetMessages.__unittest_expecting_failure__ = True
-message_factory_test.MessageFactoryTest.testGetPrototype.__unittest_expecting_failure__ = True
-if hasattr(message_factory_test.MessageFactoryTest, 'testExtensionValueInDifferentFile'):
-  message_factory_test.MessageFactoryTest.testExtensionValueInDifferentFile.__unittest_expecting_failure__ = True
+MessageFactoryTest.testCreatePrototypeOverride.__unittest_expecting_failure__ = True
+MessageFactoryTest.testDuplicateExtensionNumber.__unittest_expecting_failure__ = True
+MessageFactoryTest.testGetMessages.__unittest_expecting_failure__ = True
+MessageFactoryTest.testGetPrototype.__unittest_expecting_failure__ = True
+if hasattr(MessageFactoryTest, 'testExtensionValueInDifferentFile'):
+  MessageFactoryTest.testExtensionValueInDifferentFile.__unittest_expecting_failure__ = True
 
 if __name__ == '__main__':
-  unittest.main(module=message_factory_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/message_test_wrapper.py b/python/pb_unit_tests/message_test_wrapper.py
index e7a3749..37d8b15 100644
--- a/python/pb_unit_tests/message_test_wrapper.py
+++ b/python/pb_unit_tests/message_test_wrapper.py
@@ -23,35 +23,35 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import message_test
+from google.protobuf.internal.message_test import *
 import unittest
 
 # We don't want to support extending repeated fields with nothing; this behavior
 # is marked for deprecation in the existing library.
-message_test.MessageTest.testExtendFloatWithNothing_proto2.__unittest_expecting_failure__ = True
-message_test.MessageTest.testExtendFloatWithNothing_proto3.__unittest_expecting_failure__ = True
-message_test.MessageTest.testExtendInt32WithNothing_proto2.__unittest_expecting_failure__ = True
-message_test.MessageTest.testExtendInt32WithNothing_proto3.__unittest_expecting_failure__ = True
-message_test.MessageTest.testExtendStringWithNothing_proto2.__unittest_expecting_failure__ = True
-message_test.MessageTest.testExtendStringWithNothing_proto3.__unittest_expecting_failure__ = True
+MessageTest.testExtendFloatWithNothing_proto2.__unittest_expecting_failure__ = True
+MessageTest.testExtendFloatWithNothing_proto3.__unittest_expecting_failure__ = True
+MessageTest.testExtendInt32WithNothing_proto2.__unittest_expecting_failure__ = True
+MessageTest.testExtendInt32WithNothing_proto3.__unittest_expecting_failure__ = True
+MessageTest.testExtendStringWithNothing_proto2.__unittest_expecting_failure__ = True
+MessageTest.testExtendStringWithNothing_proto3.__unittest_expecting_failure__ = True
 
 # Python/C++ customizes the C++ TextFormat to always print trailing ".0" for
 # floats. upb doesn't do this, it matches C++ TextFormat.
-message_test.MessageTest.testFloatPrinting_proto2.__unittest_expecting_failure__ = True
-message_test.MessageTest.testFloatPrinting_proto3.__unittest_expecting_failure__ = True
+MessageTest.testFloatPrinting_proto2.__unittest_expecting_failure__ = True
+MessageTest.testFloatPrinting_proto3.__unittest_expecting_failure__ = True
 
 # For these tests we are throwing the correct error, only the text of the error
 # message is a mismatch.  For technical reasons around the limited API, matching
 # the existing error message exactly is not feasible.
-message_test.Proto3Test.testCopyFromBadType.__unittest_expecting_failure__ = True
-message_test.Proto3Test.testMergeFromBadType.__unittest_expecting_failure__ = True
+Proto3Test.testCopyFromBadType.__unittest_expecting_failure__ = True
+Proto3Test.testMergeFromBadType.__unittest_expecting_failure__ = True
 
-message_test.MessageTest.testPickleRepeatedScalarContainer_proto2.__unittest_expecting_failure__ = True
-message_test.MessageTest.testPickleRepeatedScalarContainer_proto3.__unittest_expecting_failure__ = True
-message_test.Proto2Test.testPythonicInit.__unittest_expecting_failure__ = True
-message_test.Proto2Test.test_documentation.__unittest_expecting_failure__ = True
-message_test.Proto3Test.testModifyMapEntryWhileIterating.__unittest_expecting_failure__ = True
-message_test.Proto3Test.testProto3Optional.__unittest_expecting_failure__ = True
+MessageTest.testPickleRepeatedScalarContainer_proto2.__unittest_expecting_failure__ = True
+MessageTest.testPickleRepeatedScalarContainer_proto3.__unittest_expecting_failure__ = True
+Proto2Test.testPythonicInit.__unittest_expecting_failure__ = True
+Proto2Test.test_documentation.__unittest_expecting_failure__ = True
+Proto3Test.testModifyMapEntryWhileIterating.__unittest_expecting_failure__ = True
+Proto3Test.testProto3Optional.__unittest_expecting_failure__ = True
 
 if __name__ == '__main__':
-  unittest.main(module=message_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/proto_builder_test_wrapper.py b/python/pb_unit_tests/proto_builder_test_wrapper.py
index d189f49..0b6a25a 100644
--- a/python/pb_unit_tests/proto_builder_test_wrapper.py
+++ b/python/pb_unit_tests/proto_builder_test_wrapper.py
@@ -23,10 +23,10 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import proto_builder_test
+from google.protobuf.internal.proto_builder_test import *
 import unittest
 
-proto_builder_test.ProtoBuilderTest.testMakeLargeProtoClass.__unittest_expecting_failure__ = True
+ProtoBuilderTest.testMakeLargeProtoClass.__unittest_expecting_failure__ = True
 
 if __name__ == '__main__':
-  unittest.main(module=proto_builder_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/pyproto_test_wrapper.bzl b/python/pb_unit_tests/pyproto_test_wrapper.bzl
index 3d66f76..aa57377 100644
--- a/python/pb_unit_tests/pyproto_test_wrapper.bzl
+++ b/python/pb_unit_tests/pyproto_test_wrapper.bzl
@@ -12,6 +12,7 @@
             "//python:_message",
             "@com_google_protobuf//:python_common_test_protos",
             "@com_google_protobuf//:python_specific_test_protos",
+            "@com_google_protobuf//:python_test_srcs",
             "@com_google_protobuf//:python_srcs",
         ],
     )
diff --git a/python/pb_unit_tests/reflection_test_wrapper.py b/python/pb_unit_tests/reflection_test_wrapper.py
index 35cc8ec..bda5846 100644
--- a/python/pb_unit_tests/reflection_test_wrapper.py
+++ b/python/pb_unit_tests/reflection_test_wrapper.py
@@ -23,25 +23,25 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import reflection_test
+from google.protobuf.internal.reflection_test import *
 import unittest
 
 # These tests depend on a specific iteration order for extensions, which is not
 # reasonable to guarantee.
-reflection_test.Proto2ReflectionTest.testExtensionIter.__unittest_expecting_failure__ = True
+Proto2ReflectionTest.testExtensionIter.__unittest_expecting_failure__ = True
 
 # These tests depend on a specific serialization order for extensions, which is
 # not reasonable to guarantee.
-reflection_test.SerializationTest.testCanonicalSerializationOrder.__unittest_expecting_failure__ = True
-reflection_test.SerializationTest.testCanonicalSerializationOrderSameAsCpp.__unittest_expecting_failure__ = True
+SerializationTest.testCanonicalSerializationOrder.__unittest_expecting_failure__ = True
+SerializationTest.testCanonicalSerializationOrderSameAsCpp.__unittest_expecting_failure__ = True
 
 # This test relies on the internal implementation using Python descriptors.
 # This is an implementation detail that users should not depend on.
-reflection_test.SerializationTest.testFieldDataDescriptor.__unittest_expecting_failure__ = True
+SerializationTest.testFieldDataDescriptor.__unittest_expecting_failure__ = True
 
-reflection_test.ReflectionTest.testDeepCopy_proto2.__unittest_expecting_failure__ = True
-reflection_test.ReflectionTest.testDeepCopy_proto3.__unittest_expecting_failure__ = True
-reflection_test.SerializationTest.testFieldProperties.__unittest_expecting_failure__ = True
+ReflectionTest.testDeepCopy_proto2.__unittest_expecting_failure__ = True
+ReflectionTest.testDeepCopy_proto3.__unittest_expecting_failure__ = True
+SerializationTest.testFieldProperties.__unittest_expecting_failure__ = True
 
 if __name__ == '__main__':
-  unittest.main(module=reflection_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/service_reflection_test_wrapper.py b/python/pb_unit_tests/service_reflection_test_wrapper.py
index 089779a..0006923 100644
--- a/python/pb_unit_tests/service_reflection_test_wrapper.py
+++ b/python/pb_unit_tests/service_reflection_test_wrapper.py
@@ -23,8 +23,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import service_reflection_test
+from google.protobuf.internal.service_reflection_test import *
 import unittest
 
 if __name__ == '__main__':
-  unittest.main(module=service_reflection_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/symbol_database_test_wrapper.py b/python/pb_unit_tests/symbol_database_test_wrapper.py
index 3a5bfb1..760548b 100644
--- a/python/pb_unit_tests/symbol_database_test_wrapper.py
+++ b/python/pb_unit_tests/symbol_database_test_wrapper.py
@@ -23,8 +23,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import symbol_database_test
+from google.protobuf.internal.symbol_database_test import *
 import unittest
 
 if __name__ == '__main__':
-  unittest.main(module=symbol_database_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/text_encoding_test_wrapper.py b/python/pb_unit_tests/text_encoding_test_wrapper.py
index 3c567bc..1354274 100644
--- a/python/pb_unit_tests/text_encoding_test_wrapper.py
+++ b/python/pb_unit_tests/text_encoding_test_wrapper.py
@@ -23,8 +23,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import text_encoding_test
+from google.protobuf.internal.text_encoding_test import *
 import unittest
 
 if __name__ == '__main__':
-  unittest.main(module=text_encoding_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/text_format_test_wrapper.py b/python/pb_unit_tests/text_format_test_wrapper.py
index bb9f6d8..71b3d4e 100644
--- a/python/pb_unit_tests/text_format_test_wrapper.py
+++ b/python/pb_unit_tests/text_format_test_wrapper.py
@@ -23,8 +23,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import text_format_test
+from google.protobuf.internal.text_format_test import *
 import unittest
 
 if __name__ == '__main__':
-  unittest.main(module=text_format_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/unknown_fields_test_wrapper.py b/python/pb_unit_tests/unknown_fields_test_wrapper.py
index 51710c6..902394f 100644
--- a/python/pb_unit_tests/unknown_fields_test_wrapper.py
+++ b/python/pb_unit_tests/unknown_fields_test_wrapper.py
@@ -23,8 +23,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import unknown_fields_test
+from google.protobuf.internal.unknown_fields_test import *
 import unittest
 
 if __name__ == '__main__':
-  unittest.main(module=unknown_fields_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/well_known_types_test_wrapper.py b/python/pb_unit_tests/well_known_types_test_wrapper.py
index 6ded8d4..6662457 100644
--- a/python/pb_unit_tests/well_known_types_test_wrapper.py
+++ b/python/pb_unit_tests/well_known_types_test_wrapper.py
@@ -23,8 +23,14 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import well_known_types_test
+from google.protobuf.internal.well_known_types_test import *
+import os
 import unittest
 
+if os.name == 'nt':
+  # TODO(b/231335093): This currently trigggers an assertion failure on Windows
+  # for unknown reasons.
+  StructTest.__unittest_skip__ = True
+
 if __name__ == '__main__':
-  unittest.main(module=well_known_types_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/pb_unit_tests/wire_format_test_wrapper.py b/python/pb_unit_tests/wire_format_test_wrapper.py
index c2f6c0a..f56474b 100644
--- a/python/pb_unit_tests/wire_format_test_wrapper.py
+++ b/python/pb_unit_tests/wire_format_test_wrapper.py
@@ -23,8 +23,8 @@
 # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
 # SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
-from google.protobuf.internal import wire_format_test
+from google.protobuf.internal.wire_format_test import *
 import unittest
 
 if __name__ == '__main__':
-  unittest.main(module=wire_format_test, verbosity=2)
+  unittest.main(verbosity=2)
diff --git a/python/unknown_fields.c b/python/unknown_fields.c
index 0552188..f021034 100644
--- a/python/unknown_fields.c
+++ b/python/unknown_fields.c
@@ -58,7 +58,7 @@
   PyUpb_Dealloc(self);
 }
 
-PyUpb_UnknownFieldSet* PyUpb_UnknownFieldSet_NewBare() {
+PyUpb_UnknownFieldSet* PyUpb_UnknownFieldSet_NewBare(void) {
   PyUpb_ModuleState* s = PyUpb_ModuleState_Get();
   PyUpb_UnknownFieldSet* self =
       (void*)PyType_GenericAlloc(s->unknown_fields_type, 0);
diff --git a/upb/util/def_to_proto.c b/upb/util/def_to_proto.c
index 6195336..b392327 100644
--- a/upb/util/def_to_proto.c
+++ b/upb/util/def_to_proto.c
@@ -28,6 +28,7 @@
 #include "upb/util/def_to_proto.h"
 
 #include <inttypes.h>
+#include <math.h>
 #include <setjmp.h>
 #include <stdio.h>
 
@@ -124,6 +125,19 @@
 static upb_StringView default_string(upb_ToProto_Context* ctx,
                                      const upb_FieldDef* f) {
   upb_MessageValue d = upb_FieldDef_Default(f);
+  upb_CType type = upb_FieldDef_CType(f);
+
+  if (type == kUpb_CType_Float || type == kUpb_CType_Double) {
+    double val = type == kUpb_CType_Float ? d.float_val : d.double_val;
+    if (val == INFINITY) {
+      return strviewdup(ctx, "inf");
+    } else if (val == -INFINITY) {
+      return strviewdup(ctx, "-inf");
+    } else if (val != val) {
+      return strviewdup(ctx, "nan");
+    }
+  }
+
   switch (upb_FieldDef_CType(f)) {
     case kUpb_CType_Bool:
       return strviewdup(ctx, d.bool_val ? "true" : "false");