Re: [Python-Dev] PEP 506 secrets module
On Sat, Oct 17, 2015 at 03:26:46AM +1100, Steven D'Aprano wrote: > On Fri, Oct 16, 2015 at 06:35:14PM +0300, Serhiy Storchaka wrote: > > > I suggest to add only randrange(). randint() is historical artefact, we > > shouldn't repeat this mistake in new module. The secrets module is not > > good way to generate dice rolls. In most other cases you need to > > generate integers in half-open interval [0; N). > > > > And randbelow() is absolute redundant. Random._randbelow() is > > implementation detail and I inclined to get rid of it (implementing > > randrange() in C instead). > > This was discussed on Python-Ideas, and there was little consensus there > either. (Looks like Tim Peters' prediction is coming true :-) [...] > I've also raised this issue on the python-list mailing list. I've had some feedback on python-list. To summarise the various positions expressed so far: randbelow only: 3 in favour randint only: 1 neutral (neither opposed nor in favour) randrange only: 1 in favour, 1 against both randrange and randint: 2 in favour (Total number of comments is more than the total number of posts, as some people expressed more than one opinion in the same post. As in, "I prefer X, but Y would be good too".) So you can see there is nothing even close to consensus as to which API is best, which is an argument for keeping all three functions. But significanly, only *one* of the commenters has claimed to have any significant experience in crypto work, and I will quote him: Having done quite a bit of serious crypto implementation over the past 25 years, I don't recall ever wanting anything like randrange, and if I did need it, I'd probably build it inline from randbelow rather than force some hapless future code maintainer to look up the specs on randrange. My opinion, FWIW: I like randbelow, because in modern crypto one very frequently works with integers in the range [0,M-1] for some large modulus M, and there is a constant risk of asking for something in [0,M] when one meant [0,M-1]. One can eliminate this risk, as randbelow does, by building in the -1, which normally introduces a risk of making a mistake that gives you [0,M-2], but the name "randbelow" seems like a neat fix to that problem. -- Peter Pearson This matches what Serhiy suggests: in crypto, one normally only needs to generate the half-open interval [0...n). It also matches the reason why Tim Peters added randbelow in the first place. As the author of the PEP, I'm satisfied by this argument, and will now state that my preferred option is to drop randint and randrange, and just keep randbelow. My second choice is to keep all three functions. I think it is fair to say that out of the three functions, there is consensus that randbelow has the most useful functionality in a crypto context. Otherwise, people seem roughly equally split between the three functions. There doesn't seem to be any use-case for the three argument version of randrange. -- Steve ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Conversion of a standard unicode string to a bit string in Python
Hi All, I'm currently programming a set of crypto challenges in order to get a deeper understanding of python and crypto. The problem is to break a repeating key xor data (in a file). In order to do that I need a function to calculate the hamming distance between two strings. To find that one needs to find the differing number of *bits* in a string. Any ideas on how to manipulate the string at bit level? This is my first time in writing a question to the mailing list so please let me know anything that I need to keep in mind while asking questions. Thanks in advance. Gracias Nemo ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 506 secrets module
> On Sat, Oct 17, 2015 at 03:26:46AM +1100, Steven D'Aprano wrote: [snip] > But significanly, only *one* of the commenters has claimed to have > any significant experience in crypto work, and I will quote him: I didn't specifically claim the experience you requested in responding to your post on comp.lang.python because I thought that this was implied in making a response. In fact I have 30+ years of experience in implementing cryptographic code (much involving random numbers) so there were at least two respondents who could have made this claim. For the record, I consider it desirable in code involving security to exhibit the minimum functionality neccessary to get a job done. This is because funtionality and security very often work against each other in building secure systems. I hence support your conclusion that the module should offer randbelow alone. I would oppose offering randomrange (or offering more than one of them) since this will pretty well guarantee that, sooner or later, someone will make a mistake in using the extra functionality and possibly deploy an insecure application as a result. Brian Gladman ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Conversion of a standard unicode string to a bit string in Python
This list is for discussion of development of the Python core language and standard libraries, not for development *using* Python. It sounds like you should probably do your homework problem on your own, actually, but if you seek advice, something like StackOverflow or python-list are likely to be more appropriate. On Sat, Oct 17, 2015 at 6:22 AM, Nemo Nautilius wrote: > Hi All, > I'm currently programming a set of crypto challenges in order to get a > deeper understanding of python and crypto. The problem is to break a > repeating key xor data (in a file). In order to do that I need a function > to calculate the hamming distance between two strings. To find that one > needs to find the differing number of *bits* in a string. Any ideas on how > to manipulate the string at bit level? > > This is my first time in writing a question to the mailing list so please > let me know anything that I need to keep in mind while asking questions. > Thanks in advance. > > Gracias > Nemo > > ___ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/mertz%40gnosis.cx > > -- Keeping medicines from the bloodstreams of the sick; food from the bellies of the hungry; books from the hands of the uneducated; technology from the underdeveloped; and putting advocates of freedom in prisons. Intellectual property is to the 21st century what the slave trade was to the 16th. ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 506 secrets module
Brian Gladman writes: >> On Sat, Oct 17, 2015 at 03:26:46AM +1100, Steven D'Aprano wrote: > I hence support your conclusion that the module should offer randbelow > alone. I would oppose offering randomrange (or offering more than one > of them) since this will pretty well guarantee that, sooner or later, > someone will make a mistake in using the extra functionality and > possibly deploy an insecure application as a result. > >Brian Gladman Plus if someone really does want randrange, they can simply do this: def randfrom(seq): return seq[randbelow(len(seq))] def randrange(start, stop, step=None): randfrom(range(start, stop, step)) These are simple recipes that probably don't belong in the module. ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 506 secrets module
On Sat, Oct 17, 2015 at 2:50 AM, Steven D'Aprano wrote: > [...] > So you can see there is nothing even close to consensus as to which API > is best, which is an argument for keeping all three functions. > No, that's not how we do it in Python. :-) > But significanly, only *one* of the commenters has claimed to have any > significant experience in crypto work, and I will quote him: > > Having done quite a bit of serious crypto implementation over the > past 25 years, I don't recall ever wanting anything like randrange, > and if I did need it, I'd probably build it inline from randbelow > rather than force some hapless future code maintainer to look up the > specs on randrange. > > My opinion, FWIW: I like randbelow, because in modern crypto one > very frequently works with integers in the range [0,M-1] for some > large modulus M, and there is a constant risk of asking for > something in [0,M] when one meant [0,M-1]. One can eliminate this > risk, as randbelow does, by building in the -1, which normally > introduces a risk of making a mistake that gives you [0,M-2], but > the name "randbelow" seems like a neat fix to that problem. > > -- Peter Pearson > It's not clear whether this correspondent realizes that randrange(N) is identical to randbelow(N). > This matches what Serhiy suggests: in crypto, one normally only needs to > generate the half-open interval [0...n). It also matches the reason why > Tim Peters added randbelow in the first place. > > As the author of the PEP, I'm satisfied by this argument, and will now > state that my preferred option is to drop randint and randrange, and > just keep randbelow. > > My second choice is to keep all three functions. > > I think it is fair to say that out of the three functions, there is > consensus that randbelow has the most useful functionality in a crypto > context. Otherwise, people seem roughly equally split between the three > functions. There doesn't seem to be any use-case for the three argument > version of randrange. > I'm fine with dropping the 3rd arg. But I find the argument to introduce a new spelling for 1-arg randrange() weak. I definitely thing that randint() is an attractive nuisance so we should drop that. -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 506 secrets module
Guido van Rossum writes: > On Sat, Oct 17, 2015 at 2:50 AM, Steven D'Aprano > wrote: > > [...] > So you can see there is nothing even close to consensus as to > which API > is best, which is an argument for keeping all three functions. > > No, that's not how we do it in Python. :-) Ooh, I know this! It's an argument for scrapping the whole thing, right? ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 506 secrets module
[Steven D'Aprano] >> ... >> I think it is fair to say that out of the three functions, there is >> consensus that randbelow has the most useful functionality in a crypto >> context. Otherwise, people seem roughly equally split between the three >> functions. There doesn't seem to be any use-case for the three argument >> version of randrange. [Guido] > I'm fine with dropping the 3rd arg. But I find the argument to introduce a > new spelling for 1-arg randrange() weak. Note the inherent absurdity here ;-) That is, we're proposing to add a module _all_ of whose functions are merely trivial (to the educated) respellings of functions that already exist elsewhere. Is there, e.g., really "a strong" argument for giving a different way to spell os.urandom()? That depends. I'm playing along with the basic assumption: that this module intends to be as idiot-proof as possible. In which case, sure, rename away. And in which case, no, randbelow is not a new spelling for 1-arg randrange. To the contrary, all the integer-like functions (including randrange, randint, and choice) in the random module are currently built on top of the private Random._randbelow() method. The latter is "the right" fundamental building block for implementing uniform choice free of statistical bias. It's also overwhelmingly most useful _on its own_ in the `secrets` context, and has the crushing (to me, in this context) advantage that its very name strongly suggests its argument is not a possible return value. Giving a strongly mnemonic name to a function with a dead simple "one required integer argument" signature is likely "as idiot-proof as possible" as it gets. BTW, it also gives a simple answer to "I'm used to using arc4random_uniform() in OpenBSD - how do I spell that in `secrets`?". Answer: `randbelow()` is identical, except in Python the argument isn't limited to uint32_t". > I definitely thing that randint() is an attractive nuisance so we should > drop that. `randrange()` isn't a nuisance at all in Python, but its signature is more convoluted than putative users of the proposed module seem to want, and long experience has shown its name is not idiot-proof. `secrets` users aren't looking to pick something uniformly from "a range" - they're looking to pick a non-negative integer less than some upper bound. Unneeded generalization beyond just that much is also an attractive nuisance, in context. "Simplest thing that can possibly suffice" is always a good way to start :-) ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] PEP 506 secrets module
> Guido van Rossum wrote: > I'm fine with dropping the 3rd arg. But I find the argument to > introduce a new spelling for 1-arg randrange() weak. I should stress that my preference for randbelow over randrange was based purely on their proposed functionality and not on their names. I do however have a preference for a function of minimum required functionality, i.e. one that allows only a single parameter (N) to set the range 0 .. N-1. ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] type(obj) vs. obj.__class__
In a recent tracker issue about OrderedDict [1] we've had some discussion about the use of type(od) as a replacement for od.__class__. It came up because the pure Python implementation of OrderedDict uses self.__class__ in 3 different methods (__repr__, __reduce__, and copy). The patch in that issue changes the C implementation to use Py_TYPE(). [2] So I wanted to get some feedback on the practical implications of such a change and if we need to clarify the difference more formally. In this specific case [3] there are 3 questions: * Should __repr__() for a stdlib class use type(self).__name__ or self.__class__.__name__? * Should __reduce__() return type(self) or self.__class__? * Should copy() use type(self) or self.__class__? The more general question of when we use type(obj) vs. obj.__class__ applies to both the language and to all the stdlib as I expect consistency there would result in fewer surprises. I realize that there are some places where using obj.__class__ makes more sense (e.g. for some proxy support). There are other places where using type(obj) is the way to go (e.g. special method lookup). However, the difference is muddled enough that usage is inconsistent in the stdlib. For example, C-implemented types use Py_TYPE() almost exclusively. So, would it make sense to establish some concrete guidelines about when to use type(obj) vs. obj.__class__? If so, what would those be? It may also be helpful to enumerate use cases for "type(obj) is not obj.__class__". -eric [1] http://bugs.python.org/issue25410 [2] I'm going to open a separate thread about the issue of compatibility and C accelerated types. [3] https://hg.python.org/cpython/file/default/Lib/collections/__init__.py#l238 ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] compatibility for C-accelerated types
A recent discussion in a tracker issue [1] brought up the matter of compatibility between the pure Python implementation of OrderedDict and the new C implementation. In working on that port I stuck as closely as possible to the Python implementation. This meant some parts of the code are bit more complex than they would be otherwise. (Serhiy has been kind enough to do some cleanup.) Compatibility was one of the fundamental goals of the porting effort. Not only does compatibility make sense but it's also specifically required by PEP 399 [2]: Any new accelerated code must act as a drop-in replacement as close to the pure Python implementation as reasonable. Technical details of the VM providing the accelerated code are allowed to differ as necessary, e.g., a class being a type when implemented in C. For the most part I have questions about what is "reasonable", specifically in relation to OrderedDict. I've already opened up a separate thread related to my main question: type(obj) vs. obj.__class__. [3] In the tracker issue, Serhiy pointed out: There is no a difference. io, pickle, ElementTree, bz2, virtually all accelerator classes was created as replacements of pure Python implementations. All C implementations use Py_TYPE(self) for repr() and pickling. I think this deviation is common and acceptable. In a review comment on the associated patch he said: Isn't type(self) is always the same as self.__class__ for pure Python class? If right, then this change doesn't have any effect. To which he later replied: It is the same if you assigned the __class__ attribute, but can be different if set __class__ in the subclass declaration. So it isn't clear if that is a compatibility break or how much so it might be. Serhiy also noted that, as of 3.5 [4], you can no longer assign to obj.__class__ for instances of subclasses of builtin (non-heap) types. So that is another place where the two OrderedDict implementations differ. I expect there are a few others in dark corner cases. On the tracker he notes another OrderedDict compatibility break: Backward compatibility related to __class__ assignment was already broken in C implementation. In 3.4 following code works: >>> from collections import * >>> class foo(OrderedDict): ... def bark(self): return "spam" ... >>> class bar(OrderedDict): ... pass ... >>> od = bar() >>> od.__class__ = foo >>> od.bark() 'spam' In 3.5 it doesn't. As PEP 399 says, we should go as far "as reasonable" in the pursuit of compatibility. At the same time, I feel not insignificant responsibility for *any* incompatibility that comes from the C implementation of OrderedDict. The corner cases impacted by the above compatibility concerns are borderline enough that I wanted to get some feedback. Thanks! -eric [1] http://bugs.python.org/issue25410 [2] https://www.python.org/dev/peps/pep-0399/ [3] https://mail.python.org/pipermail/python-dev/2015-October/141953.html [4] http://bugs.python.org/issue24912 ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] type(obj) vs. obj.__class__
On 18.10.15 00:45, Eric Snow wrote: In a recent tracker issue about OrderedDict [1] we've had some discussion about the use of type(od) as a replacement for od.__class__. It came up because the pure Python implementation of OrderedDict uses self.__class__ in 3 different methods (__repr__, __reduce__, and copy). The patch in that issue changes the C implementation to use Py_TYPE(). [2] So I wanted to get some feedback on the practical implications of such a change and if we need to clarify the difference more formally. In this specific case [3] there are 3 questions: * Should __repr__() for a stdlib class use type(self).__name__ or self.__class__.__name__? * Should __reduce__() return type(self) or self.__class__? * Should copy() use type(self) or self.__class__? The more general question of when we use type(obj) vs. obj.__class__ applies to both the language and to all the stdlib as I expect consistency there would result in fewer surprises. I realize that there are some places where using obj.__class__ makes more sense (e.g. for some proxy support). There are other places where using type(obj) is the way to go (e.g. special method lookup). However, the difference is muddled enough that usage is inconsistent in the stdlib. For example, C-implemented types use Py_TYPE() almost exclusively. So, would it make sense to establish some concrete guidelines about when to use type(obj) vs. obj.__class__? If so, what would those be? It may also be helpful to enumerate use cases for "type(obj) is not obj.__class__". -eric [1] http://bugs.python.org/issue25410 [2] I'm going to open a separate thread about the issue of compatibility and C accelerated types. [3] https://hg.python.org/cpython/file/default/Lib/collections/__init__.py#l238 Want to add that in common case type(obj) is the same as obj.__class__. When you set obj.__class__ (assignment is restricted by issue24912), type(obj) is changed as well. You can make obj.__class__ differ from type(obj) if set __class__ as class attribute at class creation time, or made __class__ a property, or like. >>> class A: pass ... >>> class B: __class__ = A ... >>> type(B()) >>> B().__class__ The only places where obj.__class__ made different from type(obj) in the stdlib, besides tests, are mock object (hence related to tests), and proxy stream in xml.sax.saxutils (I'm not sure that the latter use is correct). About pickling. Default implementation of __reduce_ex__ uses obj.__class__ in protocols 0 and 1, and type(obj) in protocols 2+. >>> B().__reduce_ex__(1) (, (, 'object'>, None)) >>> B().__reduce_ex__(2) (, (,), None, None, None) But pickler rejects classes with mismatched type(obj) and obj.__class__ in protocols 2+. >>> pickle.dumps(B(), 2) Traceback (most recent call last): File "", line 1, in _pickle.PicklingError: args[0] from __newobj__ args has the wrong class ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] compatibility for C-accelerated types
On 18.10.15 01:20, Eric Snow wrote: On the tracker he notes another OrderedDict compatibility break: Backward compatibility related to __class__ assignment was already broken in C implementation. In 3.4 following code works: >>> from collections import * >>> class foo(OrderedDict): ... def bark(self): return "spam" ... >>> class bar(OrderedDict): ... pass ... >>> od = bar() >>> od.__class__ = foo >>> od.bark() 'spam' In 3.5 it doesn't. Sorry, I was mistaken with this example. It works in 3.5. ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 506 secrets module
Yes, randrange(n) does that. --Guido (mobile) On Oct 17, 2015 2:28 PM, "Brian Gladman" wrote: > > Guido van Rossum wrote: > > > I'm fine with dropping the 3rd arg. But I find the argument to > > introduce a new spelling for 1-arg randrange() weak. > > I should stress that my preference for randbelow over randrange was > based purely on their proposed functionality and not on their names. > > I do however have a preference for a function of minimum required > functionality, i.e. one that allows only a single parameter (N) to > set the range 0 .. N-1. > ___ > Python-Dev mailing list > Python-Dev@python.org > https://mail.python.org/mailman/listinfo/python-dev > Unsubscribe: > https://mail.python.org/mailman/options/python-dev/guido%40python.org > ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 506 secrets module
OK, so just randbelow() then. --Guido (mobile) On Oct 17, 2015 2:13 PM, "Tim Peters" wrote: > [Steven D'Aprano] > >> ... > >> I think it is fair to say that out of the three functions, there is > >> consensus that randbelow has the most useful functionality in a crypto > >> context. Otherwise, people seem roughly equally split between the three > >> functions. There doesn't seem to be any use-case for the three argument > >> version of randrange. > > [Guido] > > I'm fine with dropping the 3rd arg. But I find the argument to introduce > a > > new spelling for 1-arg randrange() weak. > > Note the inherent absurdity here ;-) That is, we're proposing to add > a module _all_ of whose functions are merely trivial (to the educated) > respellings of functions that already exist elsewhere. Is there, > e.g., really "a strong" argument for giving a different way to spell > os.urandom()? > > That depends. I'm playing along with the basic assumption: that this > module intends to be as idiot-proof as possible. In which case, sure, > rename away. > > And in which case, no, randbelow is not a new spelling for 1-arg > randrange. To the contrary, all the integer-like functions (including > randrange, randint, and choice) in the random module are currently > built on top of the private Random._randbelow() method. The latter is > "the right" fundamental building block for implementing uniform choice > free of statistical bias. It's also overwhelmingly most useful _on > its own_ in the `secrets` context, and has the crushing (to me, in > this context) advantage that its very name strongly suggests its > argument is not a possible return value. Giving a strongly mnemonic > name to a function with a dead simple "one required integer argument" > signature is likely "as idiot-proof as possible" as it gets. > > BTW, it also gives a simple answer to "I'm used to using > arc4random_uniform() in OpenBSD - how do I spell that in `secrets`?". > Answer: `randbelow()` is identical, except in Python the argument > isn't limited to uint32_t". > > > > I definitely thing that randint() is an attractive nuisance so we should > > drop that. > > `randrange()` isn't a nuisance at all in Python, but its signature is > more convoluted than putative users of the proposed module seem to > want, and long experience has shown its name is not idiot-proof. > `secrets` users aren't looking to pick something uniformly from "a > range" - they're looking to pick a non-negative integer less than some > upper bound. Unneeded generalization beyond just that much is also an > attractive nuisance, in context. > > "Simplest thing that can possibly suffice" is always a good way to start > :-) > ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] type(obj) vs. obj.__class__
On Sat, Oct 17, 2015 at 03:45:19PM -0600, Eric Snow wrote: > In a recent tracker issue about OrderedDict [1] we've had some > discussion about the use of type(od) as a replacement for > od.__class__. [...] > The more general question of when we use type(obj) vs. obj.__class__ > applies to both the language and to all the stdlib as I expect > consistency there would result in fewer surprises. I realize that > there are some places where using obj.__class__ makes more sense (e.g. > for some proxy support). There are other places where using type(obj) > is the way to go (e.g. special method lookup). However, the > difference is muddled enough that usage is inconsistent in the stdlib. > For example, C-implemented types use Py_TYPE() almost exclusively. > > So, would it make sense to establish some concrete guidelines about > when to use type(obj) vs. obj.__class__? If so, what would those be? > It may also be helpful to enumerate use cases for "type(obj) is not > obj.__class__". I for one would like to see a definitive explanation for when they are different, and when you should use one or the other. The only obvious example I've seen is the RingBuffer from the Python Cookbook: http://code.activestate.com/recipes/68429-ring-buffer/ -- Steve ___ Python-Dev mailing list Python-Dev@python.org https://mail.python.org/mailman/listinfo/python-dev Unsubscribe: https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com