Surely "nullable" is a reasonable name?

Argument Clinic "converters" specify how to convert an individual argument to the function you're defining. Although a converter could theoretically represent any sort of conversion, most of the time they directly represent types like "int" or "double" or "str". Because there's such variety in argument parsing, the converters are customizable with parameters. Many of these are common enough that Argument Clinic suggests some standard names. Examples: "zeroes=True" for strings and buffers means "permit internal \0 characters", and "bitwise=True" for unsigned integers means "copy the bits over, even if there's overflow/underflow, and even if the original is negative". A third example is "nullable=True", which means "also accept None for this parameter". This was originally intended for use with strings (compare the "s" and "z" format units for PyArg_ParseTuple), however it looks like we'll have a use for "nullable ints" in the ongoing Argument Clinic conversion work. Several people have said they found the name "nullable" surprising, suggesting I use another name like "allow_none" or "noneable". I, in turn, find their surprise surprising; "nullable" is a term long associated with exactly this concept. It's used in C# and SQL, and the term even has its own Wikipedia page: http://en.wikipedia.org/wiki/Nullable_type Most amusingly, Vala *used* to have an annotation called "(allow-none)", but they've broken it out into two annotations, "(nullable)" and "(optional)". http://blogs.gnome.org/desrt/2014/05/27/allow-none-is-dead-long-live-nullabl... Before you say "the term 'nullable' will confuse end users", let me remind you: this is not user-facing. This is a parameter for an Argument Clinic converter, and will only ever be seen by CPython core developers. A group which I hope is not so easily confused. It's my contention that "nullable" is the correct name. But I've been asked to bring up the topic for discussion, to see if a consensus forms around this or around some other name. Let the bike-shedding begin, //arry/

On Mon, Aug 4, 2014 at 12:12 AM, Larry Hastings <larry@hastings.org> wrote:
The thing is, "null" in these languages are not the same thing. If you look to the various database wrappers there's a lot of controversy about just how to map the SQL NULL to Python: simply mapping it to Python's None becomes strange because the semantics of a SQL NULL or NULL pointer and Python None don't exactly match. Not all that long ago someone was making an argument on this list to add a SQLNULL type object to better map SQL NULL semantics (regards to sorting, as I recall -- but its been awhile) Python has None. Its definition and understanding in a Python context is clear. Why introduce some other concept? In Python its very common you pass None instead of an other argument.
Yet, my lurking observation of argument clinic is it is all about clearly defining the C-side of how things are done in Python API's. It may not confuse 'end users', but it may confuse possible contributors, and simply add a lack of clarity to the situation. Passing None in place of another argument is a very Pythonic thing to do; why confuse that by using other words which imply other semantics? None is a Python thing with clear semantics in Python; allow_none quite accurately describes the Pythonic thing described here, while 'nullable' expects for domain knowledge beyond Python and makes assumptions of semantics. /re-lurk --S

On 8/4/2014 12:35 AM, Stephen Hansen wrote:
Thanks, Stephen. +1 to all you wrote. There remains, of course, one potential justification for using "nullable", that you didn't make 100% clear. Because "argument clinic is it is all about clearly defining the C-side of how things are done in Python API's." and that is that C uses NULL (but it is only a convention, not a language feature) for missing reference parameters on occasion. But I think it is much more clear that if C NULL gets mapped to Python None, and we are talking about Python parameters, then a NULLable C parameter should map to an "allow_none" Python parameter. The concepts of C NULL, C# NULL, SQL NULL, and Python None are all slightly different, even the brilliant people on python-dev could better spend their energies on new features and bug fixes rather than being slowed by the need to remember yet another unclear and inconsistent terminology issue, of which there are already too many. Glenn

On 08/04/2014 05:46 PM, Glenn Linderman wrote:
Argument Clinic defines *both* sides of how things are done in builtins, both C and Python. So it's a bit messier than that. Currently the "nullable" flag is only applicable to certain converters which output pointer types in C, so if it gets a None for that argument it does provide a NULL as the C equivalent. But in the "nullable int" patch obviously I can't do that. Instead you get a structure containing either an int or a flag specifying "you got a None", currently named "is_null". So I don't think your proposed additional justification helps. Of course, in my opinion I don't need this additional justification. Python's "None" is its null object. And we already have the concept of "nullable types" in computer science, for exactly, *exactly!*, this concept. As the Zen says, "special cases aren't special enough to break the rules". Just because Python is silly enough to name its null object "None" doesn't mean we have to warp all our other names around it. //arry/

