Skip to content

Conversation

@pablogsal
Copy link
Member

@pablogsal pablogsal commented Oct 12, 2017

This PR solves bpo-29696 improving the readability of the return value of Formatter.parse. Following the requirements of @rhettinger and @serhiy-storchaka, the c-code upstream of the string library was modified to maintain the string module lightweight. This also improves the help section of the result class with a brief description of the result fields.

Now, instead of:

>>> Formatter().parse("mira como bebebn los peces en el {rio} {de} {la} plata")
<formatteriterator object at 0x7f1fc7c7f150>
>>> next(_)
('mira como bebebn los peces en el ', 'rio', '', None)

we obtain

>>> Formatter().parse("mira como bebebn los peces en el {rio} {de} {la} plata")
<formatteriterator object at 0x7f1fc7c7f150>
>>> next(_)
FormatterItem(literal_text='mira como bebebn los peces en el ', field_name='rio', format_spec='', conversion=None)

Please, indicate any change that is needed and I will be more than happy to change it. 😄

https://bugs.python.org/issue29696

Copy link
Contributor

@rhettinger rhettinger left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you please add tests.

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@pablogsal
Copy link
Member Author

I have made the requested changes; please review again

@bedevere-bot
Copy link

Thanks for making the requested changes!

@rhettinger: please review the changes made to this pull request.

Copy link
Member

@facundobatista facundobatista left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this work!

Patch applied OK and tests run fine.

I annotated some changes to do.

Thanks again!!

self.assertEqual(formatter.n_sequence_fields, 4)
self.assertNotEqual(formatter.__class__,tuple)
self.assertIsInstance(formatter,tuple)
self.assertEqual(formatter.__class__.__name__,"FormatterItem")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please comply PEP-8 in these last three lines.

@@ -0,0 +1,2 @@
Use namedtuple (structseq ovbject) in string.Formatter.parse iterator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

typo in "ovbject"

PyObject *format_spec_str = NULL;
PyObject *conversion_str = NULL;
PyObject *tuple = NULL;
PyObject* res = NULL;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please follow the convention and write PyObject *res

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@pablogsal
Copy link
Member Author

I have made the requested changes; please review again.

@bedevere-bot
Copy link

Thanks for making the requested changes!

@rhettinger, @facundobatista: please review the changes made to this pull request.


tuple = PyTuple_Pack(4, literal_str, field_name_str, format_spec_str,
conversion_str);
Py_XINCREF(literal_str);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

None of these pointers is NULL, isn't?

And why increment refcounters of non-borrowed references and later decrement them?

Copy link
Member Author

@pablogsal pablogsal Oct 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 814cb3b. That's right, none of the pointers is NULL. The reason for the increment and decrement is because I was getting segfaults so I tried to use idempotent incref-decref mirroring the ones that happen in PyTuple_Pack and after to check if any of the segfaults was due to incorrect incref/decref. I just removed both the increfs and the decrefs and everything is OK. Sorry for the confusion.

static PyTypeObject FormatterIterResultType;

static PyStructSequence_Desc formatter_iter_result_desc = {
"FormatterItem",
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't a module name be added?

Copy link
Member Author

@pablogsal pablogsal Oct 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I am confused. Do you mean to expose the type in a module or to add a doc to the second field?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Shouldn't the name of the type include the name of the module?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in 3ee0266.

self.assertEqual(formatter, expected_formatter)

for result, expected in zip(formatter, expected_formatter):
self.assertEqual(expected,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

First argument is an actual value, second argument is an expected value.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 814cb3b.

(result.literal_text,
result.field_name,
result.format_spec,
result.conversion,))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Redundant trailing comma.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 814cb3b.

@@ -0,0 +1,2 @@
Use namedtuple (structseq object) in string.Formatter.parse iterator
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

"named tuple"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed in 814cb3b.

result.field_name,
result.format_spec,
result.conversion)
,expected)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, this comma looks just ugly.

I would use 4 separate tests:

self.assertEqual(result.literal_text, expected[0])
...

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in ff5651c.

Py_XDECREF(format_spec_str);
Py_XDECREF(conversion_str);
return tuple;

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There is a leak in case of error.

Decrefs are needed only in case of error. If values are set to a named tuple, they are not needed.

Rename done to error and add return before it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in ff5651c.

conversion_str);
PyStructSequence_InitType(&FormatterIterResultType, &formatter_iter_result_desc);
Py_INCREF((PyObject *) &FormatterIterResultType);
res = PyStructSequence_New(&FormatterIterResultType);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Check error.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done in ff5651c.


tuple = PyTuple_Pack(4, literal_str, field_name_str, format_spec_str,
conversion_str);
PyStructSequence_InitType(&FormatterIterResultType, &formatter_iter_result_desc);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wait, do you initialize the type every time when create an instance?

Copy link
Member Author

@pablogsal pablogsal Oct 17, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I cannot find the appropriate PyInit_{module} function to initialize the type so at this point I was doing it here so there is some implementation to discuss. My apologies 😞 . Where should I initialize the StructSeq?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry, I just found where _string is initialized and I am initializing the type in PyInit__string in f10d429. Please, correct me if this is not the correct place.

@bedevere-bot
Copy link

A Python core developer has requested some changes be made to your pull request before we can consider merging it. If you could please address their requests along with any other requests in other reviews from core developers that would be appreciated.

Once you have made the requested changes, please leave a comment on this pull request containing the phrase I have made the requested changes; please review again. I will then notify any core developers who have left a review that you're ready for them to take another look at this pull request.

@pablogsal
Copy link
Member Author

I have made the requested changes; please review again

@bedevere-bot
Copy link

Thanks for making the requested changes!

@serhiy-storchaka, @facundobatista, @rhettinger: please review the changes made to this pull request.

Copy link
Member

@serhiy-storchaka serhiy-storchaka left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just added yet few nitpicks.

But actually I'm not convinced that this change is needed.

Py_XDECREF(format_spec_str);
Py_XDECREF(conversion_str);
return tuple;
return res;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just return NULL. And initializing res with NULL at line 1035 is not needed.

PyStructSequence_SET_ITEM(res, 3, conversion_str);

return res;
error:
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It would look cleaner if add an empty line before a label.

{"literal_text", "Span of literal text."},
{"field_name", "Specifies the object whose value is to be formatted."},
{"format_spec", "Contains a specification of how the value should be presented."},
{"conversion", "The conversion to be used. One of: ‘s’ (str), ‘r’ (repr) and ‘a’ (ascii)."},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line looks too long. And maybe the previous line too.

@serhiy-storchaka serhiy-storchaka dismissed their stale review October 18, 2017 07:37

Technically the PR is good.

@pablogsal
Copy link
Member Author

pablogsal commented Oct 18, 2017

IMHO this change makes things a bit more consistent. In lots of places when a tuple is returned, a structseq is used to improve readability on the returned result. Some examples of this are:

  • grp.struct_group
  • os.terminal_size
  • pwd.struct_passwd
  • resource.struct_rusage
  • signal.struct_siginfo
  • time.struct_time
  • spwd.struct_spwd
  • sys.float_info
  • sys.int_info
  • string.FormatterItem
  • sys.hash_info
  • sys.getwindowsversion
  • sys.flags
  • sys.version_info
  • sys.thread_info

@facundobatista
Copy link
Member

@rhettinger hello! This PR now has some tests.. are these enough for you?

I just run all the tests, so if you're we could merge this...

@pablogsal pablogsal closed this Jul 3, 2018
@pablogsal pablogsal deleted the bpo29696 branch May 19, 2021 18:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

6 participants