[Python-Dev] Re: Merging PRs without CLA signed
My personal stance is if Microsoft Word could have come up with the change then a signed CLA is _probably_ not needed (IOW typos and grammatical errors). But honestly, I fall into the same camp as Mariatta and Pablo out of laziness and fear of being wrong. :) Laziness because there are plenty of other people willing to sign the CLA and participate fully that I would rather help out with my limited open source time. Out of fear because I don't want to get this wrong and be the reason the PSF gets sued some day. Personally, I hope we move to CLA Assistant (or improve the-knights-who-say-ni to be as usable) and then make CLA signing a required status check on PRs to negate having to think about this. ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/QQYQSI3X26IK23MJPEQJKYNLTVZSVHP3/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Accepting PEP 584: Add Union Operators To dict
Thanks for your response Serhiy. > Yes, but this is a different thing. You must to implement new __or__ in a > subclass to make the behavior of d1 | d2 be different from {**d1, **d2}. Really? I'm sorry, but this doesn't feel like a real argument to me. There was no clear compatible path before. Now there is. It works by default, returning a dict for dict subclasses. If you want to change the return type (or do something else), you do have to do a little work. Same for every other overridden thing in any other subclass. Besides, our argument was just the opposite: "you can't implement anything in a subclass to make the type of {**d1, **d2} be different". Now that we've provided a way, it's a problem because you have to define custom behavior (if you want it)? > you want an operation for merging OrderedDict, defaultdict, etc and add > dict.__or__ just for symmetry, even if it is not actually necessary for dicts. Except that now every dict subclass gets this for free. And now everything quacks alike. Are you really suggesting that it would make more sense to implement this for all subclasses, but not dict itself? I don't think you are, but it sure sounds like it. > Let's take a closer look at these examples. I appreciate that you've taken the time to go through each one, but please note that the PEP finishes with: > The above examples show that sometimes the | operator leads to a clear > increase in readability... However other examples using the | operator lead > to long, complex single expressions... As with any other language feature, > the programmer should use their own judgement about whether | improves their > code. We're not suggesting that all of the examples would be better, or even equivalent with the new code. During the discussions last year, people kept asking for before-and-after examples. We decided to extract real examples rather than fabricate toys, so for the purposes of this PEP you can assume that they stand on their own, void of context. For example, I considered removing the `globs` example because, like you, I thought it was uglier. However, I figured that it would be wrong to omit it, since the goal of the section was to show as many candidates for the operator that we could trivially find, not "all of the ones that Brandt likes better with |". :) I'm not sure that continuing this thread of discussion is very productive. As I have mentioned before, the huge PEP is roughly: - 50% responses to arguments. - 35% examples. - 10% specification. - 5% links to prior discussions. We've addressed anything that we felt needed addressing, and they have been enough to persuade the necessary decision makers. Many of the points you make have been responded to in some way or another in this monster of a document. :) ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/RHFTVX7IV7VG3GLEVE4ZWOIHTCB2JQBK/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Unpacking native bools in the struct module: Is Python relying on undefined behavior?
> Quick and obvious fix: > > static PyObject * > nu_bool(const char *p, const formatdef *f) > { > char x; > memcpy((char *), p, sizeof x); > return PyBool_FromLong(x != 0); > } Which is optimized to static PyObject * nu_bool(const char *p, const formatdef *f) { return PyBool_FromLong(*p != 0); } ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/L6F66QMZHEG3TOIC2ERDFDUXHRSITUMZ/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Unpacking native bools in the struct module: Is Python relying on undefined behavior?
On Thu, Feb 27, 2020 at 10:51:39AM -0500, Charalampos Stratakis wrote: > Hello folks, > > I recently observed a failure on the s390x fedora rawhide buildbot, on the > clang builds, when clang got updated to version 10: > https://bugs.python.org/issue39689 > > The call: > struct.unpack('>?', b'\xf0') > means to unpack a "native bool", i.e. native size and alignment. Internally, > this does: > > static PyObject * > nu_bool(const char *p, const formatdef *f) > { > _Bool x; > memcpy((char *), p, sizeof x); > return PyBool_FromLong(x != 0); > } > > i.e., copies "sizeof x" (1 byte) of memory to a temporary buffer x, and then > treats that as _Bool. > > While I don't have access to the C standard, I believe it says that > assignment of a true value to _Bool can coerce to a unique "true" value. It > seems that if a char doesn't have the exact bit pattern for true or false, > casting to _Bool is undefined behavior. Is that correct? > > Clang 10 on s390x seems to take advantage of this: it probably only looks at > the last bit(s) so a _Bool with a bit pattern of 0xf0 turns out false. > But the tests assume that 0xf0 should unpack to True. I don't think it's specific to Clang 9, or the s390x arch. Have a look to https://godbolt.org/z/3n-LqN clang indeed just checks for the lowest bit. Is it correct? I think so. _Bool can only holds two value, 0 and 1, [0] which is different from an int whose value is true or false whether its different or equal to 0. GCC and Clang agree on that: https://godbolt.org/z/koc4Pb So yeah, according to that rule, the value set in `p` wasn't from a _Bool if it has the 0xf0 value. So you're re-interepreting memory between two different types type-punning, and that's UB. Quick and obvious fix: static PyObject * nu_bool(const char *p, const formatdef *f) { char x; memcpy((char *), p, sizeof x); return PyBool_FromLong(x != 0); } [0] the standard says 6.3.1.2 Boolean type When any scalar value is converted to_Bool,the result is 0 if the value compares equalto 0; otherwise, the result is 1. ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/S24XTMGGHJCN2FRZJWVHM5ZRMN3QORPK/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Unpacking native bools in the struct module: Is Python relying on undefined behavior?
On 2020-02-27 17:14, Serge Guelton wrote: On Thu, Feb 27, 2020 at 10:51:39AM -0500, Charalampos Stratakis wrote: Hello folks, I recently observed a failure on the s390x fedora rawhide buildbot, on the clang builds, when clang got updated to version 10: https://bugs.python.org/issue39689 The call: struct.unpack('>?', b'\xf0') means to unpack a "native bool", i.e. native size and alignment. Internally, this does: static PyObject * nu_bool(const char *p, const formatdef *f) { _Bool x; memcpy((char *), p, sizeof x); return PyBool_FromLong(x != 0); } i.e., copies "sizeof x" (1 byte) of memory to a temporary buffer x, and then treats that as _Bool. While I don't have access to the C standard, I believe it says that assignment of a true value to _Bool can coerce to a unique "true" value. It seems that if a char doesn't have the exact bit pattern for true or false, casting to _Bool is undefined behavior. Is that correct? Clang 10 on s390x seems to take advantage of this: it probably only looks at the last bit(s) so a _Bool with a bit pattern of 0xf0 turns out false. But the tests assume that 0xf0 should unpack to True. I don't think it's specific to Clang 9, or the s390x arch. Have a look to https://godbolt.org/z/3n-LqN clang indeed just checks for the lowest bit. Is it correct? I think so. _Bool can only holds two value, 0 and 1, [0] which is different from an int whose value is true or false whether its different or equal to 0. GCC and Clang agree on that: https://godbolt.org/z/koc4Pb So yeah, according to that rule, the value set in `p` wasn't from a _Bool if it has the 0xf0 value. So you're re-interepreting memory between two different types type-punning, and that's UB. Quick and obvious fix: static PyObject * nu_bool(const char *p, const formatdef *f) { char x; memcpy((char *), p, sizeof x); return PyBool_FromLong(x != 0); } (This assumes size of _Bool is the same as size of char, which I guess is also UB? But I guess we can add a build-time assertion for that, and say we don't support platforms where that's not the case.) So thanks! I'm left with a question for CPython's struct experts, which is better kept to the bug tracker: https://bugs.python.org/issue39689#msg362815 ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/364VZPYLOTVTXD6SXH4T4E36K25WM4B2/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Unpacking native bools in the struct module: Is Python relying on undefined behavior?
Hello folks, I recently observed a failure on the s390x fedora rawhide buildbot, on the clang builds, when clang got updated to version 10: https://bugs.python.org/issue39689 The call: struct.unpack('>?', b'\xf0') means to unpack a "native bool", i.e. native size and alignment. Internally, this does: static PyObject * nu_bool(const char *p, const formatdef *f) { _Bool x; memcpy((char *), p, sizeof x); return PyBool_FromLong(x != 0); } i.e., copies "sizeof x" (1 byte) of memory to a temporary buffer x, and then treats that as _Bool. While I don't have access to the C standard, I believe it says that assignment of a true value to _Bool can coerce to a unique "true" value. It seems that if a char doesn't have the exact bit pattern for true or false, casting to _Bool is undefined behavior. Is that correct? Clang 10 on s390x seems to take advantage of this: it probably only looks at the last bit(s) so a _Bool with a bit pattern of 0xf0 turns out false. But the tests assume that 0xf0 should unpack to True. -- Regards, Charalampos Stratakis Software Engineer Python Maintenance Team, Red Hat ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/O742VLCYX2AE3RWQK5RBQ3BGUOHESLF5/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Accepting PEP 584: Add Union Operators To dict
Let me split my case into two points: 1) The intuition that the right-hand side of `a | b` is a fallback value 2) The claim that `a |= b` is a common idiom to assign defaults About 2) It appears that the idiom in 2) is less common than I assumed. My expectations were shaped by working with a C++ codebase where the `|=` operator was sometimes overloaded in such a way (since there is no `||=` operator in this language). Unfortunately, I have not found similar uses of `|=` elsewhere (e.g. in Boost). To illustrate this with a specific case nonetheless, that C++ codebase had a generic data type modelled after Haskell's Maybe. In Haskell, `Maybe a` is a type which can be empty (`Nothing`) or hold a value (`Just a`). In the C++ implementation, the operation `a |= b` would assign `just(b)` iff `a` was not empty. About 1) I still believe that there is an intuition that the right operand of `|` is a fallback value, and this intuition may lead people to wrong use of dict unions. To make this intuition more explicit: Consider other operations that behave like OR in a Boolean algebra, such as logical OR, and set union. Conceptually, these operations perform one or multiple checks on the left operand, and only consider the right operand if the check "failed". - With logical OR, short-circuit semantics are widespread (cf. C, UNIX shell, or Python itself). The right operand is only evaluated if the left operand evaluates to false in a Boolean context. - With set union, implementations typically start by copying the left operand, and add entries from the right operand if they are not already present in the copy. This is also what CPython does in `set_union` (via `set_add_entry`). As another case in point, overriding items from the right operand is already provided by `dict.update`. A `|=` operator which provides for the complementary operation of filling in missing items would have made for a more orthogonal set of operations. When formulated in terms of `|`, the two operations only differ in the order of operands. > Here's our current proposal for docs. Is there anything you'd like to add? > https://github.com/python/cpython/pull/18659/files I find this quite clear. It already points out the behaviour in question. To conclude, different semantics for dict union would have been preferable in my view, but I guess that ship has sailed. Other than changing dict union semantics I don't think there is anything actionable left here. Maybe my input still has some value in clarifying expectations some users may have for this new feature. Thank you for your openness about this late input to the discussion. On Thu, 27 Feb 2020 at 10:35, Kyle Stanley wrote: > > So I've also never come across "|=" being used for this purpose. > > IIRC, the JavaScript implementation of "|=" can potentially be used in the > way Claudio described it, instead it's based on the truthiness of the > left-hand operand rather than it being "unset". But it works in that > context because "null" and "undefined" are considered falsey [1]. For > example: > > > var value = null; > > var other = 2; > > value |= other; > > console.log(value); > 2 > > So it effectively works like "value | other", but also sets "value" to > "other" iff "value" is falsey. When the left-hand operand is truthy, it > effectively does nothing. > > > var value = 3; > > var other = 2; > > value |= other; > > console.log(value); > 3 > > Also worth noting, since "value |= other" translates to "value = value | > other", it works as a bitwise OR operator; not as a catch-all for assigning > a default value: > > > var value = null; > > var other = "test"; > > value |= other; > > console.log(value); > 0 > > Instead, you'd have to use the standard OR operator, like this "value = > value || other" (since "||=" is invalid syntax): > > > var value = null; > > var other = "test"; > > value = value || other; > > console.log(value); > test > > FWIW, I have very rarely seen "|=" used as an operator in JS, but I've > seen "value = value || other" used a decent amount. > > --- > > [1] - https://developer.mozilla.org/en-US/docs/Glossary/Falsy > > > > On Wed, Feb 26, 2020 at 6:26 PM Nick Coghlan wrote: > >> >> >> On Thu., 27 Feb. 2020, 2:03 am Guido van Rossum, >> wrote: >> >>> On Wed, Feb 26, 2020 at 7:43 AM Claudio Jolowicz >>> wrote: >>> In my experience, the expression `value |= other` is a common idiom across programming languages to provide a default for `value` if it is "unset". >>> >>> Interesting. Can you point to specific examples of this? In what other >>> languages have you seen this? (Not that it would make us change PEP 584, >>> but if this appears common we could probably warn about it prominently in >>> docs and tutorials.) >>> >> >> I was thinking that bash scripting might be an example, but I double >> checked, and that's spelled 'VAR="${$VAR:-default value}" ' >> >> make has 'VAR ?= "default value"' >> >> C# uses "??=" for null
[Python-Dev] Re: Accepting PEP 584: Add Union Operators To dict
On Thu, Feb 27, 2020 at 8:15 PM Serhiy Storchaka wrote: > > 27.02.20 10:46, Chris Angelico пише: > > On Thu, Feb 27, 2020 at 7:41 PM Serhiy Storchaka > > wrote: > >> sympy/utilities/runtests.py > >> > >> Sorry, but the current code > >> > >> globs = globs.copy() > >> if extraglobs is not None: > >> globs.update(extraglobs) > >> > >> looks much clearer to me than the proposed > >> > >> globs = globs | (extraglobs if extraglobs is not None else {}) > > > > Is there a reason for not writing it as: > > > > globs = globs | (extraglobs or {}) > > > > ? That reads fairly well to me. > > Sure. Although it would work different if extraglobs is a false value > different from None, empty mapping and iterable. Yes, technically it's different. But other than this silently ignoring errors like passing 0 rather than None, it's unlikely to have any material difference. > But if we ignore such > subtle details, it could be written also as > > globs = {**globs, **(extraglobs or {})} Yeah, but now I think the pipe syntax has a definite advantage. ChrisA ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/JR3T3GFE3L6BWI7WVZ5OEOU6NCRRQRLY/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Accepting PEP 584: Add Union Operators To dict
> So I've also never come across "|=" being used for this purpose. IIRC, the JavaScript implementation of "|=" can potentially be used in the way Claudio described it, instead it's based on the truthiness of the left-hand operand rather than it being "unset". But it works in that context because "null" and "undefined" are considered falsey [1]. For example: > var value = null; > var other = 2; > value |= other; > console.log(value); 2 So it effectively works like "value | other", but also sets "value" to "other" iff "value" is falsey. When the left-hand operand is truthy, it effectively does nothing. > var value = 3; > var other = 2; > value |= other; > console.log(value); 3 Also worth noting, since "value |= other" translates to "value = value | other", it works as a bitwise OR operator; not as a catch-all for assigning a default value: > var value = null; > var other = "test"; > value |= other; > console.log(value); 0 Instead, you'd have to use the standard OR operator, like this "value = value || other" (since "||=" is invalid syntax): > var value = null; > var other = "test"; > value = value || other; > console.log(value); test FWIW, I have very rarely seen "|=" used as an operator in JS, but I've seen "value = value || other" used a decent amount. --- [1] - https://developer.mozilla.org/en-US/docs/Glossary/Falsy On Wed, Feb 26, 2020 at 6:26 PM Nick Coghlan wrote: > > > On Thu., 27 Feb. 2020, 2:03 am Guido van Rossum, wrote: > >> On Wed, Feb 26, 2020 at 7:43 AM Claudio Jolowicz >> wrote: >> >>> In my experience, the expression `value |= other` is a common idiom >>> across >>> programming languages to provide a default for `value` if it is "unset". >>> >> >> Interesting. Can you point to specific examples of this? In what other >> languages have you seen this? (Not that it would make us change PEP 584, >> but if this appears common we could probably warn about it prominently in >> docs and tutorials.) >> > > I was thinking that bash scripting might be an example, but I double > checked, and that's spelled 'VAR="${$VAR:-default value}" ' > > make has 'VAR ?= "default value"' > > C# uses "??=" for null coalescence on assignment. > > So I've also never come across "|=" being used for this purpose. > > Cheers, > Nick. > >> ___ > Python-Dev mailing list -- python-dev@python.org > To unsubscribe send an email to python-dev-le...@python.org > https://mail.python.org/mailman3/lists/python-dev.python.org/ > Message archived at > https://mail.python.org/archives/list/python-dev@python.org/message/HMKYUZP5T6HTURG46GU3L72KANB65MLQ/ > Code of Conduct: http://python.org/psf/codeofconduct/ > ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/FOL22B6MXU65P2T3M6CCMYVZSSSWR2PO/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Accepting PEP 584: Add Union Operators To dict
27.02.20 10:46, Chris Angelico пише: On Thu, Feb 27, 2020 at 7:41 PM Serhiy Storchaka wrote: sympy/utilities/runtests.py Sorry, but the current code globs = globs.copy() if extraglobs is not None: globs.update(extraglobs) looks much clearer to me than the proposed globs = globs | (extraglobs if extraglobs is not None else {}) Is there a reason for not writing it as: globs = globs | (extraglobs or {}) ? That reads fairly well to me. Sure. Although it would work different if extraglobs is a false value different from None, empty mapping and iterable. But if we ignore such subtle details, it could be written also as globs = {**globs, **(extraglobs or {})} ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/UYJ5VMSQPSS5WINGUWTTGI24IXJ6ABRC/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Accepting PEP 584: Add Union Operators To dict
On Thu, Feb 27, 2020 at 7:41 PM Serhiy Storchaka wrote: > sympy/utilities/runtests.py > > Sorry, but the current code > > globs = globs.copy() > if extraglobs is not None: > globs.update(extraglobs) > > looks much clearer to me than the proposed > > globs = globs | (extraglobs if extraglobs is not None else {}) Is there a reason for not writing it as: globs = globs | (extraglobs or {}) ? That reads fairly well to me. ChrisA ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/NSRSC3EDS7JLWZKBIXWBI46WW36PMZNU/ Code of Conduct: http://python.org/psf/codeofconduct/
[Python-Dev] Re: Accepting PEP 584: Add Union Operators To dict
18.02.20 19:35, Brandt Bucher пише: ...it was decided that `d1 | d2` also should ignore the types of the operands and always return a dict. And it accepts only dicts, not general mappings, in difference to `{**d1, **d2}`. So the only disadvantage of `{**d1, **d2}` is that it is not well known and "looks ugly". Not quite. While this point *has* been weakened a bit with the recent semantic change, you don't mention that `dict` subclasses can (and likely would) override the `__or__` trio with wrapped `super()` calls. So while `{**d1, **d2}` will *never* be anything but a `dict`, I can trust that well-written `dict` subclasses my code encounters will still be able to preserve themselves with `d1 | d2`, if desired. Yes, but this is a different thing. You *must* to implement new `__or__` in a subclass to make the behavior of `d1 | d2` be different from `{**d1, **d2}`. Actually, there was already an example -- Counter. It is not an argument for implementing `__or__` in dict. It is an argument for implementing `__or__` in other classes. So to add a value to it you have to look at from from the opposite side: you want an operation for merging OrderedDict, defaultdict, etc and add `dict.__or__` just for symmetry, even if it is not actually necessary for dicts. The pure-Python implementation of the non-inplace operator can be simpler if use dict unpacking. The purpose of the pure-Python implementation in the PEP is to be a clear, understandable example that serves as a codification of the semantics, not to be the shortest one-liner. The suggested changes make the code less readable, making it harder to see exactly what will happen if I do `self | other`. I'm against changing it, for that reason. Agree, the current code makes easier to implement such operations in other mapping classes. Regarding the commonality of this operation, we've provided eighteen detailed examples of third-party library code that are candidates for these new operators. To the best of my knowledge, a large survey like this is unprecedented in a PEP. Whether or not it is more common than a different operation on other types isn't relevant here. We have gone above and beyond in demonstrating the use cases in detail. Let's take a closer look at these examples. Unfortunately the PEP does not provide links to the original code, so the context is not always known. IPython/zmq/ipkernel.py IPython/zmq/kernelapp.py matplotlib/delaunay/triangulate.py numpy/ma/core.py praw/internal.py pygments/lexer.py sphinx/highlighting.py sphinx/quickstart.py sympy/abc.py sympy/parsing/maxima.py sympy/printing/ccode.py and sympy/printing/fcode.py In almost all examples it is guaranteed that the result is a dict. You create a dict by calling dict() or using dict display and then update it. So the form `{**d1, **d2}` can be used in all these cases. In some examples, like in praw/internal.py, it may be especially good: data = {'name': six.text_type(user), 'type': relationship, **kwargs} In some cases, like in sympy/abc.py the proposed transformation is just not correct if arguments have overridden `__or__`. Currently it is guaranteed that the result is a dict, but with proposed code it is no longer true. matplotlib/legend.py sphinx/domains/__init__.py sphinx/ext/doctest.py sphinx/ext/inheritance_diagram.py In these cases you merge a user provided dict with some default value which is a dict by default, but may be overridden in subclasses. Although it is unlikely. matplotlib/backends/backend_svg.py The current code uses `{**attrib, **extra}`. https://github.com/matplotlib/matplotlib/blob/master/lib/matplotlib/backends/backend_svg.py#L155 requests/sessions.py The proposed transformation makes the code less efficient -- it makes redundant copying. sympy/utilities/runtests.py Sorry, but the current code globs = globs.copy() if extraglobs is not None: globs.update(extraglobs) looks much clearer to me than the proposed globs = globs | (extraglobs if extraglobs is not None else {}) ___ Python-Dev mailing list -- python-dev@python.org To unsubscribe send an email to python-dev-le...@python.org https://mail.python.org/mailman3/lists/python-dev.python.org/ Message archived at https://mail.python.org/archives/list/python-dev@python.org/message/V6HCC6F2EQZTZ5JKPPMWFJNYO6HNGTJY/ Code of Conduct: http://python.org/psf/codeofconduct/