Hi! On Mon, Aug 04, 2014 at 05:12:47PM +1000, Larry Hastings <larry@hastings.org> wrote:
In my very humble opinion, "nullable" is ok, but "allow_none" is better. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On 4 Aug 2014 18:16, "Oleg Broytman" <phd@phdru.name> wrote:
Hi!
On Mon, Aug 04, 2014 at 05:12:47PM +1000, Larry Hastings <
larry@hastings.org> wrote:
Yup, this is where I stand as well. The main concern I have with nullable is that we *are* writing C code when dealing with Argument Clinic, and "nullable" may make me think of a C NULL rather than Python's None. Cheers, Nick.
https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com

I admit I spent the first half of the email scratching my head and trying to figure out what NULL had to do with argument clinic specs. (Maybe it would mean that if the argument is "not given" in some appropriate way then we set the corresponding C variable to NULL?) Finding out you were talking about None came as a surprising twist. -n On 4 Aug 2014 08:13, "Larry Hastings" <larry@hastings.org> wrote:

On Mon, Aug 4, 2014 at 12:57 PM, Ethan Furman <ethan@stoneleaf.us> wrote:
'allow_none' is definitely clearer.
I disagree. Unlike "nullable", "allow_none" does not tell me what happens on the C side when I pass in None. If the receiving type is PyObject*, either NULL or Py_None is a valid choice.

On Mon, Aug 4, 2014 at 1:53 PM, Antoine Pitrou <antoine@python.org> wrote:
We cannot "allow None" when the receiving type is C int. In this case, we need a way to implement "nullable int" type in C. We can use int * or a pair of int and _Bool or anything else. Whatever the implementation, the concept that is implemented is "nullable int." The advantage of using the term "nullable" is that it is language and implementation neutral.

On 08/05/2014 03:53 AM, Antoine Pitrou wrote:
Just to be precise: in the case where the receiving type *would* have been an int, and "nullable=True", the receiving type is actually a structure containing an int and a "you got a None" flag. I can't stick a magic value in the int and say "that represents you getting a None" because any integer value may be valid. Also, I'm pretty sure there are places in builtin argument parsing that accept either NULL or Py_None, and I *think* maybe in one or two of them they actually mean different things. What fun! For small values of "fun", //arry/

