Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 10 additions & 4 deletions java/core/src/main/java/com/google/protobuf/Descriptors.java
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,12 @@ public boolean isRequired() {
== DescriptorProtos.FeatureSet.FieldPresence.LEGACY_REQUIRED;
}

/** Is this field declared optional? */
/**
* Is this field declared optional? *
*
* <p>This method is deprecated. Use !isRequired() && !isRepeated() instead.
*/
@Deprecated
public boolean isOptional() {
return proto.getLabel() == FieldDescriptorProto.Label.LABEL_OPTIONAL
&& getFeatures().getFieldPresence()
Expand Down Expand Up @@ -1450,7 +1455,8 @@ public OneofDescriptor getRealContainingOneof() {
boolean hasOptionalKeyword() {
return isProto3Optional
|| (file.getEdition() == Edition.EDITION_PROTO2
&& isOptional()
&& !isRequired()
&& !isRepeated()
&& getContainingOneof() == null);
}

Expand Down Expand Up @@ -1937,9 +1943,9 @@ void validateFeatures() throws DescriptorValidationException {
if (containingType != null
&& containingType.toProto().getOptions().getMessageSetWireFormat()) {
if (isExtension()) {
if (!isOptional() || getType() != Type.MESSAGE) {
if (isRequired() || isRepeated() || getType() != Type.MESSAGE) {
throw new DescriptorValidationException(
this, "Extensions of MessageSets must be optional messages.");
this, "Extensions of MessageSets may not be required or repeated messages.");
}
}
}
Expand Down
1 change: 1 addition & 0 deletions python/BUILD.bazel
Original file line number Diff line number Diff line change
Expand Up @@ -160,5 +160,6 @@ py_extension(
"//upb/hash",
"//upb/util:def_to_proto",
"//upb/util:required_fields",
"@abseil-cpp//absl/base:core_headers",
],
)
18 changes: 18 additions & 0 deletions python/descriptor.c
Original file line number Diff line number Diff line change
Expand Up @@ -1056,9 +1056,23 @@ static PyObject* PyUpb_FieldDescriptor_GetCppType(PyUpb_DescriptorBase* self,

static PyObject* PyUpb_FieldDescriptor_GetLabel(PyUpb_DescriptorBase* self,
void* closure) {
PyErr_WarnEx(
PyExc_DeprecationWarning,
"label() is deprecated. Use is_required() or is_repeated() instead.", 2);

return PyLong_FromLong(upb_FieldDef_Label(self->def));
}

static PyObject* PyUpb_FieldDescriptor_IsRequired(PyUpb_DescriptorBase* self,
void* closure) {
return PyBool_FromLong(upb_FieldDef_IsRequired(self->def));
}

static PyObject* PyUpb_FieldDescriptor_IsRepeated(PyUpb_DescriptorBase* self,
void* closure) {
return PyBool_FromLong(upb_FieldDef_IsRepeated(self->def));
}

static PyObject* PyUpb_FieldDescriptor_GetIsExtension(
PyUpb_DescriptorBase* self, void* closure) {
return PyBool_FromLong(upb_FieldDef_IsExtension(self->def));
Expand Down Expand Up @@ -1165,6 +1179,10 @@ static PyGetSetDef PyUpb_FieldDescriptor_Getters[] = {
{"type", (getter)PyUpb_FieldDescriptor_GetType, NULL, "Type"},
{"cpp_type", (getter)PyUpb_FieldDescriptor_GetCppType, NULL, "C++ Type"},
{"label", (getter)PyUpb_FieldDescriptor_GetLabel, NULL, "Label"},
{"is_required", (getter)PyUpb_FieldDescriptor_IsRequired, NULL,
"Is Required"},
{"is_repeated", (getter)PyUpb_FieldDescriptor_IsRepeated, NULL,
"Is Repeated"},
{"number", (getter)PyUpb_FieldDescriptor_GetNumber, NULL, "Number"},
{"index", (getter)PyUpb_FieldDescriptor_GetIndex, NULL, "Index"},
{"default_value", (getter)PyUpb_FieldDescriptor_GetDefaultValue, NULL,
Expand Down
24 changes: 22 additions & 2 deletions python/google/protobuf/descriptor.py
Original file line number Diff line number Diff line change
Expand Up @@ -721,13 +721,33 @@ def type(self, val):

@property
def label(self):
warnings.warn(
'Call to deprecated label property. Use is_required() or is_repeated()'
' methods instead.',
category=DeprecationWarning,
stacklevel=2,
)

if (
self._GetFeatures().field_presence
== _FEATURESET_FIELD_PRESENCE_LEGACY_REQUIRED
):
return FieldDescriptor.LABEL_REQUIRED
return self._label

@property
def is_required(self):
"""Returns if the field is required."""
return (
self._GetFeatures().field_presence
== _FEATURESET_FIELD_PRESENCE_LEGACY_REQUIRED
)

@property
def is_repeated(self):
"""Returns if the field is repeated."""
return self._label == FieldDescriptor.LABEL_REPEATED

@property
def camelcase_name(self):
"""Camelcase name of this field.
Expand All @@ -746,7 +766,7 @@ def has_presence(self):
Raises:
RuntimeError: singular field that is not linked with message nor file.
"""
if self.label == FieldDescriptor.LABEL_REPEATED:
if self.is_repeated:
return False
if (
self.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE
Expand All @@ -763,7 +783,7 @@ def has_presence(self):
@property
def is_packed(self):
"""Returns if the field is packed."""
if self.label != FieldDescriptor.LABEL_REPEATED:
if not self.is_repeated:
return False
field_type = self.type
if (field_type == FieldDescriptor.TYPE_STRING or
Expand Down
10 changes: 6 additions & 4 deletions python/google/protobuf/internal/descriptor_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -588,12 +588,16 @@ def testDefault(self):
message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
field = message_descriptor.fields_by_name['repeated_int32']
self.assertEqual(field.default_value, [])
self.assertTrue(field.is_repeated)
field = message_descriptor.fields_by_name['repeated_nested_message']
self.assertEqual(field.default_value, [])
self.assertTrue(field.is_repeated)
field = message_descriptor.fields_by_name['optionalgroup']
self.assertEqual(field.default_value, None)
self.assertFalse(field.is_required)
field = message_descriptor.fields_by_name['optional_nested_message']
self.assertEqual(field.default_value, None)
self.assertFalse(field.is_required)


class NewDescriptorTest(DescriptorTest):
Expand Down Expand Up @@ -650,6 +654,7 @@ def CheckFieldDescriptor(self, field_descriptor):
self.assertIn(field_descriptor, {field_descriptor: None})
self.assertEqual(None, field_descriptor.extension_scope)
self.assertEqual(None, field_descriptor.enum_type)
self.assertFalse(field_descriptor.is_required)
self.assertTrue(field_descriptor.has_presence)
if api_implementation.Type() == 'cpp':
# For test coverage only
Expand Down Expand Up @@ -1288,10 +1293,7 @@ def testFeaturesStripped(self):

def testLegacyRequiredTransform(self):
desc = unittest_legacy_features_pb2.TestEditionsMessage.DESCRIPTOR
self.assertEqual(
desc.fields_by_name['required_field'].label,
descriptor.FieldDescriptor.LABEL_REQUIRED,
)
self.assertTrue(desc.fields_by_name['required_field'].is_required)

def testLegacyGroupTransform(self):
desc = unittest_legacy_features_pb2.TestEditionsMessage.DESCRIPTOR
Expand Down
32 changes: 16 additions & 16 deletions python/google/protobuf/internal/python_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,7 +269,6 @@ def _IsMessageMapField(field):
return value_type.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE

def _AttachFieldHelpers(cls, field_descriptor):
is_repeated = field_descriptor.label == _FieldDescriptor.LABEL_REPEATED
field_descriptor._default_constructor = _DefaultValueConstructorForField(
field_descriptor
)
Expand All @@ -282,7 +281,9 @@ def AddFieldByTag(wiretype, is_packed):
type_checkers.FIELD_TYPE_TO_WIRE_TYPE[field_descriptor.type], False
)

if is_repeated and wire_format.IsTypePackable(field_descriptor.type):
if field_descriptor.is_repeated and wire_format.IsTypePackable(
field_descriptor.type
):
# To support wire compatibility of adding packed = true, add a decoder for
# packed values regardless of the field's options.
AddFieldByTag(wire_format.WIRETYPE_LENGTH_DELIMITED, True)
Expand All @@ -291,7 +292,7 @@ def AddFieldByTag(wiretype, is_packed):
def _MaybeAddEncoder(cls, field_descriptor):
if hasattr(field_descriptor, '_encoder'):
return
is_repeated = (field_descriptor.label == _FieldDescriptor.LABEL_REPEATED)
is_repeated = field_descriptor.is_repeated
is_map_entry = _IsMapField(field_descriptor)
is_packed = field_descriptor.is_packed

Expand All @@ -316,7 +317,7 @@ def _MaybeAddDecoder(cls, field_descriptor):
if hasattr(field_descriptor, '_decoders'):
return

is_repeated = field_descriptor.label == _FieldDescriptor.LABEL_REPEATED
is_repeated = field_descriptor.is_repeated
is_map_entry = _IsMapField(field_descriptor)
helper_decoders = {}

Expand Down Expand Up @@ -387,7 +388,7 @@ def _AddEnumValues(descriptor, cls):


def _GetInitializeDefaultForMap(field):
if field.label != _FieldDescriptor.LABEL_REPEATED:
if not field.is_repeated:
raise ValueError('map_entry set on non-repeated field %s' % (
field.name))
fields_by_name = field.message_type.fields_by_name
Expand Down Expand Up @@ -425,7 +426,7 @@ def _DefaultValueConstructorForField(field):
if _IsMapField(field):
return _GetInitializeDefaultForMap(field)

if field.label == _FieldDescriptor.LABEL_REPEATED:
if field.is_repeated:
if field.has_default_value and field.default_value != []:
raise ValueError('Repeated field default value not empty list: %s' % (
field.default_value))
Expand Down Expand Up @@ -517,7 +518,7 @@ def init(self, **kwargs):
if field_value is None:
# field=None is the same as no field at all.
continue
if field.label == _FieldDescriptor.LABEL_REPEATED:
if field.is_repeated:
field_copy = field._default_constructor(self)
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE: # Composite
if _IsMapField(field):
Expand Down Expand Up @@ -636,7 +637,7 @@ def _AddPropertiesForField(field, cls):
constant_name = field.name.upper() + '_FIELD_NUMBER'
setattr(cls, constant_name, field.number)

if field.label == _FieldDescriptor.LABEL_REPEATED:
if field.is_repeated:
_AddPropertiesForRepeatedField(field, cls)
elif field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
_AddPropertiesForNonRepeatedCompositeField(field, cls)
Expand Down Expand Up @@ -838,7 +839,7 @@ def _IsPresent(item):
"""Given a (FieldDescriptor, value) tuple from _fields, return true if the
value should be included in the list returned by ListFields()."""

if item[0].label == _FieldDescriptor.LABEL_REPEATED:
if item[0].is_repeated:
return bool(item[1])
elif item[0].cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
return item[1]._is_present_in_parent
Expand All @@ -862,7 +863,7 @@ def _AddHasFieldMethod(message_descriptor, cls):

hassable_fields = {}
for field in message_descriptor.fields:
if field.label == _FieldDescriptor.LABEL_REPEATED:
if field.is_repeated:
continue
# For proto3, only submessages and fields inside a oneof have presence.
if not field.has_presence:
Expand Down Expand Up @@ -950,7 +951,7 @@ def _AddHasExtensionMethod(cls):
"""Helper for _AddMessageMethods()."""
def HasExtension(self, field_descriptor):
extension_dict._VerifyExtensionHandle(self, field_descriptor)
if field_descriptor.label == _FieldDescriptor.LABEL_REPEATED:
if field_descriptor.is_repeated:
raise KeyError('"%s" is repeated.' % field_descriptor.full_name)

if field_descriptor.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
Expand Down Expand Up @@ -1284,7 +1285,7 @@ def IsInitialized(self, errors=None):

for field, value in list(self._fields.items()): # dict can change size!
if field.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
if field.label == _FieldDescriptor.LABEL_REPEATED:
if field.is_repeated:
if (field.message_type._is_map_entry):
continue
for element in value:
Expand Down Expand Up @@ -1332,7 +1333,7 @@ def FindInitializationErrors(self):
else:
# ScalarMaps can't have any initialization errors.
pass
elif field.label == _FieldDescriptor.LABEL_REPEATED:
elif field.is_repeated:
for i in range(len(value)):
element = value[i]
prefix = '%s[%d].' % (name, i)
Expand All @@ -1357,7 +1358,6 @@ def _FullyQualifiedClassName(klass):


def _AddMergeFromMethod(cls):
LABEL_REPEATED = _FieldDescriptor.LABEL_REPEATED
CPPTYPE_MESSAGE = _FieldDescriptor.CPPTYPE_MESSAGE

def MergeFrom(self, msg):
Expand All @@ -1373,7 +1373,7 @@ def MergeFrom(self, msg):
fields = self._fields

for field, value in msg._fields.items():
if field.label == LABEL_REPEATED:
if field.is_repeated:
field_value = fields.get(field)
if field_value is None:
# Construct a new object to represent this field.
Expand Down Expand Up @@ -1442,7 +1442,7 @@ def _DiscardUnknownFields(self):
if _IsMessageMapField(field):
for key in value:
value[key].DiscardUnknownFields()
elif field.label == _FieldDescriptor.LABEL_REPEATED:
elif field.is_repeated:
for sub_message in value:
sub_message.DiscardUnknownFields()
else:
Expand Down
Loading
Loading