Skip to content
Draft
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
44 changes: 15 additions & 29 deletions python/google/protobuf/internal/text_format_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,56 +342,42 @@ def testPrintRawUtf8String(self, message_module):
parsed_message.repeated_string[0]))

def testPrintFloatFormat(self, message_module):
# Check that float_format argument is passed to sub-message formatting.
message = message_module.NestedTestAllTypes()
message.payload.optional_float = 1.25
# Check rounding at 15 significant digits
message.payload.optional_double = -.000003456789012345678
# Check no decimal point.
message.payload.repeated_float.append(-5642)
# Check no trailing zeros.
message.payload.repeated_double.append(.000078900)
formatted_fields = ['optional_float: 1.25',
'optional_double: -3.45678901234568e-6',
'repeated_float: -5642', 'repeated_double: 7.89e-5']
text_message = text_format.MessageToString(message, float_format='.15g')
formatted_fields = [
'optional_float: 1.25',
'optional_double: -3.456789012345678e-6',
'repeated_float: -5642',
'repeated_double: 7.89e-5',
]
text_message = text_format.MessageToString(message)
self.CompareToGoldenText(
self.RemoveRedundantZeros(text_message),
'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format(
*formatted_fields))
# as_one_line=True is a separate code branch where float_format is passed.
text_message = text_format.MessageToString(message,
as_one_line=True,
float_format='.15g')
self.CompareToGoldenText(
self.RemoveRedundantZeros(text_message),
'payload {{ {0} {1} {2} {3} }}'.format(*formatted_fields))

# 32-bit 1.2 is noisy when extended to 64-bit:
# >>> struct.unpack('f', struct.pack('f', 1.2))[0]
# 1.2000000476837158
message.payload.optional_float = 1.2
formatted_fields = ['optional_float: 1.2',
'optional_double: -3.45678901234568e-6',
'repeated_float: -5642', 'repeated_double: 7.89e-5']
text_message = text_format.MessageToString(message, float_format='.7g',
double_format='.15g')
self.CompareToGoldenText(
self.RemoveRedundantZeros(text_message),
'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format(
*formatted_fields))

# Test only set float_format affect both float and double fields.
formatted_fields = ['optional_float: 1.2',
'optional_double: -3.456789e-6',
'repeated_float: -5642', 'repeated_double: 7.89e-5']
text_message = text_format.MessageToString(message, float_format='.7g')
formatted_fields = [
'optional_float: 1.2',
'optional_double: -3.456789012345678e-6',
'repeated_float: -5642',
'repeated_double: 7.89e-5',
]
text_message = text_format.MessageToString(message)
self.CompareToGoldenText(
self.RemoveRedundantZeros(text_message),
'payload {{\n {0}\n {1}\n {2}\n {3}\n}}\n'.format(
*formatted_fields))