Am 04.08.14 09:12, schrieb Larry Hastings:
I have personally no problems with calling a type "nullable" even in Python, and, as a type *adjective* this seems to be the right choice (i.e. I wouldn't say "noneable int" or "allow_none int"; the former is no established or intuitive term, the latter is not an adjective). As a type *flag*, flexibility in naming is greater. zeroes=True formally creates a subtype (of string), and it doesn't hurt that it is not an adjective. "allow_zeroes" might be more descriptive. bitwise=True doesn't really create a subtype of int. For the feature in question, I find both "allow_none" and "nullable" acceptable; "noneable" is not. Regards, Martin

On 08/05/2014 08:13 AM, "Martin v. Löwis" wrote:
For the feature in question, I find both "allow_none" and "nullable" acceptable; "noneable" is not.
Well! It's rare that the core dev community is so consistent in its opinion. I still think "nullable" is totally appropriate, but I'll change it to "allow_none". //arry/

On 08/07/2014 09:41 PM, Larry Hastings wrote:
(reviving eight-month-old thread) In case anybody here is still interested in arguing about this: the Clinic API may be shifting a bit here. What follows is a quick refresher course on Argument Clinic, followed by a discussion of the proposed new API. Here's an Argument Clinic declaration of a parameter: s: str() The parameter is called "s", and it's specifying a converter function called "str" which handles converting string parameters. The str() converter itself accepts parameters; since the parameters all have default values, they're all optional. By default, str() maps directly to the "s" format unit for PyArg_ParseTuple(), as it does here. Currently str() (and a couple other converter functions) accepts a parameter called "types". "types" is specified as a string, and contains an unordered set of whitespace-separated strings representing the Python types of the values this (Clinic) parameter should accept. The default value of "types" for str() is "str"; the following declaration is equivalent to the declaration above: s: str(types="str") Other legal values for the "types" parameter for the str converter include "bytes bytearray str" and "robuffer str". Internally the types parameter is converted into a set of strings; passing it in as a string is a nicety for the caller's benefit. (It also means that the strings "robuffer str" and "str robuffer" are considered equivalent.) There's a second parameter, currently called "nullable", but I was supposed to rename it "allow_none", so I'll use that name here. If you pass in "allow_none=True" to a converter, it means "this (Clinic) parameter should accept the Python value None". So, to map to the format unit "z", you would specify: s: str(allow_none=True) And to map to the format unit "z#", you would specify: s: str(types="robuffer str", allow_none=True, length=True) In hindsight this is all a bit silly. I propose what I think is a much better API below. We should rename "types" to "accept". "accept" should takes a set of types; these types specify the types of Python objects the Clinic parameter should accept. For the funny pseudo-types needed in some Clinic declarations ("buffer", "robuffer", and "rwbuffer"), Clinic provides empty class declarations so these behave like types too. accept={str} is the default for the str() converter. If you want to map to format unit "z", you would write this: s: str(accept={str, NoneType}) (In case you haven't seen it before: NoneType = type(None). I don't think the name is registered anywhere officially in the standard library... but that's the name.) The upside of this approach: * Way, way more obvious to the casual reader. "types" was always meant as an unordered collection of types, but I felt specifying it with strings was unwieldy and made for poor reading ({'str', 'robuffer'}). Passing it in as a single string which I internally split and put in a set() was a bad compromise. But the semantics of this whitespace-delimited string were a bit unclear, even to the experienced Clinic hacker. This set-of-types version maps exactly to what the parameter was always meant to accept in the first place. As with any other code, people will read Clinic declarations far, far more often than they will write them, so optimizing for clarity is paramount. * Zen: "There should be one (and preferably only one) obvious way to do it." We have a way of specifying the types this parameter should accept; "allow_none" adds a second. * Zen: "Special cases aren't special enough to break the rules". "allow_none" was really just a special case of one possible type for "types". The downside of this approach: * You have to know what the default accept= set is for each converter. Luckily this is not onerous; there are only four converters that need an "accept" parameter, and their default values are all simple: int(accept={int}) str(accept={str}) Py_UNICODE(accept={str}) Py_buffer(accept={buffer}) I suggest this is only a (minor) problem when writing a Clinic declaration. It doesn't affect later readability, which is much more important. * It means repeating yourself a little. If you just want to say "I want to accept None too", you have to redundantly specify the default type(s) accepted by the converter function. In practice, it's really only redundant for four or five format units, and they're not the frequently-used ones. Right now I only see three uses of nullable for the built-in format units (there are two more for my path_converter) and they're all for the str converter. Yes, we could create a set containing the default types accepted by each converter function, and just let the caller specify that and incrementally add +{NoneType}. But this would be far longer than simply redundantly respecifying the default (e.g. "accept=str_converter.accept_default + {NoneType}"). Sometimes the best thing is just to bite the bullet and accept a little redundancy. Does "accept" sound good, including accepting "NoneType"? FWIW I originally proposed this in an issue on the tracker: http://bugs.python.org/issue23920 But we should probably continue the discussion here. Cheers, //arry/ p.s. Yes, I never actually got around to renaming "nullable". But I was going to get it done before beta, honest. And anyway remembering to do that is what led me down this path, which I think has been fruitful in its own right.

On 4/19/2015 1:19 AM, Larry Hastings wrote:
Is argument clinic a special case of type annotations? (Quoted and worded to be provocative, intentionally but not maliciously.) OK, I know that argument clinic applies to C code and I know that type annotations apply to Python code. And I know that C code is a lot more restrictive /a priori/ which clinic has to accommodate, and type annotations are a way of adding (unenforced) restrictions on Python code. Still, from a 50,000' view, there seems to be an overlap in functionality... and both are aimed at Py 3.5... I find that interesting... I guess describing parameter types is the latest Python trend :)

On 04/19/2015 01:26 PM, Glenn Linderman wrote:
Argument Clinic and Python 3 type annotations are related concepts. Argument Clinic's syntax is designed in such a way that we actually use ast.parse() to parse it, and that includes using the type annotation syntax. That's about all they have in common. This discussion is off-topic and of limited interest; if you have further questions along these lines please email me privately. //arry/

On Apr 19, 2015, at 01:19 AM, Larry Hastings wrote:
Having only followed the AC discussions tangentially, I have to say that the above suggestion and the given examples make a lot more intuitive sense to me. I had the same initial thought as Glenn regarding type annotations. It's fine that they're separate concepts, but it's also helpful that Larry's suggestion above seems to align them better. Cheers, -Barry

On Sun, Apr 19, 2015 at 11:19 AM, Larry Hastings <larry@hastings.org> wrote:
"Accept" sounds great to me. Allowing a parameter to be None by specifying NoneType is logical and so makes a certain amount of sense. It seems to me that this approach will make it very common to have parameter declarations of the form "int(accept={int, NoneType})" in the stdlib. I'm conflicted whether this is better or worse than "int(allow_none=True)". The former makes it clear that the parameter can accept more than a single type, necessitating additional processing to check what the actual type of the passed value is, which I like. So I'm +0.5 for this at the moment. As for the default set of accepted types for various convertors, if we could choose any syntax we liked, something like "accept=+{NoneType}" would be much better IMO. I'm definitely against repeating the default set of accepted types, since this would require very wide changes whenever the default set of types for a convertor is changed, as well as breaking compatibility for 3rd party libraries using AC. - Tal

On 04/21/2015 04:50 AM, Tal Einat wrote:
In theory Argument Clinic could use any syntax it likes. In practice, under the covers we tease out one or two bits of non-Python syntax, then run ast.parse over it. Saved us a lot of work. "s: accept={str,NoneType}" is a legal Python parameter declaration; "s: accept+={NoneType}" is not. If I could figure out a clean way to hack in support for += I'll support it. Otherwise you'll be forced to spell it out. //arry/

On 22 April 2015 at 03:31, Larry Hastings <larry@hastings.org> wrote:
Ellipsis seems potentially useful here to mean "whatever the default accepted types are": "s: accept={...,NoneType}" My other question would be whether we can use "None" in preference to NoneType, as PEP 484 does: https://www.python.org/dev/peps/pep-0484/#using-none Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On 04/24/2015 09:45 PM, Nick Coghlan wrote:
Ah, I misread Tal's suggestion. Using unary + is an even neater approach.
Not exactly. The way I figure it, the best way to achieve this with unary plus is to ast.parse it (as we currently do) and then modify the parse tree. That works but it's kind of messy. My main objection to this notation is that that set objects /don't support +./ The union operator for sets is |. I've prototyped a hack allowing str(accept|={NoneType}) I used the tokenize module to tokenize, modify, and untokenize the converter invocation. Works fine. And since augmented assignment is (otherwise) illegal in expressions, it's totally unambiguous. I think if we do it at all it should be with that notation. //arry/

On Mon, Aug 4, 2014 at 12:12 AM, Larry Hastings <larry@hastings.org> wrote:
The thing is, "null" in these languages are not the same thing. If you look to the various database wrappers there's a lot of controversy about just how to map the SQL NULL to Python: simply mapping it to Python's None becomes strange because the semantics of a SQL NULL or NULL pointer and Python None don't exactly match. Not all that long ago someone was making an argument on this list to add a SQLNULL type object to better map SQL NULL semantics (regards to sorting, as I recall -- but its been awhile) Python has None. Its definition and understanding in a Python context is clear. Why introduce some other concept? In Python its very common you pass None instead of an other argument.
Yet, my lurking observation of argument clinic is it is all about clearly defining the C-side of how things are done in Python API's. It may not confuse 'end users', but it may confuse possible contributors, and simply add a lack of clarity to the situation. Passing None in place of another argument is a very Pythonic thing to do; why confuse that by using other words which imply other semantics? None is a Python thing with clear semantics in Python; allow_none quite accurately describes the Pythonic thing described here, while 'nullable' expects for domain knowledge beyond Python and makes assumptions of semantics. /re-lurk --S

On 8/4/2014 12:35 AM, Stephen Hansen wrote:
Thanks, Stephen. +1 to all you wrote. There remains, of course, one potential justification for using "nullable", that you didn't make 100% clear. Because "argument clinic is it is all about clearly defining the C-side of how things are done in Python API's." and that is that C uses NULL (but it is only a convention, not a language feature) for missing reference parameters on occasion. But I think it is much more clear that if C NULL gets mapped to Python None, and we are talking about Python parameters, then a NULLable C parameter should map to an "allow_none" Python parameter. The concepts of C NULL, C# NULL, SQL NULL, and Python None are all slightly different, even the brilliant people on python-dev could better spend their energies on new features and bug fixes rather than being slowed by the need to remember yet another unclear and inconsistent terminology issue, of which there are already too many. Glenn

On 08/04/2014 05:46 PM, Glenn Linderman wrote:
Argument Clinic defines *both* sides of how things are done in builtins, both C and Python. So it's a bit messier than that. Currently the "nullable" flag is only applicable to certain converters which output pointer types in C, so if it gets a None for that argument it does provide a NULL as the C equivalent. But in the "nullable int" patch obviously I can't do that. Instead you get a structure containing either an int or a flag specifying "you got a None", currently named "is_null". So I don't think your proposed additional justification helps. Of course, in my opinion I don't need this additional justification. Python's "None" is its null object. And we already have the concept of "nullable types" in computer science, for exactly, *exactly!*, this concept. As the Zen says, "special cases aren't special enough to break the rules". Just because Python is silly enough to name its null object "None" doesn't mean we have to warp all our other names around it. //arry/

Hi! On Mon, Aug 04, 2014 at 05:12:47PM +1000, Larry Hastings <larry@hastings.org> wrote:
In my very humble opinion, "nullable" is ok, but "allow_none" is better. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.

On 4 Aug 2014 18:16, "Oleg Broytman" <phd@phdru.name> wrote:
Hi!
On Mon, Aug 04, 2014 at 05:12:47PM +1000, Larry Hastings <
larry@hastings.org> wrote:
Yup, this is where I stand as well. The main concern I have with nullable is that we *are* writing C code when dealing with Argument Clinic, and "nullable" may make me think of a C NULL rather than Python's None. Cheers, Nick.
https://mail.python.org/mailman/options/python-dev/ncoghlan%40gmail.com

I admit I spent the first half of the email scratching my head and trying to figure out what NULL had to do with argument clinic specs. (Maybe it would mean that if the argument is "not given" in some appropriate way then we set the corresponding C variable to NULL?) Finding out you were talking about None came as a surprising twist. -n On 4 Aug 2014 08:13, "Larry Hastings" <larry@hastings.org> wrote:

On Mon, Aug 4, 2014 at 12:57 PM, Ethan Furman <ethan@stoneleaf.us> wrote:
'allow_none' is definitely clearer.
I disagree. Unlike "nullable", "allow_none" does not tell me what happens on the C side when I pass in None. If the receiving type is PyObject*, either NULL or Py_None is a valid choice.

On Mon, Aug 4, 2014 at 1:53 PM, Antoine Pitrou <antoine@python.org> wrote:
We cannot "allow None" when the receiving type is C int. In this case, we need a way to implement "nullable int" type in C. We can use int * or a pair of int and _Bool or anything else. Whatever the implementation, the concept that is implemented is "nullable int." The advantage of using the term "nullable" is that it is language and implementation neutral.

On 08/05/2014 03:53 AM, Antoine Pitrou wrote:
Just to be precise: in the case where the receiving type *would* have been an int, and "nullable=True", the receiving type is actually a structure containing an int and a "you got a None" flag. I can't stick a magic value in the int and say "that represents you getting a None" because any integer value may be valid. Also, I'm pretty sure there are places in builtin argument parsing that accept either NULL or Py_None, and I *think* maybe in one or two of them they actually mean different things. What fun! For small values of "fun", //arry/

Am 04.08.14 09:12, schrieb Larry Hastings:
I have personally no problems with calling a type "nullable" even in Python, and, as a type *adjective* this seems to be the right choice (i.e. I wouldn't say "noneable int" or "allow_none int"; the former is no established or intuitive term, the latter is not an adjective). As a type *flag*, flexibility in naming is greater. zeroes=True formally creates a subtype (of string), and it doesn't hurt that it is not an adjective. "allow_zeroes" might be more descriptive. bitwise=True doesn't really create a subtype of int. For the feature in question, I find both "allow_none" and "nullable" acceptable; "noneable" is not. Regards, Martin

On 08/05/2014 08:13 AM, "Martin v. Löwis" wrote:
For the feature in question, I find both "allow_none" and "nullable" acceptable; "noneable" is not.
Well! It's rare that the core dev community is so consistent in its opinion. I still think "nullable" is totally appropriate, but I'll change it to "allow_none". //arry/

On 08/07/2014 09:41 PM, Larry Hastings wrote:
(reviving eight-month-old thread) In case anybody here is still interested in arguing about this: the Clinic API may be shifting a bit here. What follows is a quick refresher course on Argument Clinic, followed by a discussion of the proposed new API. Here's an Argument Clinic declaration of a parameter: s: str() The parameter is called "s", and it's specifying a converter function called "str" which handles converting string parameters. The str() converter itself accepts parameters; since the parameters all have default values, they're all optional. By default, str() maps directly to the "s" format unit for PyArg_ParseTuple(), as it does here. Currently str() (and a couple other converter functions) accepts a parameter called "types". "types" is specified as a string, and contains an unordered set of whitespace-separated strings representing the Python types of the values this (Clinic) parameter should accept. The default value of "types" for str() is "str"; the following declaration is equivalent to the declaration above: s: str(types="str") Other legal values for the "types" parameter for the str converter include "bytes bytearray str" and "robuffer str". Internally the types parameter is converted into a set of strings; passing it in as a string is a nicety for the caller's benefit. (It also means that the strings "robuffer str" and "str robuffer" are considered equivalent.) There's a second parameter, currently called "nullable", but I was supposed to rename it "allow_none", so I'll use that name here. If you pass in "allow_none=True" to a converter, it means "this (Clinic) parameter should accept the Python value None". So, to map to the format unit "z", you would specify: s: str(allow_none=True) And to map to the format unit "z#", you would specify: s: str(types="robuffer str", allow_none=True, length=True) In hindsight this is all a bit silly. I propose what I think is a much better API below. We should rename "types" to "accept". "accept" should takes a set of types; these types specify the types of Python objects the Clinic parameter should accept. For the funny pseudo-types needed in some Clinic declarations ("buffer", "robuffer", and "rwbuffer"), Clinic provides empty class declarations so these behave like types too. accept={str} is the default for the str() converter. If you want to map to format unit "z", you would write this: s: str(accept={str, NoneType}) (In case you haven't seen it before: NoneType = type(None). I don't think the name is registered anywhere officially in the standard library... but that's the name.) The upside of this approach: * Way, way more obvious to the casual reader. "types" was always meant as an unordered collection of types, but I felt specifying it with strings was unwieldy and made for poor reading ({'str', 'robuffer'}). Passing it in as a single string which I internally split and put in a set() was a bad compromise. But the semantics of this whitespace-delimited string were a bit unclear, even to the experienced Clinic hacker. This set-of-types version maps exactly to what the parameter was always meant to accept in the first place. As with any other code, people will read Clinic declarations far, far more often than they will write them, so optimizing for clarity is paramount. * Zen: "There should be one (and preferably only one) obvious way to do it." We have a way of specifying the types this parameter should accept; "allow_none" adds a second. * Zen: "Special cases aren't special enough to break the rules". "allow_none" was really just a special case of one possible type for "types". The downside of this approach: * You have to know what the default accept= set is for each converter. Luckily this is not onerous; there are only four converters that need an "accept" parameter, and their default values are all simple: int(accept={int}) str(accept={str}) Py_UNICODE(accept={str}) Py_buffer(accept={buffer}) I suggest this is only a (minor) problem when writing a Clinic declaration. It doesn't affect later readability, which is much more important. * It means repeating yourself a little. If you just want to say "I want to accept None too", you have to redundantly specify the default type(s) accepted by the converter function. In practice, it's really only redundant for four or five format units, and they're not the frequently-used ones. Right now I only see three uses of nullable for the built-in format units (there are two more for my path_converter) and they're all for the str converter. Yes, we could create a set containing the default types accepted by each converter function, and just let the caller specify that and incrementally add +{NoneType}. But this would be far longer than simply redundantly respecifying the default (e.g. "accept=str_converter.accept_default + {NoneType}"). Sometimes the best thing is just to bite the bullet and accept a little redundancy. Does "accept" sound good, including accepting "NoneType"? FWIW I originally proposed this in an issue on the tracker: http://bugs.python.org/issue23920 But we should probably continue the discussion here. Cheers, //arry/ p.s. Yes, I never actually got around to renaming "nullable". But I was going to get it done before beta, honest. And anyway remembering to do that is what led me down this path, which I think has been fruitful in its own right.

On 4/19/2015 1:19 AM, Larry Hastings wrote:
Is argument clinic a special case of type annotations? (Quoted and worded to be provocative, intentionally but not maliciously.) OK, I know that argument clinic applies to C code and I know that type annotations apply to Python code. And I know that C code is a lot more restrictive /a priori/ which clinic has to accommodate, and type annotations are a way of adding (unenforced) restrictions on Python code. Still, from a 50,000' view, there seems to be an overlap in functionality... and both are aimed at Py 3.5... I find that interesting... I guess describing parameter types is the latest Python trend :)

On 04/19/2015 01:26 PM, Glenn Linderman wrote:
Argument Clinic and Python 3 type annotations are related concepts. Argument Clinic's syntax is designed in such a way that we actually use ast.parse() to parse it, and that includes using the type annotation syntax. That's about all they have in common. This discussion is off-topic and of limited interest; if you have further questions along these lines please email me privately. //arry/

On Apr 19, 2015, at 01:19 AM, Larry Hastings wrote:
Having only followed the AC discussions tangentially, I have to say that the above suggestion and the given examples make a lot more intuitive sense to me. I had the same initial thought as Glenn regarding type annotations. It's fine that they're separate concepts, but it's also helpful that Larry's suggestion above seems to align them better. Cheers, -Barry

On Sun, Apr 19, 2015 at 11:19 AM, Larry Hastings <larry@hastings.org> wrote:
"Accept" sounds great to me. Allowing a parameter to be None by specifying NoneType is logical and so makes a certain amount of sense. It seems to me that this approach will make it very common to have parameter declarations of the form "int(accept={int, NoneType})" in the stdlib. I'm conflicted whether this is better or worse than "int(allow_none=True)". The former makes it clear that the parameter can accept more than a single type, necessitating additional processing to check what the actual type of the passed value is, which I like. So I'm +0.5 for this at the moment. As for the default set of accepted types for various convertors, if we could choose any syntax we liked, something like "accept=+{NoneType}" would be much better IMO. I'm definitely against repeating the default set of accepted types, since this would require very wide changes whenever the default set of types for a convertor is changed, as well as breaking compatibility for 3rd party libraries using AC. - Tal

On 04/21/2015 04:50 AM, Tal Einat wrote:
In theory Argument Clinic could use any syntax it likes. In practice, under the covers we tease out one or two bits of non-Python syntax, then run ast.parse over it. Saved us a lot of work. "s: accept={str,NoneType}" is a legal Python parameter declaration; "s: accept+={NoneType}" is not. If I could figure out a clean way to hack in support for += I'll support it. Otherwise you'll be forced to spell it out. //arry/

On 22 April 2015 at 03:31, Larry Hastings <larry@hastings.org> wrote:
Ellipsis seems potentially useful here to mean "whatever the default accepted types are": "s: accept={...,NoneType}" My other question would be whether we can use "None" in preference to NoneType, as PEP 484 does: https://www.python.org/dev/peps/pep-0484/#using-none Cheers, Nick. -- Nick Coghlan | ncoghlan@gmail.com | Brisbane, Australia

On 04/24/2015 09:45 PM, Nick Coghlan wrote:
Ah, I misread Tal's suggestion. Using unary + is an even neater approach.
Not exactly. The way I figure it, the best way to achieve this with unary plus is to ast.parse it (as we currently do) and then modify the parse tree. That works but it's kind of messy. My main objection to this notation is that that set objects /don't support +./ The union operator for sets is |. I've prototyped a hack allowing str(accept|={NoneType}) I used the tokenize module to tokenize, modify, and untokenize the converter invocation. Works fine. And since augmented assignment is (otherwise) illegal in expressions, it's totally unambiguous. I think if we do it at all it should be with that notation. //arry/
participants (13)
-
"Martin v. Löwis"
-
Alexander Belopolsky
-
Antoine Pitrou
-
Barry Warsaw
-
Ethan Furman
-
Glenn Linderman
-
Gregory P. Smith
-
Larry Hastings
-
Nathaniel Smith
-
Nick Coghlan
-
Oleg Broytman
-
Stephen Hansen
-
Tal Einat