From 610702ed18d4323e44b9741102ed90377243470e Mon Sep 17 00:00:00 2001 From: Jie Luo Date: Mon, 11 Nov 2024 15:00:18 -0800 Subject: [PATCH] Fix a Python bug: when package is empty, DescriptorDatabase FindFileContainingSymbol method will able to find symbol names not start with '.' The old behavior requires a prefix of '.' for empty packages like '.Foo'. To not break old behaviors, both 'Foo' and '.Foo' will be supported. The support for leading '.' will be removed around 2026 Jan. For example: db.FindFileContainingSymbol('Foo') db.FindFileContainingSymbol('.Foo') # with a warning will have same result PiperOrigin-RevId: 695493356 --- .../Reflection/FeatureSetDescriptor.g.cs | 17 ------------ python/google/protobuf/descriptor_database.py | 26 +++++++++++++++--- .../internal/descriptor_database_test.py | 27 +++++++++++++++++-- 3 files changed, 47 insertions(+), 23 deletions(-) delete mode 100644 csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs diff --git a/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs b/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs deleted file mode 100644 index 208ce1fcb6..0000000000 --- a/csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs +++ /dev/null @@ -1,17 +0,0 @@ -#region Copyright notice and license -// 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 -#endregion - -namespace Google.Protobuf.Reflection; - -internal sealed partial class FeatureSetDescriptor -{ - // Canonical serialized form of the edition defaults, generated by embed_edition_defaults. - private const string DefaultsBase64 = - "ChMYhAciACoMCAEQAhgCIAMoATACChMY5wciACoMCAIQARgBIAIoATABChMY6AciDAgBEAEYASACKAEwASoAIOYHKOgH"; -} diff --git a/python/google/protobuf/descriptor_database.py b/python/google/protobuf/descriptor_database.py index 46a893e316..eeb8599372 100644 --- a/python/google/protobuf/descriptor_database.py +++ b/python/google/protobuf/descriptor_database.py @@ -52,14 +52,24 @@ class DescriptorDatabase(object): for name in _ExtractSymbols(message, package): self._AddSymbol(name, file_desc_proto) for enum in file_desc_proto.enum_type: - self._AddSymbol(('.'.join((package, enum.name))), file_desc_proto) + self._AddSymbol( + ('.'.join((package, enum.name)) if package else enum.name), + file_desc_proto, + ) for enum_value in enum.value: self._file_desc_protos_by_symbol[ - '.'.join((package, enum_value.name))] = file_desc_proto + '.'.join((package, enum_value.name)) if package else enum_value.name + ] = file_desc_proto for extension in file_desc_proto.extension: - self._AddSymbol(('.'.join((package, extension.name))), file_desc_proto) + self._AddSymbol( + ('.'.join((package, extension.name)) if package else extension.name), + file_desc_proto, + ) for service in file_desc_proto.service: - self._AddSymbol(('.'.join((package, service.name))), file_desc_proto) + self._AddSymbol( + ('.'.join((package, service.name)) if package else service.name), + file_desc_proto, + ) def FindFileByName(self, name): """Finds the file descriptor proto by file name. @@ -102,6 +112,14 @@ class DescriptorDatabase(object): Raises: KeyError if no file contains the specified symbol. """ + if symbol.count('.') == 1 and symbol[0] == '.': + symbol = symbol.lstrip('.') + warnings.warn( + 'Please remove the leading "." when ' + 'FindFileContainingSymbol, this will turn to error ' + 'in 2026 Jan.', + RuntimeWarning, + ) try: return self._file_desc_protos_by_symbol[symbol] except KeyError: diff --git a/python/google/protobuf/internal/descriptor_database_test.py b/python/google/protobuf/internal/descriptor_database_test.py index 77afa0bedb..89e401ea84 100644 --- a/python/google/protobuf/internal/descriptor_database_test.py +++ b/python/google/protobuf/internal/descriptor_database_test.py @@ -56,8 +56,26 @@ class DescriptorDatabaseTest(unittest.TestCase): 'google.protobuf.python.internal.Factory2Enum.FACTORY_2_VALUE_0')) self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( 'google.protobuf.python.internal.FACTORY_2_VALUE_0')) - self.assertEqual(file_desc_proto2, db.FindFileContainingSymbol( - '.NO_PACKAGE_VALUE_0')) + self.assertEqual( + file_desc_proto2, db.FindFileContainingSymbol('NO_PACKAGE_VALUE_0') + ) + self.assertEqual( + file_desc_proto2, db.FindFileContainingSymbol('.NO_PACKAGE_VALUE_0') + ) + self.assertEqual( + file_desc_proto2, db.FindFileContainingSymbol('NoPackageMessage') + ) + self.assertEqual( + file_desc_proto2, db.FindFileContainingSymbol('.NoPackageMessage') + ) + self.assertEqual( + file_desc_proto2, + db.FindFileContainingSymbol('NoPackageEnum'), + ) + self.assertEqual( + file_desc_proto2, + db.FindFileContainingSymbol('.NoPackageEnum'), + ) # Can find top level extension. self.assertEqual(file_desc_proto, db.FindFileContainingSymbol( 'google.protobuf.python.internal.another_field')) @@ -80,6 +98,11 @@ class DescriptorDatabaseTest(unittest.TestCase): with self.assertRaisesRegex(KeyError, r'\'protobuf_unittest\.NoneMessage\''): db.FindFileContainingSymbol('protobuf_unittest.NoneMessage') + with self.assertRaises(KeyError): + db.FindFileContainingSymbol( + '.google.protobuf.python.internal.FACTORY_2_VALUE_0' + ) + def testConflictRegister(self): db = descriptor_database.DescriptorDatabase() unittest_fd = descriptor_pb2.FileDescriptorProto.FromString(