# Test default float_format will automatic print shortest float.
# Test print shortest float.
message.payload.optional_float = 1.2345678912
message.payload.optional_double = 1.2345678912
formatted_fields = ['optional_float: 1.2345679',
Expand Down
11 changes: 0 additions & 11 deletions python/google/protobuf/proto_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@ def serialize(
use_short_repeated_primitives: bool = False,
pointy_brackets: bool = False,
use_index_order: bool = False,
float_format: Optional[str] = None,
double_format: Optional[str] = None,
use_field_number: bool = False,
descriptor_pool: Optional[DescriptorPool] = None,
indent: int = 0,
Expand All @@ -50,13 +48,6 @@ def serialize(
will be printed at the end of the message and their relative order is
determined by the extension number. By default, use the field number
order.
float_format (str): If set, use this to specify float field formatting (per
the "Format Specification Mini-Language"); otherwise, shortest float that
has same value in wire will be printed. Also affect double field if
double_format is not set but float_format is set.
double_format (str): If set, use this to specify double field formatting
(per the "Format Specification Mini-Language"); if it is not set but
float_format is set, use float_format. Otherwise, use ``str()``
use_field_number: If True, print field numbers instead of names.
descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types.
indent (int): The initial indent level, in terms of spaces, for pretty
Expand All @@ -78,8 +69,6 @@ def serialize(
use_short_repeated_primitives=use_short_repeated_primitives,
pointy_brackets=pointy_brackets,
use_index_order=use_index_order,
float_format=float_format,
double_format=double_format,
use_field_number=use_field_number,
descriptor_pool=descriptor_pool,
indent=indent,
Expand Down
133 changes: 41 additions & 92 deletions python/google/protobuf/text_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -100,8 +100,6 @@ def MessageToString(
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
use_field_number=False,
descriptor_pool=None,
indent=0,
Expand All @@ -110,11 +108,6 @@ def MessageToString(
force_colon=False) -> str:
"""Convert protobuf message to text format.

Double values can be formatted compactly with 15 digits of
precision (which is the most that IEEE 754 "double" can guarantee)
using double_format='.15g'. To ensure that converting to text and back to a
proto will result in an identical value, double_format='.17g' should be used.

Args:
message: The protocol buffers message.
as_utf8: Return unescaped Unicode for non-ASCII characters.
Expand All @@ -127,13 +120,6 @@ def MessageToString(
will be printed at the end of the message and their relative order is
determined by the extension number. By default, use the field number
order.
float_format (str): Deprecated. If set, use this to specify float field
formatting (per the "Format Specification Mini-Language"); otherwise,
shortest float that has same value in wire will be printed. Also affect
double field if double_format is not set but float_format is set.
double_format (str): Deprecated. If set, use this to specify double field
formatting (per the "Format Specification Mini-Language"); if it is not
set but float_format is set, use float_format. Otherwise, use ``str()``
use_field_number: If True, print field numbers instead of names.
descriptor_pool (DescriptorPool): Descriptor pool used to resolve Any types.
indent (int): The initial indent level, in terms of spaces, for pretty
Expand All @@ -150,20 +136,19 @@ def MessageToString(
"""
out = TextWriter(as_utf8)
printer = _Printer(
out,
indent,
as_utf8,
as_one_line,
use_short_repeated_primitives,
pointy_brackets,
use_index_order,
float_format,
double_format,
use_field_number,
descriptor_pool,
message_formatter,
out=out,
indent=indent,
as_utf8=as_utf8,
as_one_line=as_one_line,
use_short_repeated_primitives=use_short_repeated_primitives,
pointy_brackets=pointy_brackets,
use_index_order=use_index_order,
use_field_number=use_field_number,
descriptor_pool=descriptor_pool,
message_formatter=message_formatter,
print_unknown_fields=print_unknown_fields,
force_colon=force_colon)
force_colon=force_colon,
)
printer.PrintMessage(message)
result = out.getvalue()
out.close()
Expand Down Expand Up @@ -225,8 +210,6 @@ def PrintMessage(message,
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
use_field_number=False,
descriptor_pool=None,
message_formatter=None,
Expand All @@ -246,13 +229,6 @@ def PrintMessage(message,
use_index_order: If True, print fields of a proto message using the order
defined in source code instead of the field number. By default, use the
field number order.
float_format: If set, use this to specify float field formatting
(per the "Format Specification Mini-Language"); otherwise, shortest
float that has same value in wire will be printed. Also affect double
field if double_format is not set but float_format is set.
double_format: If set, use this to specify double field formatting
(per the "Format Specification Mini-Language"); if it is not set but
float_format is set, use float_format. Otherwise, str() is used.
use_field_number: If True, print field numbers instead of names.
descriptor_pool: A DescriptorPool used to resolve Any types.
message_formatter: A function(message, indent, as_one_line): unicode|None
Expand All @@ -268,8 +244,6 @@ def PrintMessage(message,
use_short_repeated_primitives=use_short_repeated_primitives,
pointy_brackets=pointy_brackets,
use_index_order=use_index_order,
float_format=float_format,
double_format=double_format,
use_field_number=use_field_number,
descriptor_pool=descriptor_pool,
message_formatter=message_formatter,
Expand All @@ -287,18 +261,22 @@ def PrintField(field,
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
message_formatter=None,
print_unknown_fields=False,
force_colon=False):
"""Print a single field name/value pair."""
printer = _Printer(out, indent, as_utf8, as_one_line,
use_short_repeated_primitives, pointy_brackets,
use_index_order, float_format, double_format,
message_formatter=message_formatter,
print_unknown_fields=print_unknown_fields,
force_colon=force_colon)
printer = _Printer(
out,
indent,
as_utf8,
as_one_line,
use_short_repeated_primitives,
pointy_brackets,
use_index_order,
message_formatter=message_formatter,
print_unknown_fields=print_unknown_fields,
force_colon=force_colon,
)
printer.PrintField(field, value)


Expand All @@ -311,18 +289,22 @@ def PrintFieldValue(field,
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
message_formatter=None,
print_unknown_fields=False,
force_colon=False):
"""Print a single field value (not including name)."""
printer = _Printer(out, indent, as_utf8, as_one_line,
use_short_repeated_primitives, pointy_brackets,
use_index_order, float_format, double_format,
message_formatter=message_formatter,
print_unknown_fields=print_unknown_fields,
force_colon=force_colon)
printer = _Printer(
out,
indent,
as_utf8,
as_one_line,
use_short_repeated_primitives,
pointy_brackets,
use_index_order,
message_formatter=message_formatter,
print_unknown_fields=print_unknown_fields,
force_colon=force_colon,
)
printer.PrintFieldValue(field, value)


Expand Down Expand Up @@ -367,20 +349,14 @@ def __init__(
use_short_repeated_primitives=False,
pointy_brackets=False,
use_index_order=False,
float_format=None,
double_format=None,
use_field_number=False,
descriptor_pool=None,
message_formatter=None,
print_unknown_fields=False,
force_colon=False):
force_colon=False,
):
"""Initialize the Printer.

Double values can be formatted compactly with 15 digits of precision
(which is the most that IEEE 754 "double" can guarantee) using
double_format='.15g'. To ensure that converting to text and back to a proto
will result in an identical value, double_format='.17g' should be used.

Args:
out: To record the text format result.
indent: The initial indent level for pretty print.
Expand All @@ -392,13 +368,6 @@ def __init__(
use_index_order: If True, print fields of a proto message using the order
defined in source code instead of the field number. By default, use the
field number order.
float_format: Deprecated. If set, use this to specify float field
formatting (per the "Format Specification Mini-Language"); otherwise,
shortest float that has same value in wire will be printed. Also affect
double field if double_format is not set but float_format is set.
double_format: Deprecated. If set, use this to specify double field
formatting (per the "Format Specification Mini-Language"); if it is not
set but float_format is set, use float_format. Otherwise, str() is used.
use_field_number: If True, print field numbers instead of names.
descriptor_pool: A DescriptorPool used to resolve Any types.
message_formatter: A function(message, indent, as_one_line): unicode|None
Expand All @@ -415,15 +384,6 @@ def __init__(
self.use_short_repeated_primitives = use_short_repeated_primitives
self.pointy_brackets = pointy_brackets
self.use_index_order = use_index_order
self.float_format = float_format
if double_format is not None:
warnings.warn(
'double_format is deprecated for text_format. This will '
'turn into error in 7.34.0, please remove it before that.'
)
self.double_format = double_format
else:
self.double_format = float_format
self.use_field_number = use_field_number
self.descriptor_pool = descriptor_pool
self.message_formatter = message_formatter
Expand Down Expand Up @@ -656,21 +616,10 @@ def PrintFieldValue(self, field, value):
else:
out.write('false')
elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_FLOAT:
if self.float_format is not None:
warnings.warn(
'float_format is deprecated for text_format. This '
'will turn into error in 7.34.0, please remove it '
'before that.'
)
out.write('{1:{0}}'.format(self.float_format, value))
if math.isnan(value):
out.write(str(value))
else:
if math.isnan(value):
out.write(str(value))
else:
out.write(str(type_checkers.ToShortestFloat(value)))
elif (field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_DOUBLE and
self.double_format is not None):
out.write('{1:{0}}'.format(self.double_format, value))
out.write(str(type_checkers.ToShortestFloat(value)))
else:
out.write(str(value))

Expand Down
Loading