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
pull/19202/head
Jie Luo 2 weeks ago committed by Copybara-Service
parent 0df15fcbb0
commit 610702ed18
  1. 17
      csharp/src/Google.Protobuf/Reflection/FeatureSetDescriptor.g.cs
  2. 26
      python/google/protobuf/descriptor_database.py
  3. 27
      python/google/protobuf/internal/descriptor_database_test.py

@ -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";
}

@ -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:

@ -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(

Loading…
Cancel
Save