Skip to content

Add 'bool' format character to PyArg_ParseTuple* #58910

Closed

Description

@larryhastings
BPO 14705
Nosy @loewis, @birkenfeld, @rhettinger, @mdickinson, @larryhastings, @ericvsmith, @benjaminp, @serhiy-storchaka
Files
  • larry.parse.tuple.p.and.P.1.diff: Patch adding 'p' and 'P' support to PyArg_ParseTuple etc.
  • larry.parse.tuple.p.and.P.2.diff
  • larry.parse.tuple.p.and.P.3.diff
  • larry.parse.tuple.p.4.diff
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields:

    assignee = 'https://github.com/larryhastings'
    closed_at = <Date 2012-05-06.06:03:22.058>
    created_at = <Date 2012-05-02.09:29:19.125>
    labels = ['interpreter-core', 'type-feature']
    title = "Add 'bool' format character to PyArg_ParseTuple*"
    updated_at = <Date 2012-05-07.09:45:44.331>
    user = 'https://github.com/larryhastings'

    bugs.python.org fields:

    activity = <Date 2012-05-07.09:45:44.331>
    actor = 'python-dev'
    assignee = 'larry'
    closed = True
    closed_date = <Date 2012-05-06.06:03:22.058>
    closer = 'larry'
    components = ['Interpreter Core']
    creation = <Date 2012-05-02.09:29:19.125>
    creator = 'larry'
    dependencies = []
    files = ['25441', '25453', '25465', '25468']
    hgrepos = []
    issue_num = 14705
    keywords = ['patch']
    message_count = 34.0
    messages = ['159781', '159783', '159785', '159839', '159844', '159916', '159918', '159923', '159926', '159927', '159928', '159929', '159930', '159931', '159932', '159933', '159934', '160000', '160001', '160003', '160005', '160006', '160007', '160008', '160013', '160016', '160019', '160044', '160045', '160046', '160047', '160049', '160056', '160127']
    nosy_count = 9.0
    nosy_names = ['loewis', 'georg.brandl', 'rhettinger', 'mark.dickinson', 'larry', 'eric.smith', 'benjamin.peterson', 'python-dev', 'serhiy.storchaka']
    pr_nums = []
    priority = 'normal'
    resolution = 'fixed'
    stage = 'resolved'
    status = 'closed'
    superseder = None
    type = 'enhancement'
    url = 'https://bugs.python.org/issue14705'
    versions = ['Python 3.3']

    Activity

    1. larryhastings commented on May 2, 2012

      @larryhastings
      ContributorAuthor

      Currently functions that parse their arguments with the PyArg_ParseTuple family which want to take a boolean-ish parameter face two choices:

      • take an "int", then test whether or not the int is 0, or
      • take an "object", then call PyObject_IsTrue themselves.

      The former is foolish; though it works with ints and bools, it doesn't work with any other type (float, str, list, etc) which strictly speaking are valid for boolean fields. And this is common enough that the latter should not be necessary.

      I propose to add support for a new format character to the PyArg_ParseTuple family: 'b', which specifies 'boolean'. Its
      implementation would be much the same as that of 'd' except:

      • the output type would be "int" instead of "double",
      • it would check for a -1 instead of calling PyErr_Occured, and
      • it would call PyObject_IsTrue instead of PyFloat_AsDouble.

      If we cared, I could also add 'B', which would only accept
      either Py_True or Py_False. But I see no reason why we'd ever want
      to strictly enforce the type... do you? (I can see MvL's argument now:
      "We've lived this long without it. YAGNI.")

      If there's interest I'll knock out a patch. I expect it to be less than ten lines not counting documentation and test. (Less than twenty if
      folks actually want 'B'.)

    2. self-assigned this
      on May 2, 2012
    3. serhiy-storchaka commented on May 2, 2012

      @serhiy-storchaka
      Member

      Yes, I too have encountered this in the process of working on bpo-14626. For this purpose it is appropriate to use a special converter (with 'O&'). I suppose it must be a strict сonverter; there is no point in specifying followlinks=[1, 2, 3]. If it is somewhere need a nonstrict ones -- use 'O' and then check the how to in this particular case.

      Would be good to have a special letter for this format, but note that 'b' and 'B' are already used. It is better first to use the сonverter, and expand the format only when the enough number of uses.

    4. larryhastings commented on May 2, 2012

      @larryhastings
      ContributorAuthor

      For this purpose it is appropriate to use a special converter
      (with 'O&').

      The converter works--but, then, a similar converter would also work
      for double, and float, and long long and many others. If long long
      is special enough to merit explicit support in PyArg_ParseTuple,
      then bool definitely is, as I strongly suspect bool is used much more
      frequently.

      I suppose it must be a strict сonverter; there is no point
      in specifying followlinks=[1, 2, 3].

      I don't see a need for that either, but--where would you draw the line? What is the principle that says "ints are okay, floats are... okay, lists are not"?

      Python has a long-established concept of the "truthiness" of an expression. I *strongly* suggest we stick with that unless we have a *very* good reason why not.

      note that 'b' and 'B' are already used.

      I'm a moron! I must have looked right at it and it didn't register.

      't' (truth) and 'f' (false) are also taken. As is 'c' (conditional).
      The only thing I can come up with that's remotely related and
      isn't already taken is 'p' for predicate.

      It is better first to use the сonverter, and expand the format
      only when the enough number of uses.

      I suspect there are already loads of places in the standard library
      that should be using this rather than abusing 'i'.

    5. larryhastings commented on May 3, 2012

      @larryhastings
      ContributorAuthor

      My first patch. Adds 'p' and 'P', along with documentation and unit tests.

    6. serhiy-storchaka commented on May 3, 2012

      @serhiy-storchaka
      Member

      Patch looks good to me.

      I however prefer to use 'P'.

    7. ericvsmith commented on May 4, 2012

      @ericvsmith
      Member

      The patch looks good to me.

      Are there any places in the current code base that would use "P"? "p" seems the more useful case.

      Are you planning on changing existing code to use P or p, or just use it going forward?

    8. mdickinson commented on May 4, 2012

      @mdickinson
      Member

      I also think that 'P' looks too strict to be really useful. I can't think of too many cases where I'd really want to insist on a boolean argument (and reject values of 0 or 1).

      Maybe implement just 'p' for now and consider 'P' later?

    9. larryhastings commented on May 4, 2012

      @larryhastings
      ContributorAuthor

      I looked through the Python sources and couldn't find any instances of a function or method with an argument that only allowed you to pass in either True or False.

      Serily already said he would use 'P' over 'p', although I too am unconvinced that's a good idea. Serily: why would you unhesitatingly prefer 'P' to 'p'?

      Certainly I see loads of uses for 'p'. For example, when converting code from Python to C that already relied on Python's standard definition of truthiness.

      I did find some spots that took an object and converted to bool with PyObject_IsTrue, like _json.Encoder(allow_nan) and pickle._Pickler(fix_imports). These too would be well-served by 'p'.

      I also found some funny in-between cases. For example, stat_float_times and the three-argument form of os.symlink both claim to take a boolean but actually take 'i' (integer). This is relying on bool.__int__(). We certainly couldn't use 'P' here. We could consider switching these to 'p', though in all likelyhood we'll just leave 'em alone.

    10. loewis commented on May 4, 2012

      loewismannequin
      Mannequin

      I think there should be a test case also where PyObject_IsTrue gives an exception (which I think can happen if __bool__ raises an exception).

    11. larryhastings commented on May 4, 2012

      @larryhastings
      ContributorAuthor

      I think there should be a test case also where PyObject_IsTrue gives an
      exception (which I think can happen if __bool__ raises an exception).

      I'd be happy to add such a test, but I don't know of any types like that. Can anyone suggest one?

    12. loewis commented on May 4, 2012

      loewismannequin
      Mannequin

      > I think there should be a test case also where PyObject_IsTrue gives an
      > exception (which I think can happen if __bool__ raises an exception).

      I'd be happy to add such a test, but I don't know of any types like
      that. Can anyone suggest one?

      class NotTrue:
           def __bool__(self):
               raise NotImplementedError
    13. larryhastings commented on May 4, 2012

      @larryhastings
      ContributorAuthor

      Added test forcing a failure for 'p' (and 'P'). This made me have to handle errors a little differently, so it was definitely good to test it. Thanks for the suggestion, Martin!

      Also changed wording in documentation ever-so-slightly.

    14. 9 remaining items

    15. mdickinson commented on May 5, 2012

      @mdickinson
      Member

      I considered briefly trying to make 'P' handle subclasses of bool.

      Not an issue: bool can't be subclassed. :-)

      Python 3.2.3 (default, Apr 13 2012, 00:15:25) 
      [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
      Type "help", "copyright", "credits" or "license" for more information.
      >>> class MyBool(bool):
      ...     pass
      ... 
      Traceback (most recent call last):
        File "<stdin>", line 1, in <module>
      TypeError: type 'bool' is not an acceptable base type
    16. serhiy-storchaka commented on May 5, 2012

      @serhiy-storchaka
      Member

      That's not a reason to use 'P'. Why you should use 'P' in the first place?

      I just guided by the principle "Explicit is better than implicit".
      Statements 'if' and 'while' I consider explicit and expect cast to bool.
      Implicit cast to bool in the transfer of parameter causes discomfort (no
      one (no one Pythonist) expects the implicit cast to str). Unfortunately,
      for historical reasons, there is a lot of code, where the parameters are
      casted to bool or int is used instead of bool. Therefore, we cannot
      simply enter the restrictions.

      Well, I was certainly wrong. Don't let me mislead you.

      Anyway, what lunatic would subclass bool?

      Class bool cannot be subclassed further.

    17. larryhastings commented on May 5, 2012

      @larryhastings
      ContributorAuthor

      Serhiy, I'm having a little trouble with your English. (But I'm sure your English is far better than my... uh, anything besides English.) So let me ask a question with a clear yes/no answer:

      Do you still think 'P' is better than 'p'?

    18. serhiy-storchaka commented on May 5, 2012

      @serhiy-storchaka
      Member

      Do you still think 'P' is better than 'p'?

      No.

      I hope I haven't made a lot of mistakes in the previous sentence.

    19. larryhastings commented on May 5, 2012

      @larryhastings
      ContributorAuthor

      I hope I haven't made a lot of mistakes in the previous sentence.

      It depends, do you consider three "a lot"? ;-)

      Attached is a new patch removing 'P'. (The regrtest is still running but I don't expect any failures.) I'm guessing I won't get any further feedback. So unless I hear otherwise I'll check it in tomorrow.

    20. mdickinson commented on May 5, 2012

      @mdickinson
      Member

      Latest patch looks good to me.

    21. python-dev commented on May 5, 2012

      python-devmannequin
      Mannequin

      New changeset bc6d28e726d8 by Larry Hastings in branch 'default':
      Issue bpo-14705: Add 'p' format character to PyArg_ParseTuple* for bool support.
      http://hg.python.org/cpython/rev/bc6d28e726d8

    22. larryhastings commented on May 5, 2012

      @larryhastings
      ContributorAuthor

      Eh, it was ready, why wait? Thanks everybody for your feedback!

    23. rhettinger commented on May 6, 2012

      @rhettinger
      Contributor

      I would have expected a bool parse code to insist on a boolean, so that:

          int x;
          PyArg_ParseTupleAndKeywords(args, kwds, "p:func", &x);

      would behave the same as:

          PyObject  *o;
          int x;
          PyArg_ParseTupleAndKeywords(args, kwds, "O!:func", &PyBool_Type, &o);
          x = o == Py_True;
    24. larryhastings commented on May 6, 2012

      @larryhastings
      ContributorAuthor

      I would have expected a bool parse code to insist on a boolean,

      I originally had a second form ('P') that insisted on a boolean as you suggest. But nobody could come up with a use case. So I removed it in the final patch. Please see this issue for the discussion.

      If you have a use case for it I'd be happy to revive it and check it in.

    25. python-dev commented on May 6, 2012

      python-devmannequin
      Mannequin

      New changeset 709850f1ec67 by Larry Hastings in branch 'default':
      Update Misc/NEWS for issues bpo-14127 and bpo-14705. (And, technically, bpo-10148.)
      http://hg.python.org/cpython/rev/709850f1ec67

    26. python-dev commented on May 6, 2012

      python-devmannequin
      Mannequin

      New changeset 05274ab06182 by Larry Hastings in branch 'default':
      Update Misc/NEWS for issues bpo-14127 and bpo-14705. (And, technically, bpo-10148.)
      http://hg.python.org/cpython/rev/05274ab06182

    27. python-dev commented on May 7, 2012

      python-devmannequin
      Mannequin

      New changeset e4617650f006 by Larry Hastings in branch 'default':
      Issue bpo-14705: Added support for the new 'p' format unit to skipitem().
      http://hg.python.org/cpython/rev/e4617650f006

    28. transferred this issue fromon Apr 10, 2022
    Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

    Metadata

    Metadata

    Assignees

    Labels

    interpreter-core(Objects, Python, Grammar, and Parser dirs)type-featureA feature request or enhancement

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions