This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

classification
Title: Should Clinic have "nullable" or types=NoneType?
Type: enhancement Stage: resolved
Components: Argument Clinic Versions: Python 3.5
process
Status: closed Resolution: fixed
Dependencies: Superseder:
Assigned To: larry Nosy List: larry, serhiy.storchaka, zach.ware
Priority: normal Keywords:

Created on 2015-04-12 04:24 by larry, last changed 2022-04-11 14:58 by admin. This issue is now closed.

Messages (11)
msg240534 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2015-04-12 04:24
I was staring at Clinic tonight and a thought came to me.  We could express "nullable=True" as "types='NoneType'".  For example, the converter for 'Z' could change from

    Py_UNICODE(nullable=True)

to

    Py_UNICODE(types="str NoneType")

There Should Be Only One Way To Do It.  Should we get rid of "nullable=True" and use types=NoneType instead?

FWIW it's pretty arbitrary either way; the arguments to the converter are just telling the converter how to generate the code.  I don't think it would make any difference in the converter's code--either way is fine.
msg240536 - (view) Author: Zachary Ware (zach.ware) * (Python committer) Date: 2015-04-12 04:30
s/Only One/One Obvious/ ;)

Which way is more obvious? How would it affect nullable ints?
msg240542 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2015-04-12 05:22
This will break other principle. Don't Repeat Yourself. "str" for the "Py_UNICODE" converter looks redundant.
msg240556 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2015-04-12 14:00
Saying that "str" is redundant makes me think you don't understand what "types" does.  "types" accepts a text string listing all of the Python types the converter accepts.  You can accept the converter's default, or you can specify your own value.  If you specify your own value you must list all the types.  So "str" is not redundant there.

The problem with "which one is more obvious": we could get rid of "nullable" and just use "types".  But we can't get rid of "types".  If we keep both, now we theoretically have two ways to specify it.  Which should you use?  Do we say "you must use the nullable parameter, you're not allowed to specify NoneType in types", and if so, why?

p.s. I promised to rename "nullable" to "accepts_none".  Obviously if I just get rid of it I needn't bother.

p.p.s. Should types accept a "+" to mean "all the defaults, and..."?  For example, calling str(types="+ foo") was equivalent to str(types="str foo")?
msg241475 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2015-04-19 05:34
I'm now converging on changing types= to accept a set of real types, see issue #24001.  That change has an impact on this decision.

(By the way, let's assume that if "nullable", I have to rename it to "accepts_none".  I'll use that name below.)

What makes me want to use types={NoneType} is the Zen: "There should be one (and preferably only one) obvious way to do it", and "Special cases aren't special enough to break the rules".  But Argument Clinic's input isn't Python, so maybe the Zen doesn't need to be as strict here.

What makes me not want to use types={NoneType} is that it's generally longer, and it requires you to know the default types accepted by a converter.

Currently (after the rename) to get format unit "z" you write:
   s: str(accepts_none=True)
If I changed this (and #24001 goes in), you'd have to write:
   s: str(types={str, NoneType})

It requires you to know all the default types of the converter in question, just so you can add NoneType to it.  And it's longer.

We could fix it if converter classes generally published their default types.  So you could say
   s: str(types=str_converter.default_types + {NoneType})
And it's even longer.  So we probably shouldn't bother with this.

On the other hand, out of all the converters that exist, only three have a types= argument (int, str, and Py_buffer).  And it's not unreasonable to expect the caller to know the default types= set.  Although, we'd have to add types= to a fourth converter (Py_UNICODE), which currently supports nullable= but doesn't need types=.
msg241480 - (view) Author: Serhiy Storchaka (serhiy.storchaka) * (Python committer) Date: 2015-04-19 05:49
accepts_none=True looks as "doesn't accept anything" to me.
msg241484 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2015-04-19 05:58
Oh, I misremembered.  The name "allow_none" was inflicted on me by python-dev, in this thread:

https://mail.python.org/pipermail/python-dev/2014-August/135650.html
msg241491 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2015-04-19 07:28
p.s. I'm now leaning heavily towards renaming "types" to "accept", and putting NoneType in the set passed to accept= instead of a separate parameter.
msg241494 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2015-04-19 08:19
I've posted about this to python-dev.
msg241672 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2015-04-20 18:04
I've implemented this change in the latest patch (#3) for #24001.
msg242757 - (view) Author: Larry Hastings (larry) * (Python committer) Date: 2015-05-08 12:35
The final version of this has been implemented as part of 41fb7fd04b5d for issue #24001.

However, I'll mention here for posterity's sakes: there's an additional discussion on #24145.  (Everyone on the nosy list has already been invited to the party!)
History
Date User Action Args
2022-04-11 14:58:15adminsetgithub: 68108
2015-05-08 12:35:17larrysetstatus: open -> closed
resolution: fixed
messages: + msg242757

stage: test needed -> resolved
2015-04-20 18:04:22larrysetmessages: + msg241672
2015-04-19 08:19:40larrysetmessages: + msg241494
2015-04-19 07:28:32larrysetmessages: + msg241491
2015-04-19 05:58:22larrysetmessages: + msg241484
2015-04-19 05:49:49serhiy.storchakasetmessages: + msg241480
2015-04-19 05:34:03larrysetmessages: + msg241475
2015-04-12 14:00:58larrysetmessages: + msg240556
2015-04-12 05:22:46serhiy.storchakasetmessages: + msg240542
2015-04-12 04:30:06zach.waresetmessages: + msg240536
2015-04-12 04:24:21larrycreate