Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On Thu, Apr 25, 2013 at 7:43 AM, Antoine Pitrou solip...@pitrou.net wrote: On Thu, 25 Apr 2013 04:19:36 +0200 Lennart Regebro rege...@gmail.com wrote: On Thu, Apr 25, 2013 at 3:54 AM, Stephen J. Turnbull step...@xemacs.org wrote: RFC 4648 repeatedly refers to *characters*, without specifying an encoding for them. [...] Base64 is an encoding that transforms between 8-bit streams. No, it isn't. What Stephen wrote above. Yes it is. Base64 takes 8-bit bytes and transforms them into another 8-bit stream that can be safely transmitted over various channels that would mangle an unencoded 8-bit stream, such as email etc. http://en.wikipedia.org/wiki/Base64 Either you get a LookupError: unknown encoding: base64, which is what you get now, or you get an UnicodeEncodingError if the text is not ASCII. We don't want the latter, because it means that code that looks fine for the developer breaks in real life because the developer was American That's bogus. No, that's real life. By the same argument, we should suppress any encoding which isn't able to represent all possible unicode strings. No, if you explicitly use such an encoding it is because you need to because you are transferring data to a system that needs the encoding in question. Unicode errors are unavoidable at that point, not an unexpected surprise because a conversion happened implicitly that you didn't know about. //Lennart ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] A decade as a core dev
Am 18.04.2013 17:02, schrieb Brett Cannon: Today marks my 10 year anniversary as a core developer on Python. I wrote a blog post to mark the occasion (http://sayspy.blogspot.ca/2013/04/a-decade-of-commits.html), but I wanted to personally thank python-dev for the past decade (and whatever comes in the future). All of you taught me how to really program and for that I will be eternally grateful. And the friendships I have built through this list are priceless. Hah, I only have 2 years to go. Time flies like an unladen swallow... Congrats :) Georg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
Lennart Regebro writes: Base64 is an encoding that transforms between 8-bit streams. Let it be that. Don't try to shoehorn it into a completely different kind of encoding. By completely different kind of encoding do you mean codec? I think that would be an unfortunate result. These operations on streams are theoretically nicely composable. It would be nice if practice reflected that by having a uniform API for all of these operations (charset translation, encoded text to internal, content transfer encoding, compression ...). I think it would be useful, too, though I can't prove that. Anyway, this discussion belongs on python-ideas at this point. Or would, if I had an idea about implementation. I'll take it there when I do have something to say about implementation. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On Thu, Apr 25, 2013 at 8:57 AM, Stephen J. Turnbull step...@xemacs.org wrote: I think that would be an unfortunate result. These operations on streams are theoretically nicely composable. It would be nice if practice reflected that by having a uniform API for all of these operations (charset translation, encoded text to internal, content transfer encoding, compression ...). I think it would be useful, too, though I can't prove that. But the translation to and from Unicode to some 8-bit encoding is different from the others. It makes sense that they have a different API. If you have a Unicode string you can go: Unicode text - UTF8 - ZIP - BASE64. Or you can go Unicode text - UTF8 - BASE64 - ZIP Although admittedly that makes much less sense. :-) But you can not go: Unicode text - BASE64 - ZIP - UTF8 The str/bytes encoding/decoding is not like the others. //Lennart ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On Thu, Apr 25, 2013 at 4:57 PM, Stephen J. Turnbull step...@xemacs.org wrote: Lennart Regebro writes: Base64 is an encoding that transforms between 8-bit streams. Let it be that. Don't try to shoehorn it into a completely different kind of encoding. By completely different kind of encoding do you mean codec? I think that would be an unfortunate result. These operations on streams are theoretically nicely composable. It would be nice if practice reflected that by having a uniform API for all of these operations (charset translation, encoded text to internal, content transfer encoding, compression ...). I think it would be useful, too, though I can't prove that. Anyway, this discussion belongs on python-ideas at this point. Or would, if I had an idea about implementation. I'll take it there when I do have something to say about implementation. Bringing the mailing list thread up to date with the state of the relevant tracker issues: I created http://bugs.python.org/issue17827 to cover adding the missing documentation for codecs.encode and codecs.decode as the officially supported solutions for easy use of the codec infrastructure *without* the additional text model specific input and output type restrictions imposed by the str.encode, bytes.decode and bytearray.decode methods. I created http://bugs.python.org/issue17828 to cover emitting more meaningful exceptions when a codec throws TypeError or ValueError, as well as when the additional type checking fails for str.encode, bytes.decode and bytearray.decode. I created http://bugs.python.org/issue17839 to cover the fact that part of the problem here is that the base64 module currently only accepts bytes and bytearray as inputs, rather than anything that supports the PEP 3118 buffer interface. http://bugs.python.org/issue7475 (linked earlier in the thread) is now strictly about restoring the shorthand aliases for base64_codec, bz2_codec et al that were removed in http://bugs.python.org/issue10807. Regards, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
Le Thu, 25 Apr 2013 08:38:12 +0200, Lennart Regebro rege...@gmail.com a écrit : On Thu, Apr 25, 2013 at 7:43 AM, Antoine Pitrou solip...@pitrou.net wrote: On Thu, 25 Apr 2013 04:19:36 +0200 Lennart Regebro rege...@gmail.com wrote: On Thu, Apr 25, 2013 at 3:54 AM, Stephen J. Turnbull step...@xemacs.org wrote: RFC 4648 repeatedly refers to *characters*, without specifying an encoding for them. [...] Base64 is an encoding that transforms between 8-bit streams. No, it isn't. What Stephen wrote above. Yes it is. Base64 takes 8-bit bytes and transforms them into another 8-bit stream that can be safely transmitted over various channels that would mangle an unencoded 8-bit stream, such as email etc. http://en.wikipedia.org/wiki/Base64 I don't see anything in that Wikipedia page that validates your opinion. The Wikipedia page does talk about *text* and *characters* for the result of base64 encoding. Besides, I would consider a RFC more authoritative than a Wikipedia definition. By the same argument, we should suppress any encoding which isn't able to represent all possible unicode strings. No, if you explicitly use such an encoding it is because you need to because you are transferring data to a system that needs the encoding in question. Unicode errors are unavoidable at that point, not an unexpected surprise because a conversion happened implicitly that you didn't know about. I don't know what implicit conversion you are talking about. There's no implicit conversion in a scheme where the result of base64 encoding is a text string. Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
Le Fri, 12 Apr 2013 05:55:00 -0700, Eli Bendersky eli...@gmail.com a écrit : To programmatically access enumeration values, use ``getattr``:: getattr(Colors, 'red') EnumValue: Colors.red [value=1] The PEP should mention how to get an enum from its raw value: Colors[1] EnumValue: Colors.red [value=1] or: Colors(1) EnumValue: Colors.red [value=1] It would perhaps be nice to have a .get() method that return None if the raw value is unknown: Colors(42) ... ValueError: 42 Colors.get(42) Regards Anroine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On Thu, Apr 25, 2013 at 11:25 AM, Antoine Pitrou solip...@pitrou.net wrote: Le Thu, 25 Apr 2013 08:38:12 +0200, Yes it is. Base64 takes 8-bit bytes and transforms them into another 8-bit stream that can be safely transmitted over various channels that would mangle an unencoded 8-bit stream, such as email etc. http://en.wikipedia.org/wiki/Base64 I don't see anything in that Wikipedia page that validates your opinion. OK, quote me the exact page text from the Wikipedia article or RFC that explains how you map the 31-bit character space of Unicode to Base64. The Wikipedia page does talk about *text* and *characters* for the result of base64 encoding. So are saying that you want the Python implementation of base64 encoding to take 8-bit binary data in bytes format and return a Unicode string containing the Base64 encoded data? I think that would surprise most people, and be of significantly less use than a base64 encoding that returns bytes. Python 3 still views text as Unicode only. Everything else is not text, but binary data. This makes sense, is consistent and makes things easier to handle. This is the whole point of making the str into Unicode in Python 3. No, if you explicitly use such an encoding it is because you need to because you are transferring data to a system that needs the encoding in question. Unicode errors are unavoidable at that point, not an unexpected surprise because a conversion happened implicitly that you didn't know about. I don't know what implicit conversion you are talking about. There's no implicit conversion in a scheme where the result of base64 encoding is a text string. I'm sorry, I thought you were arguing for a base64 encoding taking Unicode strings and returning 8-bit bytes. That position I can understand, although I disagree with it. The position that a base64 encoding should take 8-bit bytes and return Unicode strings is incomprehensible to me. I have no idea why you would want that, how you would use it, how you would implement that API in a reasonable way, nor how you would explain why it is like that. I can't think of any usecase where you would want base64 encoded data unless you intend to transmit it over an 8-bit channel, so why it should return a Unicode string instead of 8-bit bytes is completely beyond my comprehension. Sorry. //Lennart ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On 2013-04-25, at 11:25 , Antoine Pitrou wrote: Besides, I would consider a RFC more authoritative than a Wikipedia definition. Base encoding of data is used in many situations to store or transfer data in environments that, perhaps for legacy reasons, are restricted to US-ASCII [1] data. so the output is US-ASCII data, a byte stream. Stephen is correct that you could decide you don't care about those semantics, and implement base64 encoding as a bytes - str decoding then requiring a re-encoding (to ascii) before wire transmission. The clarity of the interface (or lack thereof) would probably make users want to send a strongly worded letter to whoever implemented it though, I don't think `data.decode('base64').encode('ascii')` would fit the obviousness or readability expectations of most users. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 2:42 AM, Antoine Pitrou solip...@pitrou.net wrote: Le Fri, 12 Apr 2013 05:55:00 -0700, Eli Bendersky eli...@gmail.com a écrit : To programmatically access enumeration values, use ``getattr``:: getattr(Colors, 'red') EnumValue: Colors.red [value=1] The PEP should mention how to get an enum from its raw value: Colors[1] EnumValue: Colors.red [value=1] Yes, this is mentioned in the beginning of the same paragraph. or: Colors(1) EnumValue: Colors.red [value=1] This syntax was considered initially but then rejected because it's confusing, and there already exists a way to lookup by value (Colors[1]). Eli It would perhaps be nice to have a .get() method that return None if the raw value is unknown: Colors(42) ... ValueError: 42 Colors.get(42) Regards Anroine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/eliben%40gmail.com ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
Le Thu, 25 Apr 2013 05:21:50 -0700, Eli Bendersky eli...@gmail.com a écrit : or: Colors(1) EnumValue: Colors.red [value=1] This syntax was considered initially but then rejected because it's confusing, and there already exists a way to lookup by value (Colors[1]). Well, it works in latest flufl.enum. Is there a difference between the PEP and the implementation. Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
Le Thu, 25 Apr 2013 12:46:43 +0200, Xavier Morel catch-...@masklinn.net a écrit : On 2013-04-25, at 11:25 , Antoine Pitrou wrote: Besides, I would consider a RFC more authoritative than a Wikipedia definition. Base encoding of data is used in many situations to store or transfer data in environments that, perhaps for legacy reasons, are restricted to US-ASCII [1] data. so the output is US-ASCII data, a byte stream. Well, depending on the context, US-ASCII can be a character set or a character encoding. If some specification is talking about text and characters, then it is something that can reasonably be a str in Python land. Similarly, we have chosen to make filesystem paths str by default in Python 3, even though many Unix-heads would claim that filesystem paths are bytes only. The reason is that while they are technically bytes (under Unix), they are functionally text. Now, if the base64-encoded data is your entire payload, this clearly amounts to nitpicking. But when you want to *embed* that data in some larger chunk of text (e.g. a JSON object), then it makes a lot of sense to consider the base64-encoded data a piece of *text*, not bytes. Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
Le Thu, 25 Apr 2013 12:05:01 +0200, Lennart Regebro rege...@gmail.com a écrit : The Wikipedia page does talk about *text* and *characters* for the result of base64 encoding. So are saying that you want the Python implementation of base64 encoding to take 8-bit binary data in bytes format and return a Unicode string containing the Base64 encoded data? I'm not wanting anything here, since that would clearly break backwards compatibility. But I think binascii should have gone that way in Python 3, indeed. binascii.b2a_hex(), for example, would be much more practical if it returned str, rather than bytes. Python 3 still views text as Unicode only. Python 3 doesn't *view* text as unicode, it *represents* it as unicode. That is, unicode is the character set that Python 3 is able to represent in the canonical text type, str. If you ever encounter a hypothetical text that uses characters outside of Unicode (obviously it will be encoded using a non-unicode encoding :-)), then you can't represent it as a str. And base64 is clearly representable as unicode, since it's representable using the ASCII character set (which is a subset of the unicode character set). I can't think of any usecase where you would want base64 encoded data unless you intend to transmit it over an 8-bit channel, I can think of many usecases where I want to *embed* base64-encoded data in a larger text *before* encoding that text and transmitting it over a 8-bit channel. (GPG signatures, binary data embedded in JSON objects, etc.) Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 5:29 AM, Antoine Pitrou solip...@pitrou.net wrote: Le Thu, 25 Apr 2013 05:21:50 -0700, Eli Bendersky eli...@gmail.com a écrit : or: Colors(1) EnumValue: Colors.red [value=1] This syntax was considered initially but then rejected because it's confusing, and there already exists a way to lookup by value (Colors[1]). Well, it works in latest flufl.enum. Is there a difference between the PEP and the implementation. It produces a deprecation warning in flufl.enum because flufl.enum specifically supported this earlier. It should not be supported in the stdlib implementation. The __call__ syntax has been repurposed for the convenience API: Animals = Enum('Animals', 'ant bee cat dog') Animals Animals {ant: 1, bee: 2, cat: 3, dog: 4} Animals.ant EnumValue: Animals.ant [value=1] Animals.ant.value 1 The aforementioned deprecated syntax refers to __call__ with a single arguments (the convenience API by definition requires more than one). Eli ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On Thu, Apr 25, 2013 at 2:57 PM, Antoine Pitrou solip...@pitrou.net wrote: I can think of many usecases where I want to *embed* base64-encoded data in a larger text *before* encoding that text and transmitting it over a 8-bit channel. That still doesn't mean that this should be the default behavior. Just because you *can* represent base64 as Unicode text doesn't mean that it should be. (GPG signatures, binary data embedded in JSON objects, etc.) Is the GPG signature calculated on the *Unicode* data? How is that done? Isn't it done on the encoded message? As I understand it a GPG signature is done on any sort of document. Either me or you have completely misunderstood how GPG works, I think. :-) In the case of JSON objects, they are intended for data exchange, and hence in the end need to be byte strings. So if you have a byte string you want to base64 encode before transmitting it with json, you would just end up transforming it to a unicode string and then back. That doesn't seem useful. One use case where you clearly *do* want the base64 encoded data to be unicode strings is because you want to embed it in a text discussing base64 strings, for a blog or a book or something. That doesn't seem to be a very common usecase. For the most part you base64 encode things because it's going to be transmitted, and hence the natural result of a base64 encoding should be data that is ready to be transmitted, hence byte strings, and not Unicode strings. Python 3 doesn't *view* text as unicode, it *represents* it as unicode. I don't agree that there is a significant difference between those wordings in this context. The end result is the same: Things intended to be handled/seen as textual should be unicode strings, things intended for data exchange should be byte strings. Something that is base64 encoded is primarily intended for data exchange. A base64 encoding should therefore return byte strings, especially since most API's that perform this transmission will take byte strings as input. If you want to include this in textual data, for whatever reason, like printing it in a book, then the conversion is trivial, but that is clearly the less common use case, and should therefore not be the default behavior. //Lennart ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 04/25/2013 01:43 AM, Antoine Pitrou wrote: On Thu, 25 Apr 2013 04:19:36 +0200 Lennart Regebro rege...@gmail.com wrote: On Thu, Apr 25, 2013 at 3:54 AM, Stephen J. Turnbull step...@xemacs.org wrote: RFC 4648 repeatedly refers to *characters*, without specifying an encoding for them. [...] Base64 is an encoding that transforms between 8-bit streams. No, it isn't. What Stephen wrote above. Stephen was incorrect: the base64 standard is about encoding a binary stream (8-bit bites) onto another binary stream (6-bit bytes), but one which can be safely transmitted over a 7-bit-only medium. Text in Py3ks sense is irrelevant. Either you get a LookupError: unknown encoding: base64, which is what you get now, or you get an UnicodeEncodingError if the text is not ASCII. We don't want the latter, because it means that code that looks fine for the developer breaks in real life because the developer was American That's bogus. By the same argument, we should suppress any encoding which isn't able to represent all possible unicode strings. That's almost all encodings provided by Python (including utf-8, if you consider lone surrogates). I'm sorry for Americans, but they *still* must know about character encodings, and be ready to handle UnicodeErrors, when using Python 3 for encoding/decoding bytestrings. There's no way around it. WHat does that snark have to do with this discussion? base64 has no more to do with character set encodings than it does the moon. It would be a transform (bytes - bytes), not an encoding. Tres. - -- === Tres Seaver +1 540-429-0999 tsea...@palladion.com Palladion Software Excellence by Designhttp://palladion.com -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with undefined - http://www.enigmail.net/ iEYEARECAAYFAlF5Nc4ACgkQ+gerLs4ltQ7f9ACgx19dzyLXCDzkLkWITSU+7WyD XEMAn38mZgK8F1/FGWJc+ANOJz2tfHI/ =qpSL -END PGP SIGNATURE- ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On Apr 25, 2013, at 03:34 PM, Lennart Regebro wrote: In the case of JSON objects, they are intended for data exchange, and hence in the end need to be byte strings. Except that they're not. http://bugs.python.org/issue10976 -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On 25/04/2013 14:34, Lennart Regebro wrote: On Thu, Apr 25, 2013 at 2:57 PM, Antoine Pitrou solip...@pitrou.net wrote: I can think of many usecases where I want to *embed* base64-encoded data in a larger text *before* encoding that text and transmitting it over a 8-bit channel. That still doesn't mean that this should be the default behavior. Just because you *can* represent base64 as Unicode text doesn't mean that it should be. (GPG signatures, binary data embedded in JSON objects, etc.) Is the GPG signature calculated on the *Unicode* data? How is that done? Isn't it done on the encoded message? As I understand it a GPG signature is done on any sort of document. Either me or you have completely misunderstood how GPG works, I think. :-) In the case of JSON objects, they are intended for data exchange, and hence in the end need to be byte strings. So if you have a byte string you want to base64 encode before transmitting it with json, you would just end up transforming it to a unicode string and then back. That doesn't seem useful. The JSON specification says that it's text. Its string literals can contain Unicode codepoints. It needs to be encoded to bytes for transmission and storage, but JSON itself is not a bytestring format. One use case where you clearly *do* want the base64 encoded data to be unicode strings is because you want to embed it in a text discussing base64 strings, for a blog or a book or something. That doesn't seem to be a very common usecase. For the most part you base64 encode things because it's going to be transmitted, and hence the natural result of a base64 encoding should be data that is ready to be transmitted, hence byte strings, and not Unicode strings. Python 3 doesn't *view* text as unicode, it *represents* it as unicode. I don't agree that there is a significant difference between those wordings in this context. The end result is the same: Things intended to be handled/seen as textual should be unicode strings, things intended for data exchange should be byte strings. Something that is base64 encoded is primarily intended for data exchange. A base64 encoding should therefore return byte strings, especially since most API's that perform this transmission will take byte strings as input. If you want to include this in textual data, for whatever reason, like printing it in a book, then the conversion is trivial, but that is clearly the less common use case, and should therefore not be the default behavior. base64 is a way of encoding binary data as text. The problem is that traditionally text has been encoded with one byte per character, except in those locales where there were too many characters in the character set for that to be possible. In Python 3 we're trying to stop mixing binary data (bytestrings) with text (Unicode strings). ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On Thu, Apr 25, 2013 at 10:07 AM, Barry Warsaw ba...@python.org wrote: On Apr 25, 2013, at 03:34 PM, Lennart Regebro wrote: In the case of JSON objects, they are intended for data exchange, and hence in the end need to be byte strings. Except that they're not. http://bugs.python.org/issue10976 -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/dholth%40gmail.com What am I doing wrong in this JSON crypto signature verification snippet that features many conversions between binary and text? recipients = jwsjs[recipients] encoded_payload = binary(jwsjs[payload]) headers = [] for recipient in recipients: h = binary(recipient[header]) s = binary(recipient[signature]) header = json.loads(native(urlsafe_b64decode(h))) vk = urlsafe_b64decode(binary(header[jwk][vk])) secured_input = b..join((h, encoded_payload)) sig = urlsafe_b64decode(s) sig_msg = sig+secured_input verified_input = native(ed25519ll.crypto_sign_open(sig_msg, vk)) verified_header, verified_payload = verified_input.split('.') verified_header = binary(verified_header) decoded_header = native(urlsafe_b64decode(verified_header)) headers.append(json.loads(decoded_header)) verified_payload = binary(verified_payload) # only return header, payload that have passed through the crypto library. payload = json.loads(native(urlsafe_b64decode(verified_payload))) return headers, payload ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On Thu, Apr 25, 2013 at 4:22 PM, MRAB pyt...@mrabarnett.plus.com wrote: The JSON specification says that it's text. Its string literals can contain Unicode codepoints. It needs to be encoded to bytes for transmission and storage, but JSON itself is not a bytestring format. OK, fair enough. base64 is a way of encoding binary data as text. It's a way of encoding binary data using ASCII. There is a subtle but important difference. In Python 3 we're trying to stop mixing binary data (bytestrings) with text (Unicode strings). Yup. And that's why a byte64 encoding shouldn't return Unicode strings. //Lennart ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
Le Thu, 25 Apr 2013 09:55:26 -0400, Tres Seaver tsea...@palladion.com a écrit : -BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 04/25/2013 01:43 AM, Antoine Pitrou wrote: On Thu, 25 Apr 2013 04:19:36 +0200 Lennart Regebro rege...@gmail.com wrote: On Thu, Apr 25, 2013 at 3:54 AM, Stephen J. Turnbull step...@xemacs.org wrote: RFC 4648 repeatedly refers to *characters*, without specifying an encoding for them. [...] Base64 is an encoding that transforms between 8-bit streams. No, it isn't. What Stephen wrote above. Stephen was incorrect: the base64 standard is about encoding a binary stream (8-bit bites) onto another binary stream (6-bit bytes), but one which can be safely transmitted over a 7-bit-only medium. So where does the RFC talk about 6-bit bytes at all? Or did you just invent it? ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
Le Thu, 25 Apr 2013 15:34:45 +0200, Lennart Regebro rege...@gmail.com a écrit : I don't agree that there is a significant difference between those wordings in this context. The end result is the same: Things intended to be handled/seen as textual should be unicode strings, things intended for data exchange should be byte strings. I don't think this distinction is meaningful at all. In the end, everything is a byte string on a classical computer (including unicode strings displayed on your monitor, obviously). If you think the technicalities of an operation should never be hidden or abstracted away, then you're better off with C than Python ;-) Regards Antoine. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 06:03 AM, Eli Bendersky wrote: The __call__ syntax has been repurposed for the convenience API: -- Animals = Enum('Animals', 'ant bee cat dog') -- Animals Animals {ant: 1, bee: 2, cat: 3, dog: 4} -- Animals.ant EnumValue: Animals.ant [value=1] -- Animals.ant.value 1 The aforementioned deprecated syntax refers to __call__ with a single arguments (the convenience API by definition requires more than one). I don't understand why having Enum() be the convenience function rules out `Animals(1)` from returning `Animals.ant`. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
FWIW, If we're going ahead with the plan to make Colors.red an instance of Colors, maybe the class names used in examples should be singular, i.e. isinstance(Color.red, Color)? -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 8:46 AM, Ethan Furman et...@stoneleaf.us wrote: On 04/25/2013 06:03 AM, Eli Bendersky wrote: The __call__ syntax has been repurposed for the convenience API: -- Animals = Enum('Animals', 'ant bee cat dog') -- Animals Animals {ant: 1, bee: 2, cat: 3, dog: 4} -- Animals.ant EnumValue: Animals.ant [value=1] -- Animals.ant.value 1 The aforementioned deprecated syntax refers to __call__ with a single arguments (the convenience API by definition requires more than one). I don't understand why having Enum() be the convenience function rules out `Animals(1)` from returning `Animals.ant`. Because we already have a way to do that: Animals[1]. Why do you need two slightly different ways to do the same? Moreover, why do you want to make Animals.__call__ behave very differently based only on the number of args? This seems to be un-pythonic in multiple ways. Eli ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 9:39 AM, Ethan Furman et...@stoneleaf.us wrote: On 04/25/2013 09:34 AM, Eli Bendersky wrote: On Thu, Apr 25, 2013 at 8:46 AM, Ethan Furman et...@stoneleaf.usmailto: et...@stoneleaf.us wrote: On 04/25/2013 06:03 AM, Eli Bendersky wrote: The __call__ syntax has been repurposed for the convenience API: -- Animals = Enum('Animals', 'ant bee cat dog') -- Animals Animals {ant: 1, bee: 2, cat: 3, dog: 4} -- Animals.ant EnumValue: Animals.ant [value=1] -- Animals.ant.value 1 The aforementioned deprecated syntax refers to __call__ with a single arguments (the convenience API by definition requires more than one). I don't understand why having Enum() be the convenience function rules out `Animals(1)` from returning `Animals.ant`. Because we already have a way to do that: Animals[1]. Why do you need two slightly different ways to do the same? Moreover, why do you want to make Animals.__call__ behave very differently based only on the number of args? This seems to be un-pythonic in multiple ways. I think we're talking past each other (or I'm not awake yet ;). Animals is a class. Giving Animals a parameter (such as 1 or 'ant') should return the instance that matches. This is how classes work. I don't understand your assertion that there is another way to call Animals... do you mean something like: -- MoreAnimals = Animals('MoreAnimals', 'bird worm insect') Yes, this works in the current implementation. But I'm realizing that the recent proposals of making isinstance(Color.red, Color) True will turn things around anyway so this discussion may be moot. Eli ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On 25/04/2013 15:22, MRAB wrote: On 25/04/2013 14:34, Lennart Regebro wrote: On Thu, Apr 25, 2013 at 2:57 PM, Antoine Pitrou solip...@pitrou.net wrote: I can think of many usecases where I want to *embed* base64-encoded data in a larger text *before* encoding that text and transmitting it over a 8-bit channel. That still doesn't mean that this should be the default behavior. Just because you *can* represent base64 as Unicode text doesn't mean that it should be. [snip] One use case where you clearly *do* want the base64 encoded data to be unicode strings is because you want to embed it in a text discussing base64 strings, for a blog or a book or something. That doesn't seem to be a very common usecase. For the most part you base64 encode things because it's going to be transmitted, and hence the natural result of a base64 encoding should be data that is ready to be transmitted, hence byte strings, and not Unicode strings. Python 3 doesn't *view* text as unicode, it *represents* it as unicode. I don't agree that there is a significant difference between those wordings in this context. The end result is the same: Things intended to be handled/seen as textual should be unicode strings, things intended for data exchange should be byte strings. Something that is base64 encoded is primarily intended for data exchange. A base64 encoding should therefore return byte strings, especially since most API's that perform this transmission will take byte strings as input. If you want to include this in textual data, for whatever reason, like printing it in a book, then the conversion is trivial, but that is clearly the less common use case, and should therefore not be the default behavior. base64 is a way of encoding binary data as text. The problem is that traditionally text has been encoded with one byte per character, except in those locales where there were too many characters in the character set for that to be possible. In Python 3 we're trying to stop mixing binary data (bytestrings) with text (Unicode strings). RFC 4648 says Base encoding of data is used in many situations to store or transfer data in environments that, perhaps for legacy reasons, are restricted to US-ASCII [1] data.. To me, US-ASCII is an encoding, so it appears to be talking about encoding binary data (bytestrings) to ASCII-encoded text (bytestrings). ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 09:34 AM, Eli Bendersky wrote: On Thu, Apr 25, 2013 at 8:46 AM, Ethan Furman et...@stoneleaf.us mailto:et...@stoneleaf.us wrote: On 04/25/2013 06:03 AM, Eli Bendersky wrote: The __call__ syntax has been repurposed for the convenience API: -- Animals = Enum('Animals', 'ant bee cat dog') -- Animals Animals {ant: 1, bee: 2, cat: 3, dog: 4} -- Animals.ant EnumValue: Animals.ant [value=1] -- Animals.ant.value 1 The aforementioned deprecated syntax refers to __call__ with a single arguments (the convenience API by definition requires more than one). I don't understand why having Enum() be the convenience function rules out `Animals(1)` from returning `Animals.ant`. Because we already have a way to do that: Animals[1]. Why do you need two slightly different ways to do the same? Moreover, why do you want to make Animals.__call__ behave very differently based only on the number of args? This seems to be un-pythonic in multiple ways. I think we're talking past each other (or I'm not awake yet ;). Animals is a class. Giving Animals a parameter (such as 1 or 'ant') should return the instance that matches. This is how classes work. I don't understand your assertion that there is another way to call Animals... do you mean something like: -- MoreAnimals = Animals('MoreAnimals', 'bird worm insect') ? -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On Thu, Apr 25, 2013 at 5:27 PM, Antoine Pitrou solip...@pitrou.net wrote: Le Thu, 25 Apr 2013 15:34:45 +0200, Lennart Regebro rege...@gmail.com a écrit : I don't agree that there is a significant difference between those wordings in this context. The end result is the same: Things intended to be handled/seen as textual should be unicode strings, things intended for data exchange should be byte strings. I don't think this distinction is meaningful at all. OK, then I think we have found the core of the problem, and the end of the discussion (from my side, that is). In the end, everything is a byte string on a classical computer (including unicode strings displayed on your monitor, obviously). Yes of course. Especially since my monitor is an output device. ;-) If you think the technicalities of an operation should never be hidden or abstracted away, then you're better off with C than Python ;-) The whole point is that Python *does* abstract it away. It abstract the internals of Unicode strings in such a way that they are no longer, conceptually, 8-bit data. This *is* a distinction Python does, and it is a useful distinction. I do not see any reason to remove it. http://regebro.wordpress.com/2011/03/23/unconfusing-unicode-what-is-unicode/ //Lennart ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
Lennart Regebro writes: On Thu, Apr 25, 2013 at 4:22 PM, MRAB pyt...@mrabarnett.plus.com wrote: The JSON specification says that it's text. Its string literals can contain Unicode codepoints. It needs to be encoded to bytes for transmission and storage, but JSON itself is not a bytestring format. OK, fair enough. base64 is a way of encoding binary data as text. It's a way of encoding binary data using ASCII. There is a subtle but important difference. Yes, there is a difference, but I think you're wrong. RFC 4648 explicitly states that Base-n encodings are intended for human handling and even makes reference to character glyphs (the rationale for excluding confusable digits from the Base32 alphabet). That's text. Even if it is a rather restricted subset of text, those restrictions are much stronger than merely to ASCII, and they are based on aspects of text that go well beyond merely an encoding with a small code unit. In Python 3 we're trying to stop mixing binary data (bytestrings) with text (Unicode strings). Yup. And that's why a byte64 encoding shouldn't return Unicode strings. That's inaccurate. Antoine has presented several examples of why *some* base64 encoders might return Unicode strings, precisely because their output will be embedded in Unicode streams. Debugging the MIME composition functions in the email module is another. An accurate statement is that these use cases are relatively unusual. The common use case is feeding a binary stream directly into a wire protocol. Supporting that use case demands a base64 encoder with a bytes-to-bytes signature in the stdlib, for both convenience and to some extent efficiency. I don't really care if the stdlib supports the specialized use cases with a separate base64 encoder (Antoine suggested the binascii module), or if it leaves that up to the user (it's just an occasional use of .decode('ascii'), after all). ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
On Thu, 25 Apr 2013, Lennart Regebro wrote: On Thu, Apr 25, 2013 at 4:22 PM, MRAB pyt...@mrabarnett.plus.com wrote: The JSON specification says that it's text. Its string literals can contain Unicode codepoints. It needs to be encoded to bytes for transmission and storage, but JSON itself is not a bytestring format. OK, fair enough. base64 is a way of encoding binary data as text. It's a way of encoding binary data using ASCII. There is a subtle but important difference. It is a way of encoding arrays of 8-bit bytes as arrays of characters that are part of the printable, non-whitespace subset of the ASCII repertoire. Since the ASCII repertoire is now simply the first 128 code points in the Unicode repertoire, it is equally correct to say that base64 is a way of encoding binary data as Unicode text. In Python 3 we're trying to stop mixing binary data (bytestrings) with text (Unicode strings). Yup. And that's why a byte64 encoding shouldn't return Unicode strings. That is exactly why it should return Unicode strings. What bytes should get sent if base64 is used to send a byte array over an EBCDIC link? [*] Having said that, there may be other reasons for base64 encoding to return bytes - I can conceive of arguments involving efficiency, or practicality, or the most common use cases. So I can't say for sure what base64 encoding actually ought to return in Python. But the purist stance should be that base64 encoding should return text, i.e. a string, i.e. unicode. [*] I apologize to anybody who just ate. Isaac Morland CSCF Web Guru DC 2554C, x36650WWW Software Specialist ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 23, 2013, at 03:44 PM, Antoine Pitrou wrote: I'm having a problem with the proposed implementation. I haven't found any mention of it, so apologies if this has already been discussed: from flufl.enum import * class C(Enum): ... a = 1 ... b = 2 ... C.a.__class__ class 'flufl.enum._enum.EnumValue' isinstance(C.a, C) False isinstance(C(1), C) False It would really be better if instances were actual instances of the class, IMO. Ignore the single argument call syntax for Enums please. As Eli pointed out, you have getitem syntax for this and the single argument call syntax is deprecated. It will be removed in a future version of flufl.enum and need not appear in stdlib enum. TOOWTDI. C.a and C[1] return the same object, and it seems perfectly natural to me that this object is *not* an instance of the enum class. In fact, it seems completely weird to me that C.a would be an instance of the enum class. It seems very rare that a class has attributes that are instances of that class. It's not even easy to do with traditional syntax. class Foo: a = Foo() b = Foo() c = Foo() Huh? -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?
MRAB writes: RFC 4648 says Base encoding of data is used in many situations to store or transfer data in environments that, perhaps for legacy reasons, are restricted to US-ASCII [1] data.. To me, US-ASCII is an encoding, so it appears to be talking about encoding binary data (bytestrings) to ASCII-encoded text (bytestrings). I think that's a misreading, inconsistent with the rest of the RFC. The references to US-ASCII are not clearly normative, as the value- character mappings are given in tables, and are self-contained. (The one you quote is clearly informative, since it describes a use-case.) The term subset of US-ASCII suggests repertoire, not encoding, as does the use of alphabet to refer to these subsets. *Every* (other?) normative statement is very careful to say that input of a Base-n encoder is octets (with two uses of bytes in the definition of Base32), and the output is characters. There are no exceptions, and there are *no* references to encoding of characters or the corresponding character codes (except the possible implicit reference via US-ASCII). I can make no sense of those facts if the intent of the RFC is to restrict the output of a Base-n encoder to characters encoded in (8-bit) US-ASCII. Why not just say so, and use octets and their ASCII codes throughout, with the corresponding characters used as informative commentary? I think it much more likely that subset of the character repertoire of US-ASCII was intended, but abbreviated to subset of US-ASCII. This kind of abbreviation is very common in informal discussion of coded character sets. I admit it's a little surprising that the author would be so incautious in his use of US-ASCII, but if he really meant US-ASCII- the-encoding, I find the style of the rest of the RFC astonishing! ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 23, 2013, at 01:20 PM, Philip Jenvey wrote: Furthermore, you could define methods/fields on enum values, like Java's enums. There's no reason why you couldn't do this now, even with the class separation. I've documented the customization protocol, so just add these methods to the class you set in __value_factory__. No need to conflate the classes, which I think just adds unnecessary complexity and confusion. -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 23, 2013, at 10:24 AM, R. David Murray wrote: isinstance(C.a, C) False isinstance(C(1), C) False It would really be better if instances were actual instances of the class, IMO. The first False looks correct to me, I would not expect an enum value to be an instance of the class that holds it as an attribute. Agreed, completely. The second certainly looks odd, but what does it even mean to have an instance of an Enum class? It only looks odd because it's using failed, duplicate, deprecated syntax. Does this look similarly odd? isinstance(C[1], C) False given that ``C[1] is C.a``? -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
-BEGIN PGP SIGNED MESSAGE- Hash: SHA1 On 04/25/2013 12:39 PM, Ethan Furman wrote: Animals is a class. Giving Animals a parameter (such as 1 or 'ant') should return the instance that matches. Animals is *not* a class -- it just uses the class syntax as a convenient way to set up the names used to construct the new type. (This subtlety is why the metaclass hook is reputed to make peoples' brains explode). This is how classes work. Not really. Normal classes, when called, give you a new instance: they don't look up existing instances. Tres. - -- === Tres Seaver +1 540-429-0999 tsea...@palladion.com Palladion Software Excellence by Designhttp://palladion.com -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.11 (GNU/Linux) Comment: Using GnuPG with undefined - http://www.enigmail.net/ iEYEARECAAYFAlF5fa4ACgkQ+gerLs4ltQ7FSwCgzhcoXonMO/7W+xYMpM4EvtTj nPIAnAkHtWxFMaU3dqfFUclNQkUcJ2FZ =C0/7 -END PGP SIGNATURE- ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 23, 2013, at 04:33 PM, Antoine Pitrou wrote: That said, I don't see why it wouldn't make sense for an enum value to be an instance of that class. It can be useful to write `isinstance(value, MyEnumClass)`. Also, any debug facility which has a preference for writing out class names would produce a better output than the generic EnumValue. These semantics seem very weird to me, but at least we have a principled way to lie about it in Python 3. We could add this to the metaclass: def __instancecheck__(cls, instance): return instance.enum is cls or cls in instance.enum.__bases__ Thus: X = Enum('X', 'a b c') Y = Enum('Y', 'z y x') class Z(Y): ... d = 4 ... e = 5 ... isinstance(Z.d, Y) True isinstance(Z.d, Z) True isinstance(Z.d, X) False isinstance(Y.z, Y) True isinstance(Y.z, Z) False -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 23, 2013, at 10:53 AM, R. David Murray wrote: Ah. I'd be looking for a bug every time I saw isinstance(value, myEnumClass). A better class name for values and an API for getting that class from the EnumClass would be nice, though. (So that you could write isinstance(value, MyEnumClass.ValueClass), say.) I think if we did this, the attribute should be the same name as the one used to customize the value factory. Okay, this is horrible, but you could use isinstance(value, MyEnumClass.__value_factory__) The only thing stopping you from doing this right now is that when __value_factory__ is not given, a default is used which is not available on that attribute. That's easily corrected though. 1) really, to be consistent with the documentation, this should be __item_factory__ since the attributes of the enum class are called items, while items have an underlying value (e.g. A.b.value). 2) A better name than either __item_factory__ or __value_factory__ is welcome, though I guess that will spawn another bikeshedding, soul-destroying centi-thread. ;) 3) I'd like to make the implementation names consistent with the documentation in the next version of flufl.enum. -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 25, 2013, at 11:42 AM, Antoine Pitrou wrote: The PEP should mention how to get an enum from its raw value: Colors[1] EnumValue: Colors.red [value=1] or: Colors(1) EnumValue: Colors.red [value=1] No, this is a failed experiment. It's deprecated in flufl.enum and shouldn't make it into stdlib enum. getitem syntax is TOOWTDI. It would perhaps be nice to have a .get() method that return None if the raw value is unknown: Colors(42) ... ValueError: 42 Colors.get(42) class Methods(Enum): set = 1 get = 2 delete = 3 What is Methods.get? Catching the ValueError ``Methods[5]`` would raise doesn't seem so bad. -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
-BEGIN PGP SIGNED MESSAGE- Hash: SHA256 On Apr 25, 2013, at 03:02 PM, Tres Seaver wrote: On 04/25/2013 12:39 PM, Ethan Furman wrote: Animals is a class. Giving Animals a parameter (such as 1 or 'ant') should return the instance that matches. Animals is *not* a class -- it just uses the class syntax as a convenient way to set up the names used to construct the new type. (This subtlety is why the metaclass hook is reputed to make peoples' brains explode). Thanks for the great explanation! :) - -Barry -BEGIN PGP SIGNATURE- Version: GnuPG v1.4.12 (GNU/Linux) iQIcBAEBCAAGBQJReYSxAAoJEBJutWOnSwa/1a8QALXlY5GkrDTgjTNc+i3VFbpW nQ+5iYSUKk7E7A5HTE/GO1thG/3lVVLQpDvuTP+ETqHiVgZ/oKI0WFpfC7C6h85W U7qclwjfZ0kng529FscwNcICgPilHng/gOR4msatje59R9Sw54mDkIYDHllhYzdZ R1NeWzfBmKL9aZJ3xGaIKHEB6Cwwk6ZL0F7S87Voe9ipd6ihRPbJK4y574XPe/4i m8jIrEVHI/9KCiDEdJrMXX7u+61jLEmWW9UnMuDJkNItxg/oiVwknSd2munDh1Ti yf7dZPkfx4Dcarv3DH5K/D/wo8OaOiqnvrM0qTImQObCWk8RswnGT3/SJmBNsfmN gndc+UTcVDYsVHtr57SEc79Y6vEAgdOlkrOChgzEoXUh9DS2slYFGuVMajncRJTI RY14k2KzPy1FdPysADk3KW6BIZRvZHMvszNFcEQiMwrDv98zFPfCqsm1KME7eBSg 4fjD0e5f8V+yLCyeUMUZxB6KhFyPdDi53w9X2mOQx9TPJqOJPNS7kzgGcMxagLMI BEw+3L3c5B5FZSd9JIQeIm3r5Cfee9Dvfgcfd5Y3QsHzaGCSSermRXs0cqRS51Bl 4LT39RDm6E+rSguR8PSOabmhwUrfhr2KMzkfZXtR8RwStPH4Tii8zpiSgY88k9JD XUZvZxjFCwWl3syPcMNR =Eglp -END PGP SIGNATURE- ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 12:02 PM, Tres Seaver wrote: On 04/25/2013 12:39 PM, Ethan Furman wrote: Animals is a class. Giving Animals a parameter (such as 1 or 'ant') should return the instance that matches. Animals is *not* a class -- it just uses the class syntax as a convenient way to set up the names used to construct the new type. (This subtlety is why the metaclass hook is reputed to make peoples' brains explode). So Animals is a type? Like int? -- int('5') # 5 -- Animal(1) # I think it should be Animal.ant ;) This is how classes work. Not really. Normal classes, when called, give you a new instance: they don't look up existing instances. You mean like bool? -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 11:44 AM, Barry Warsaw wrote: On Apr 23, 2013, at 03:44 PM, Antoine Pitrou wrote: I'm having a problem with the proposed implementation. I haven't found any mention of it, so apologies if this has already been discussed: from flufl.enum import * class C(Enum): ... a = 1 ... b = 2 ... C.a.__class__ class 'flufl.enum._enum.EnumValue' isinstance(C.a, C) False isinstance(C(1), C) False It would really be better if instances were actual instances of the class, IMO. Ignore the single argument call syntax for Enums please. As Eli pointed out, you have getitem syntax for this and the single argument call syntax is deprecated. It will be removed in a future version of flufl.enum and need not appear in stdlib enum. TOOWTDI. For me, the getitem syntax on a class seems odd and the call syntax is TOOWTDI. C.a and C[1] return the same object, and it seems perfectly natural to me that this object is *not* an instance of the enum class. In fact, it seems completely weird to me that C.a would be an instance of the enum class. It seems very rare that a class has attributes that are instances of that class. It's not even easy to do with traditional syntax. class Foo: a = Foo() b = Foo() c = Foo() Obviously you need a metaclass in there. ;) -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 25, 2013, at 01:18 PM, Ethan Furman wrote: Ignore the single argument call syntax for Enums please. As Eli pointed out, you have getitem syntax for this and the single argument call syntax is deprecated. It will be removed in a future version of flufl.enum and need not appear in stdlib enum. TOOWTDI. For me, the getitem syntax on a class seems odd and the call syntax is TOOWTDI. Not if you think of it as a lookup operation instead of an instantiation operation. It really is the former because neither syntax creates new enum item objects, it just returns an already existing one. -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 2:17 PM, Barry Warsaw ba...@python.org wrote: On Apr 25, 2013, at 01:18 PM, Ethan Furman wrote: Ignore the single argument call syntax for Enums please. As Eli pointed out, you have getitem syntax for this and the single argument call syntax is deprecated. It will be removed in a future version of flufl.enum and need not appear in stdlib enum. TOOWTDI. For me, the getitem syntax on a class seems odd and the call syntax is TOOWTDI. Not if you think of it as a lookup operation instead of an instantiation operation. It really is the former because neither syntax creates new enum item objects, it just returns an already existing one. I think it's important to stress what this syntax is actually going to be used for. No one (I hope) is actually going to write Animals(1) or Animals[1]. They will write Animals.ant - this is what enums are for in the first place! The way I see it, this syntax is for enabling *programmatic access* - if you pull the value from a DB and want to convert it to an actual enum value, etc. So do we really need to have two syntaxes for this? The call syntax already has other uses, and it's weird because: Enum() - Creates new enums Animals() -- accesses values ?! This is contradictory Animals[...] to serve as a by-value lookup makes sense, though. Eli ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 25, 2013, at 02:25 PM, Eli Bendersky wrote: I think it's important to stress what this syntax is actually going to be used for. No one (I hope) is actually going to write Animals(1) or Animals[1]. They will write Animals.ant - this is what enums are for in the first place! The way I see it, this syntax is for enabling *programmatic access* - if you pull the value from a DB and want to convert it to an actual enum value, etc. So do we really need to have two syntaxes for this? Excellent point, and no, we don't :). The call syntax already has other uses, and it's weird because: Enum() - Creates new enums Animals() -- accesses values ?! This is contradictory Animals[...] to serve as a by-value lookup makes sense, though. I think so too. :) Note that I discovered that the same two-value call syntax on Enum can be used on the derived classes. It's exactly the same as using subclassing syntax to extend an existing enum. E.g. class A(Enum): ... a = 1 ... b = 2 ... c = 3 ... class B(A): ... d = 4 ... e = 5 ... B.a is A.a True X = Enum('X', 'a b c') Y = X('Y', (('d', 4), ('e', 5))) Y.a is X.a True That's a nice symmetry. -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 02:17 PM, Barry Warsaw wrote: On Apr 25, 2013, at 01:18 PM, Ethan Furman wrote: Ignore the single argument call syntax for Enums please. As Eli pointed out, you have getitem syntax for this and the single argument call syntax is deprecated. It will be removed in a future version of flufl.enum and need not appear in stdlib enum. TOOWTDI. For me, the getitem syntax on a class seems odd and the call syntax is TOOWTDI. Not if you think of it as a lookup operation instead of an instantiation operation. It really is the former because neither syntax creates new enum item objects, it just returns an already existing one. True, but I don't. ;) I think the closest comparable thing in Python is the boolean class; while True and False are not attributes of bool, they are the only two instances, and invoking bool is going to return one of the existing bool instances (which is to say, True or False). It's basically a conversion from whatever to bool. -- bool('something') # returns True -- bool(None) # returns False Similarly, an Enum converts a string or a number to it's comparable enumerator (right word, Stephen?) -- class Animal(Enum): ... ant = 1 ... bee = 2 ... fly = 3 -- Animal(2) # should return Animal.bee -- Animal('ant') # should return Animal.ant It seems to me that storing the instances on the class as attributes is mostly for convenience; we could just as easily not, and change the repr of enumerators to 'Animal ant [int=1]'. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 11:50 AM, Barry Warsaw ba...@python.org wrote: On Apr 23, 2013, at 10:24 AM, R. David Murray wrote: isinstance(C.a, C) False isinstance(C(1), C) False It would really be better if instances were actual instances of the class, IMO. The first False looks correct to me, I would not expect an enum value to be an instance of the class that holds it as an attribute. Agreed, completely. The second certainly looks odd, but what does it even mean to have an instance of an Enum class? It only looks odd because it's using failed, duplicate, deprecated syntax. Does this look similarly odd? isinstance(C[1], C) False given that ``C[1] is C.a``? I don't know what's going on, but it feels like we had this same discussion a week ago, and I still disagree. Disregarding, the C[i] notation, I feel quite strongly that in the following example: class Color(Enum): red = 1 white = 2 blue = 3 orange = 4 the values Color.red etc. should be instances of Color. This is how things work in all other languages that I am aware of that let you define enums. -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 25, 2013, at 02:54 PM, Guido van Rossum wrote: I don't know what's going on, Mostly that this is my first opportunity to chime in on the subject. but it feels like we had this same discussion a week ago, and I still disagree. Disregarding, the C[i] notation, I feel quite strongly that in the following example: class Color(Enum): red = 1 white = 2 blue = 3 orange = 4 the values Color.red etc. should be instances of Color. This is how things work in all other languages that I am aware of that let you define enums. Is it enough that isinstance(Color.red, Color) returns True, or do you really-and-truly want them to be instances of Color? I still think it's weird, but I could accept the former if you're flexible on the latter, which in some sense is just an implementation detail anyway. -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 25, 2013, at 02:30 PM, Ethan Furman wrote: -- class Animal(Enum): ... ant = 1 ... bee = 2 ... fly = 3 -- Animal(2) # should return Animal.bee -- Animal('ant') # should return Animal.ant It seems to me that storing the instances on the class as attributes is mostly for convenience; we could just as easily not, and change the repr of enumerators to 'Animal ant [int=1]'. So I guess you would still expect these to hold true: Animal.ant is Animal(2) True Animal.ant is Animal('ant') True -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 21, 2013, at 09:12 PM, R. David Murray wrote: Regardless of the specific values involved, it is pretty much guaranteed that if anything other than definition order is used we *will* get bug reports/enhancement requests to fix it, on a regular basis. We can choose to live with that, but we should admit that it will will happen :) What's the definition order here? Methods = Enum('Methods', {'set': 8, 'get': 15, 'delete': 16}) -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 22, 2013, at 10:55 AM, Tim Delaney wrote: Would it be worthwhile storing a sorted version of the enum keys here? Or do you think the current space vs speed tradeoff is better? It's an implementation detail that doesn't bother me too much either way. -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 3:02 PM, Barry Warsaw ba...@python.org wrote: On Apr 25, 2013, at 02:54 PM, Guido van Rossum wrote: I don't know what's going on, Mostly that this is my first opportunity to chime in on the subject. but it feels like we had this same discussion a week ago, and I still disagree. Disregarding, the C[i] notation, I feel quite strongly that in the following example: class Color(Enum): red = 1 white = 2 blue = 3 orange = 4 the values Color.red etc. should be instances of Color. This is how things work in all other languages that I am aware of that let you define enums. Is it enough that isinstance(Color.red, Color) returns True, or do you really-and-truly want them to be instances of Color? I still think it's weird, but I could accept the former if you're flexible on the latter, which in some sense is just an implementation detail anyway. Clearly this is a trick question. :-) I was told when this was brought up previously (a week ago?) that it would be simple to make it truly the same class. I suppose you were going to propose to use isinstance() overloading, but I honestly think that Color.red.__class__ should be the same object as Color. -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 22, 2013, at 10:42 AM, Nick Coghlan wrote: On Mon, Apr 22, 2013 at 10:28 AM, Barry Warsaw ba...@python.org wrote: On Apr 22, 2013, at 09:02 AM, Nick Coghlan wrote: Iteration order matters a lot if you don't want people complaining about enums being broken: class Days(enum.Enum): Monday = 1 Tuesday = 2 Wednesday = 3 Thursday = 4 Friday = 5 Saturday = 6 Sunday = 7 Sorry, that's still not a complete use case. I don't see why you'd depend on iteration order over Days for any particular functionality. You mean other than printing the days of the week in order without needing to worry about the specific values assigned to them? My point is, days of the week has a natural ordering, so why wouldn't you use IntEnum for that? Problem solved. There's no natural ordering for things like colors or animals, so the values don't matter. I claim that neither does the repr or iteration order except that the former should be *predictable* and it would be nice to define the latter, but that's not actually necessary. Undefined iteration order would be just as fine for Enum. Using sort-by-name also introduces other weirdness, such as subclasses potentially inserting their values in the middle of inherited names, rather than appending to the end as one might reasonably expect. I don't see how iteration order could affect how you'd write the derived class syntax. While using sort-by-name is better than not providing a consistent ordering at all, using definition order is substantially less surprising than sorting by key name, and PEP 3115 and collections.OrderedDict makes that easy to support in Python 3.x. The fact that this will make for a behavioural difference between the standard library and flufl.enum does *not* count as an argument for making the behaviour of the standard library version less intuitive (if that was a valid argument, the 3.3+ ipaddress module would look a *lot* more like it's ipaddr inspiration). Maybe. If they care about iteration order at all, then they will have to special case their code for Python's 3.3, which means they'll probably have to explicitly sort it anyway for the foreseeable future. I guess it'll be moot in 10 years though. ;) They probably don't care about iteration order, which I think will be the common case (heck, iteration over the enum will be pretty rare *anyway*). -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 02:25 PM, Eli Bendersky wrote: On Thu, Apr 25, 2013 at 2:17 PM, Barry Warsaw ba...@python.org mailto:ba...@python.org wrote: On Apr 25, 2013, at 01:18 PM, Ethan Furman wrote: For me, the getitem syntax on a class seems odd and the call syntax is TOOWTDI. Not if you think of it as a lookup operation instead of an instantiation operation. It really is the former because neither syntax creates new enum item objects, it just returns an already existing one. I think it's important to stress what this syntax is actually going to be used for. No one (I hope) is actually going to write Animals(1) or Animals[1]. They will write Animals.ant - this is what enums are for in the first place! The way I see it, this syntax is for enabling *programmatic access* - if you pull the value from a DB and want to convert it to an actual enum value, etc. So do we really need to have two syntaxes for this? The call syntax already has other uses, and it's weird because: Enum() - Creates new enums Animals() -- accesses values ?! This is contradictory Animals[...] to serve as a by-value lookup makes sense, though. How about consistency? If I'm converting several types of items from a database I'd like to do something like: result = [] for field in row: type = get_type(field) # returns int, bool, str, or an Enum type result.append(type(field)) What you're suggesting means complicating the logic: result = [] for field in row: type = get_type(field) # returns int, bool, str, or an Enum type if isinstance(type, Enum): result.append(type[field]) else: result.append(type(field)) We just got NoneType fixed to actually return None instead of raising an error for this same type of scenario, why should we muddy it up again? -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Apr 25, 2013, at 03:19 PM, Guido van Rossum wrote: Clearly this is a trick question. :-) A bit, yes. :) I was told when this was brought up previously (a week ago?) that it would be simple to make it truly the same class. It didn't sound simple to me, but I haven't seen any actual code yet. I suppose you were going to propose to use isinstance() overloading, but I honestly think that Color.red.__class__ should be the same object as Color. Yes, a custom __instancecheck__() is two lines of code. I just can't get over the weirdness of a class having attributes which are actual instances of itself. -Barry signature.asc Description: PGP signature ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 3:29 PM, Barry Warsaw ba...@python.org wrote: On Apr 25, 2013, at 03:19 PM, Guido van Rossum wrote: I suppose you were going to propose to use isinstance() overloading, but I honestly think that Color.red.__class__ should be the same object as Color. Yes, a custom __instancecheck__() is two lines of code. I just can't get over the weirdness of a class having attributes which are actual instances of itself. TBH I had a hard time getting over the fact that even though the class said a = 1, C.a is not the integer 1. But I did get over it. Hopefully you can get over *this* weirdness. -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, 25 Apr 2013 14:37:29 -0700, Ethan Furman et...@stoneleaf.us wrote: On 04/25/2013 02:25 PM, Eli Bendersky wrote: On Thu, Apr 25, 2013 at 2:17 PM, Barry Warsaw ba...@python.org mailto:ba...@python.org wrote: On Apr 25, 2013, at 01:18 PM, Ethan Furman wrote: For me, the getitem syntax on a class seems odd and the call syntax is TOOWTDI. Not if you think of it as a lookup operation instead of an instantiation operation. It really is the former because neither syntax creates new enum item objects, it just returns an already existing one. I think it's important to stress what this syntax is actually going to be used for. No one (I hope) is actually going to write Animals(1) or Animals[1]. They will write Animals.ant - this is what enums are for in the first place! The way I see it, this syntax is for enabling *programmatic access* - if you pull the value from a DB and want to convert it to an actual enum value, etc. So do we really need to have two syntaxes for this? The call syntax already has other uses, and it's weird because: Enum() - Creates new enums Animals() -- accesses values ?! This is contradictory Animals[...] to serve as a by-value lookup makes sense, though. How about consistency? If I'm converting several types of items from a database I'd like to do something like: result = [] for field in row: type = get_type(field) # returns int, bool, str, or an Enum type result.append(type(field)) What you're suggesting means complicating the logic: result = [] for field in row: type = get_type(field) # returns int, bool, str, or an Enum type if isinstance(type, Enum): result.append(type[field]) else: result.append(type(field)) We just got NoneType fixed to actually return None instead of raising an error for this same type of scenario, why should we muddy it up again? I haven't cared much about this particular bikeshed, but I find this a somewhat compelling argument. I'm working on a system that depends on exactly this standard behavior of (most?) built in types in Python: if you pass an instance or something that can be converted to an instance to the type constructor, you get back an instance. If Enums break that paradigm(*), someone would have to write a custom class that provided that behavior in order to use Enums with my system. I wouldn't say that was a show stopper, especially since my system may never go anywhere :), but it certainly is an exemplar of the issue Eli is talking about. --David (*) Hmm. NoneType(None) is still an error. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 03:07 PM, Barry Warsaw wrote: On Apr 25, 2013, at 02:30 PM, Ethan Furman wrote: -- class Animal(Enum): ... ant = 1 ... bee = 2 ... fly = 3 -- Animal(2) # should return Animal.bee -- Animal('ant') # should return Animal.ant It seems to me that storing the instances on the class as attributes is mostly for convenience; we could just as easily not, and change the repr of enumerators to 'Animal ant [int=1]'. So I guess you would still expect these to hold true: Animal.ant is Animal(2) True Animal.ant is Animal('ant') True Well, except for ant being 1, yeah. ;) -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 03:11 PM, Barry Warsaw wrote: On Apr 21, 2013, at 09:12 PM, R. David Murray wrote: Regardless of the specific values involved, it is pretty much guaranteed that if anything other than definition order is used we *will* get bug reports/enhancement requests to fix it, on a regular basis. We can choose to live with that, but we should admit that it will will happen :) What's the definition order here? Methods = Enum('Methods', {'set': 8, 'get': 15, 'delete': 16}) Whatever random order {}.keys() returns -- and python programmers should be expecting that (or at least smack themselves for forgetting it ;) -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 03:46 PM, R. David Murray wrote: On Thu, 25 Apr 2013 14:37:29 -0700, Ethan Furman et...@stoneleaf.us wrote: On 04/25/2013 02:25 PM, Eli Bendersky wrote: On Thu, Apr 25, 2013 at 2:17 PM, Barry Warsaw ba...@python.org mailto:ba...@python.org wrote: On Apr 25, 2013, at 01:18 PM, Ethan Furman wrote: For me, the getitem syntax on a class seems odd and the call syntax is TOOWTDI. Not if you think of it as a lookup operation instead of an instantiation operation. It really is the former because neither syntax creates new enum item objects, it just returns an already existing one. I think it's important to stress what this syntax is actually going to be used for. No one (I hope) is actually going to write Animals(1) or Animals[1]. They will write Animals.ant - this is what enums are for in the first place! The way I see it, this syntax is for enabling *programmatic access* - if you pull the value from a DB and want to convert it to an actual enum value, etc. So do we really need to have two syntaxes for this? The call syntax already has other uses, and it's weird because: Enum() - Creates new enums Animals() -- accesses values ?! This is contradictory Animals[...] to serve as a by-value lookup makes sense, though. How about consistency? If I'm converting several types of items from a database I'd like to do something like: result = [] for field in row: type = get_type(field) # returns int, bool, str, or an Enum type result.append(type(field)) What you're suggesting means complicating the logic: result = [] for field in row: type = get_type(field) # returns int, bool, str, or an Enum type if isinstance(type, Enum): result.append(type[field]) else: result.append(type(field)) We just got NoneType fixed to actually return None instead of raising an error for this same type of scenario, why should we muddy it up again? I haven't cared much about this particular bikeshed, but I find this a somewhat compelling argument. I'm working on a system that depends on exactly this standard behavior of (most?) built in types in Python: if you pass an instance or something that can be converted to an instance to the type constructor, you get back an instance. If Enums break that paradigm(*), someone would have to write a custom class that provided that behavior in order to use Enums with my system. I wouldn't say that was a show stopper, especially since my system may never go anywhere :), but it certainly is an exemplar of the issue Eli is talking about. Um, did you mean of the issue Ethan is talking about? 'Cause Eli is against it. (*) Hmm. NoneType(None) is still an error. Hmm, so it is. When I pushed for the change just having NoneType() work was sufficient. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 03:23 PM, Barry Warsaw wrote: On Apr 22, 2013, at 10:42 AM, Nick Coghlan wrote: On Mon, Apr 22, 2013 at 10:28 AM, Barry Warsaw ba...@python.org wrote: On Apr 22, 2013, at 09:02 AM, Nick Coghlan wrote: Iteration order matters a lot if you don't want people complaining about enums being broken: class Days(enum.Enum): Monday = 1 Tuesday = 2 Wednesday = 3 Thursday = 4 Friday = 5 Saturday = 6 Sunday = 7 Sorry, that's still not a complete use case. I don't see why you'd depend on iteration order over Days for any particular functionality. You mean other than printing the days of the week in order without needing to worry about the specific values assigned to them? My point is, days of the week has a natural ordering, so why wouldn't you use IntEnum for that? Problem solved. Because by using an IntEnum we lose the Enum type protection, which is one of the reasons to want an Enum type to begin with. There's no natural ordering for things like colors or animals, so the values don't matter. I claim that neither does the repr or iteration order except that the former should be *predictable* and it would be nice to define the latter, but that's not actually necessary. Undefined iteration order would be just as fine for Enum. People like things sorted (or am I alone here?) There are three obvious natural orderings: 1 - value 2 - definition order 3 - name And that's my order of preference for them. Using sort-by-name also introduces other weirdness, such as subclasses potentially inserting their values in the middle of inherited names, rather than appending to the end as one might reasonably expect. I don't see how iteration order could affect how you'd write the derived class syntax. It probably wouldn't, but if I had: -- class Color(Enum): ... red = 1 ... blue = 2 ... green = 3 -- class MoreColor(Color): ... cyan = 4 ... magenta = 5 ... yellow = 6 I would be very unhappy with: -- list(MoreColor) [ MoreColor.blue, MoreColor.cyan, MoreColor.green, MoreColor.magenta, MoreColor.red, MoreColor.yellow, ] because 1) it's not the order I defined it in; and 2) it's not in value order. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 4/25/2013 3:37 PM, Guido van Rossum wrote: On Thu, Apr 25, 2013 at 3:29 PM, Barry Warsawba...@python.org wrote: On Apr 25, 2013, at 03:19 PM, Guido van Rossum wrote: I suppose you were going to propose to use isinstance() overloading, but I honestly think that Color.red.__class__ should be the same object as Color. Yes, a custom __instancecheck__() is two lines of code. I just can't get over the weirdness of a class having attributes which are actual instances of itself. TBH I had a hard time getting over the fact that even though the class said a = 1, C.a is not the integer 1. But I did get over it. Hopefully you can get over*this* weirdness. :) The minute metaclass is involved, it is no longer a class, but a whatchamacallit. What blows people's minds regarding metaclasses is that they aren't necessarily what they look like. In this case, we are defining enumerations using a syntax that sort of looks like class attribute syntax, which are neither classes, nor types, but rather a collection of cooperative objects with shared methods in a shared subsidiary namespace. Perhaps instead of metaclass altering the behavior of classes, it might have been less confusing to simply define a new keyword whatchamacallit (or metaclass) that have behaviors defined by the various methods defined in connection with it... while the existing techniques exist and would require a deprecation cycle to eliminate, it may not be too late to define alternate keywords that make it clearer that using such keywords, is making user-defined objects of some sort, class-like or -unlike, type-like or -unlike, object-like or -unlike, cooperative or not, etc., all by user definition. Any behavioral resemblance to classes would be only by user specification of same (perhaps such a specification of same as class should be easy). My question is, once an enumeration is defined, is there a way, short of element-by-element assignment, to import the individual enumeration instances into the current namespace, so that I can say red instead of Color.red ? I understand the benefits of avoiding name collisions when there are lots of enumerations, and lots of opportunities for name collections between, say, RGBColor and CYMKColor... but there are lots of uses for enumerations where the subsidiary namespace is just aggravating noise. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] NoneType(None) raises exception
We just fixed NoneType() to return None instead of raising an exception. Another use-case for calling NoneType is working with ORMs: result = [] for field in row: type = get_type(field) # returns int, bool, str, NoneType, ... result.append(type(field)) if field is None, the resulting call is NoneType(None), and since NoneType doesn't take any parameters we get an exception. Is it worth filing a bug to have NoneType accept one optional argument, which defaults to None, and must be None, else raise an exception? Or should it be: class NoneType: def __new__(cls, *args, **kws): return None Which is basically what my 2.x none() helper function does... -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] NoneType(None) raises exception
2013/4/25 Ethan Furman et...@stoneleaf.us: We just fixed NoneType() to return None instead of raising an exception. Another use-case for calling NoneType is working with ORMs: result = [] for field in row: type = get_type(field) # returns int, bool, str, NoneType, ... result.append(type(field)) if field is None, the resulting call is NoneType(None), and since NoneType doesn't take any parameters we get an exception. Is it worth filing a bug to have NoneType accept one optional argument, which defaults to None, and must be None, else raise an exception? IMO, that has no interesting semantic meaning and defining your own none function is a perfectly acceptable way of dealing with your problem. -- Regards, Benjamin ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] NoneType(None) raises exception
On 26/04/2013 00:09, Ethan Furman wrote: We just fixed NoneType() to return None instead of raising an exception. Another use-case for calling NoneType is working with ORMs: result = [] for field in row: type = get_type(field) # returns int, bool, str, NoneType, ... result.append(type(field)) if field is None, the resulting call is NoneType(None), and since NoneType doesn't take any parameters we get an exception. Is it worth filing a bug to have NoneType accept one optional argument, which defaults to None, and must be None, else raise an exception? Or should it be: class NoneType: def __new__(cls, *args, **kws): return None Which is basically what my 2.x none() helper function does... On the one hand, NoneType(None) seems a strange thing to do. On the other hand: type(value)(value) == value would return True for the built-in types (will certain exceptions, such as when value is float(NaN)). Let's ask the Zen: Special cases aren't special enough to break the rules. Although practicality beats purity. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 4/25/2013 3:23 PM, Barry Warsaw wrote: My point is, days of the week has a natural ordering, so why wouldn't you use IntEnum for that? Problem solved. While the ordering is natural, some implementations start from 0, some start from 1, and on the naming side, some start from Sunday, and some start from Monday. So there are lots of opportunities for the numbers vary, and having easy conversions to int which expose those numbers and allow comparisons to integers, is adding problems, not solving them. On 4/25/2013 3:36 PM, Ethan Furman wrote: People like things sorted (or am I alone here?) There are three obvious natural orderings: 1 - value 2 - definition order 3 - name And that's my order of preference for them. So, being blissfully unaware of the implementation issues, not having yet read the implementation, I suggest that the preferred iteration order should be a characteristic of the Enum when defined, and/or that there should be a method to obtain a list in any of the natural orderings (specifying value ordering may add a restriction that the values be orderable, if done at definition time; if done only on retrieval, attempting to access the list by value would raise an exception). Another possible ordering would be random, and for enumerations with values that are tuples or lists or hashes, ordering by some specified element would be conceivable. On the other hand, except for definition order, all the other possible orderings could be derived externally to the enumeration. So if enumerations preserve/provide definition order, all the others could be implemented externally or as subtypes. Definition order, then is the basic ordering for enumerations because it cannot be externally derived, other than by reading the source code. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] NoneType(None) raises exception
On 26/04/13 09:56, MRAB wrote: On the one hand, NoneType(None) seems a strange thing to do. Only when you write it out like that as constants. It's no more, or less, strange than str('spam') or int(1) or list([]). Why would you do that? But as soon as you think of it in general terms: some_type(some_instance) that's a pretty normal thing to do. And if it just so happened that some_instance were an instance of some_type, it would be surprising if the call failed. (I initially wrote astonishing, but then I realised that some types take more than one argument, e.g. FunctionType. So it's merely surprising.) On the other hand: type(value)(value) == value would return True for the built-in types (will certain exceptions, such as when value is float(NaN)). Not an exception, that works fine in 3.3: value = float('nan') type(value)(value) nan Let's ask the Zen: Special cases aren't special enough to break the rules. Although practicality beats purity. I cannot think of any use-case where I would actively want NoneType(None) to fail. That would be like having bool(True) raise an exception. On the other hand, NoneType(x) for any other x ought to fail. -- Steven ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 04:26 PM, Glenn Linderman wrote: My question is, once an enumeration is defined, is there a way, short of element-by-element assignment, to import the individual enumeration instances into the current namespace, so that I can say red instead of Color.red ? I understand the benefits of avoiding name collisions when there are lots of enumerations, and lots of opportunities for name collections between, say, RGBColor and CYMKColor... but there are lots of uses for enumerations where the subsidiary namespace is just aggravating noise. You mean something like: -- class Color(Enum): ... RED = 1 ... GREEN = 2 ... BLUE = 3 -- Color.register() # puts Color in sys.modules -- from Color import * # doesn't work in a function, though :( -- BLUE Color.BLUE Yeah, that would be nice. ;) A bit dangerous, though -- what if another module does the same thing, but its Color is different? Better would be: -- Color.export(globals()) # put the enumerators in globals -- RED Color.RED -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 3:29 PM, Barry Warsawba...@python.org wrote: I just can't get over the weirdness of a class having attributes which are actual instances of itself. I wonder how many programmers will even notice that this characteristic exists. Exactly the same weirdness occurs in Java, but I had never thought about it until this discussion came up, and I wondered Hmmm... seems like this ought to happen in Java too, tried it out, and found that it did. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 26/04/2013 00:59, Glenn Linderman wrote: On 4/25/2013 3:23 PM, Barry Warsaw wrote: My point is, days of the week has a natural ordering, so why wouldn't you use IntEnum for that? Problem solved. While the ordering is natural, some implementations start from 0, some start from 1, and on the naming side, some start from Sunday, and some start from Monday. So there are lots of opportunities for the numbers vary, and having easy conversions to int which expose those numbers and allow comparisons to integers, is adding problems, not solving them. [snip] But there _is_ an ordering problem, in that the days wrap around. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 26/04/13 11:53, Ethan Furman wrote: -- from Color import * # doesn't work in a function, though :( Yeah, that would be nice. ;) A bit dangerous, though -- what if another module does the same thing, but its Color is different? It needs to put foo.Color in sys.modules, where foo is the name of the defining module. Then you do from foo.Color import * The drawback being that you need to write the name of the module into the import statement. It's disappointing that the import syntax doesn't have a way of saying this module. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] NoneType(None) raises exception
On 26/04/2013 01:27, Steven D'Aprano wrote: On 26/04/13 09:56, MRAB wrote: On the one hand, NoneType(None) seems a strange thing to do. Only when you write it out like that as constants. It's no more, or less, strange than str('spam') or int(1) or list([]). Why would you do that? None is a singleton, but instances of str, int, list, etc aren't. Why can it take an argument when there's only ever one of them? That's why it seems strange to me. But as soon as you think of it in general terms: some_type(some_instance) that's a pretty normal thing to do. And if it just so happened that some_instance were an instance of some_type, it would be surprising if the call failed. (I initially wrote astonishing, but then I realised that some types take more than one argument, e.g. FunctionType. So it's merely surprising.) On the other hand: type(value)(value) == value would return True for the built-in types (will certain exceptions, such as when value is float(NaN)). Not an exception, that works fine in 3.3: value = float('nan') type(value)(value) nan But: value = float('NaN') type(value)(value) == value False That's what I mean by it being an exception. Let's ask the Zen: Special cases aren't special enough to break the rules. Although practicality beats purity. I cannot think of any use-case where I would actively want NoneType(None) to fail. That would be like having bool(True) raise an exception. On the other hand, NoneType(x) for any other x ought to fail. OK, so practicality (or pragmatism) wins. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 26/04/13 13:03, MRAB wrote: But there _is_ an ordering problem, in that the days wrap around. Do we want a CircularEnum, then? Ordering would be defined only up to the starting value, which you would be required to specify when doing anything where it mattered. class Day(CircularEnum): sunday = 0 monday = 1 ... saturday = 6 list(Day.startingat(Day.tuesday)) -- [Day.tuesday, Day,wednesday, Day.thursday, Day.friday, Day.saturday, Day.sunday, Day.monday] Modular arithmetic would apply, so Day.saturday + 3 -- Day.tuesday That would be the replacement for Day(3), which would be disallowed. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] NoneType(None) raises exception
On 04/25/2013 05:27 PM, Steven D'Aprano wrote: On 26/04/13 09:56, MRAB wrote: On the other hand: type(value)(value) == value would return True for the built-in types (will certain exceptions, such as when value is float(NaN)). Not an exception, that works fine in 3.3: value = float('nan') type(value)(value) nan You missed the == part: type(value)(value) == value False Let's ask the Zen: Special cases aren't special enough to break the rules. Although practicality beats purity. I cannot think of any use-case where I would actively want NoneType(None) to fail. That would be like having bool(True) raise an exception. On the other hand, NoneType(x) for any other x ought to fail. Or, since the purpose of NoneType is to return None, just return None no matter what! Kind'a like 0 * anything == 0. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 06:03 PM, MRAB wrote: On 26/04/2013 00:59, Glenn Linderman wrote: On 4/25/2013 3:23 PM, Barry Warsaw wrote: My point is, days of the week has a natural ordering, so why wouldn't you use IntEnum for that? Problem solved. While the ordering is natural, some implementations start from 0, some start from 1, and on the naming side, some start from Sunday, and some start from Monday. So there are lots of opportunities for the numbers vary, and having easy conversions to int which expose those numbers and allow comparisons to integers, is adding problems, not solving them. [snip] But there _is_ an ordering problem, in that the days wrap around. Lots of counting systems wrap: seconds, minutes, hours, days of week, days of month, days of year, millimeters, inches, etc., etc., and so forth. We still apply ordering to them, and talk about 15 whatevers being less than 42 whatevers. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 06:23 PM, Greg Ewing wrote: On 26/04/13 13:03, MRAB wrote: But there _is_ an ordering problem, in that the days wrap around. Do we want a CircularEnum, then? Ordering would be defined only up to the starting value, which you would be required to specify when doing anything where it mattered. class Day(CircularEnum): sunday = 0 monday = 1 ... saturday = 6 list(Day.startingat(Day.tuesday)) -- [Day.tuesday, Day,wednesday, Day.thursday, Day.friday, Day.saturday, Day.sunday, Day.monday] Modular arithmetic would apply, so Day.saturday + 3 -- Day.tuesday That would be the replacement for Day(3), which would be disallowed. Interesting idea, but why does Day(3) have to be disallowed to make it work? -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] NoneType(None) raises exception
On Apr 25, 2013, at 04:09 PM, Ethan Furman wrote: We just fixed NoneType() to return None instead of raising an exception. Another use-case for calling NoneType is working with ORMs: result = [] for field in row: type = get_type(field) # returns int, bool, str, NoneType, ... result.append(type(field)) I know this use case came up w.r.t. the enum discussion, but I'm not sure it's relevant in a practical sense. Most of the Python ORMs I've worked with have an extension facility to allow custom types/classes to be stored and retrieved into database columns, and these converters always have intimate knowledge of the types they're dealing with, both on the Python side and on the db side. E.g. datetimes to take a pretty common standard Python data type. So while a generic callable API is nice, I'm not sure you'll ever be able to get full coverage over common Python types. -Barry ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 4/25/2013 4:53 PM, Ethan Furman wrote: On 04/25/2013 04:26 PM, Glenn Linderman wrote: My question is, once an enumeration is defined, is there a way, short of element-by-element assignment, to import the individual enumeration instances into the current namespace, so that I can say red instead of Color.red ? I understand the benefits of avoiding name collisions when there are lots of enumerations, and lots of opportunities for name collections between, say, RGBColor and CYMKColor... but there are lots of uses for enumerations where the subsidiary namespace is just aggravating noise. You mean something like: -- class Color(Enum): ... RED = 1 ... GREEN = 2 ... BLUE = 3 -- Color.register() # puts Color in sys.modules -- from Color import * # doesn't work in a function, though :( -- BLUE Color.BLUE Something like that, but that works in a function too :) Yeah, that would be nice. ;) A bit dangerous, though -- what if another module does the same thing, but its Color is different? Better would be: -- Color.export(globals()) # put the enumerators in globals -- RED Color.RED Globals? locals should be possible too. Or even something like: with Color: BLUE RED Although the extra indentation could also be annoying. One wouldn't want the module defining Color to automatically 'export' the colors: but rather a way to request an 'export' them into a particular scope. That way the proliferation of names into scopes is chosen by the programmer. import module_containing_color module_containing_color.Color.export_enumerations( globals ) or import module_containing_color module_containing_color.Color.export_enumerations( locals ) Or maybe locals is implicit, and in the file scope of a module, locals are globals anyway, so doing module_containing_color.Color.export_enumerations() would make the enumerations available to all definitions in the file, but inside a class or def doing the same thing would make the names direct members of the class or locals in the function. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Fri, Apr 26, 2013 at 8:29 AM, Barry Warsaw ba...@python.org wrote: On Apr 25, 2013, at 03:19 PM, Guido van Rossum wrote: Clearly this is a trick question. :-) A bit, yes. :) I was told when this was brought up previously (a week ago?) that it would be simple to make it truly the same class. It didn't sound simple to me, but I haven't seen any actual code yet. I'm the one who said I didn't see any obvious barriers to the merger, but I've realised there is one, and it's similar to one namedtuple struggles with: how to handle method definitions. With the current flufl.enum design, if you want to give instances of a particular enum additional behaviour, you can use a custom item type and add the methods there. Simple and relatively obvious. With a merged design, it becomes *really* hard to give the instances custom behaviour, because the metaclass will somehow have to differentiate between namespace entries that are intended to be callables, and those which are intended to be instances of the enum. This is not an easy problem to solve. So, while I was initially in the merge them camp, I'm back to thinking the core architecture of flufl.enum is correct, but there may be some API adjustment to do, such as: 1. Lose the __getitem__ on the metaclass, and replace that with __call__ 2. Ensure that isinstance(MyEnum.item, MyEnum) returns True (even though it isn't really) 3. Inspired by namedtuple, move the current Enum constructor functionality to an Enum._make() API (implemented either as a class method in Enum or as an ordinary method on the metaclass) Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] NoneType(None) raises exception
On Thu, Apr 25, 2013 at 9:12 PM, MRAB pyt...@mrabarnett.plus.com wrote: Only when you write it out like that as constants. It's no more, or less, strange than str('spam') or int(1) or list([]). Why would you do that? None is a singleton, but instances of str, int, list, etc aren't. Why can it take an argument when there's only ever one of them? That's why it seems strange to me. How about bool? False and True are singletons much like None is, and bool(False) == False; bool(True) == True. Sure the distinction is that all of those are useful as conversion functions, whereas NoneType would never be used that way. -- Devin ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 7:13 PM, Nick Coghlan ncogh...@gmail.com wrote: I'm the one who said I didn't see any obvious barriers to the merger, but I've realised there is one, and it's similar to one namedtuple struggles with: how to handle method definitions. With the current flufl.enum design, if you want to give instances of a particular enum additional behaviour, you can use a custom item type and add the methods there. Simple and relatively obvious. With a merged design, it becomes *really* hard to give the instances custom behaviour, because the metaclass will somehow have to differentiate between namespace entries that are intended to be callables, and those which are intended to be instances of the enum. This is not an easy problem to solve. It's really sad that this technical problem exists (and I realize what it is) -- because the obvious syntax (whose equivalent works in Java, BTW) *seems* so natural: class Color: red = 1 white = 2 blue = 3 orange = 4 def wave(self, n=1): for _ in range(n): print('Waving', self) a = Color.red a.wave() Color.orange.wave(3) So, while I was initially in the merge them camp, I'm back to thinking the core architecture of flufl.enum is correct, but there may be some API adjustment to do, such as: 1. Lose the __getitem__ on the metaclass, and replace that with __call__ 2. Ensure that isinstance(MyEnum.item, MyEnum) returns True (even though it isn't really) If the above syntax won't work, that isinstance() outcome isn't really important. :-( Can't we do some kind of callable check? There may be some weird decorators that won't work, but they aren't likely to be useful in this context. 3. Inspired by namedtuple, move the current Enum constructor functionality to an Enum._make() API (implemented either as a class method in Enum or as an ordinary method on the metaclass) -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 07:09 PM, Glenn Linderman wrote: On 4/25/2013 4:53 PM, Ethan Furman wrote: On 04/25/2013 04:26 PM, Glenn Linderman wrote: My question is, once an enumeration is defined, is there a way, short of element-by-element assignment, to import the individual enumeration instances into the current namespace, so that I can say red instead of Color.red ? I understand the benefits of avoiding name collisions when there are lots of enumerations, and lots of opportunities for name collections between, say, RGBColor and CYMKColor... but there are lots of uses for enumerations where the subsidiary namespace is just aggravating noise. You mean something like: -- class Color(Enum): ... RED = 1 ... GREEN = 2 ... BLUE = 3 -- Color.register() # puts Color in sys.modules -- from Color import * # doesn't work in a function, though :( -- BLUE Color.BLUE Something like that, but that works in a function too :) Not in Py3 it doesn't: Python 3.2.3 (default, Oct 19 2012, 19:53:16) [GCC 4.7.2] on linux2 Type help, copyright, credits or license for more information. -- def test(): ... from sys import * ... print('huh') ... File stdin, line 1 SyntaxError: import * only allowed at module level Yeah, that would be nice. ;) A bit dangerous, though -- what if another module does the same thing, but its Color is different? Better would be: -- Color.export(globals()) # put the enumerators in globals -- RED Color.RED Globals? locals should be possible too. At least in Cpython, updating locals() does not work in functions. Or even something like: with Color: BLUE RED Although the extra indentation could also be annoying. One wouldn't want the module defining Color to automatically 'export' the colors: but rather a way to request an 'export' them into a particular scope. That way the proliferation of names into scopes is chosen by the programmer. import module_containing_color module_containing_color.Color.export_enumerations( globals ) or import module_containing_color module_containing_color.Color.export_enumerations( locals ) Or maybe locals is implicit, and in the file scope of a module, locals are globals anyway, so doing module_containing_color.Color.export_enumerations() locals() can't be implicit, at least not without deep black magic of inspecting frames in the call stack -- which is hardly portable. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Fri, Apr 26, 2013 at 12:38 PM, Guido van Rossum gu...@python.org wrote: If the above syntax won't work, that isinstance() outcome isn't really important. :-( Can't we do some kind of callable check? There may be some weird decorators that won't work, but they aren't likely to be useful in this context. Yeah, it may not be as tricky as I feared: adding not callable(attr_val) to the conditions for deciding whether or not to convert a class attribute to an instance of the enum would likely suffice to address the method problem. You couldn't create an enum of callables, but that would be a seriously weird thing to do anyway Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 4/25/2013 7:25 PM, Ethan Furman wrote: On 04/25/2013 07:09 PM, Glenn Linderman wrote: On 4/25/2013 4:53 PM, Ethan Furman wrote: On 04/25/2013 04:26 PM, Glenn Linderman wrote: My question is, once an enumeration is defined, is there a way, short of element-by-element assignment, to import the individual enumeration instances into the current namespace, so that I can say red instead of Color.red ? I understand the benefits of avoiding name collisions when there are lots of enumerations, and lots of opportunities for name collections between, say, RGBColor and CYMKColor... but there are lots of uses for enumerations where the subsidiary namespace is just aggravating noise. You mean something like: -- class Color(Enum): ... RED = 1 ... GREEN = 2 ... BLUE = 3 -- Color.register() # puts Color in sys.modules -- from Color import * # doesn't work in a function, though :( -- BLUE Color.BLUE Something like that, but that works in a function too :) Not in Py3 it doesn't: Parse error. Something like that, but something like that that works in a function too :) is what I meant. I understand that the feature you demonstrated doesn't work in Py3... that's why we need something like that rather than that :) Python 3.2.3 (default, Oct 19 2012, 19:53:16) [GCC 4.7.2] on linux2 Type help, copyright, credits or license for more information. -- def test(): ... from sys import * ... print('huh') ... File stdin, line 1 SyntaxError: import * only allowed at module level Yeah, that would be nice. ;) A bit dangerous, though -- what if another module does the same thing, but its Color is different? Better would be: -- Color.export(globals()) # put the enumerators in globals -- RED Color.RED Globals? locals should be possible too. At least in Cpython, updating locals() does not work in functions. Or even something like: with Color: BLUE RED Although the extra indentation could also be annoying. One wouldn't want the module defining Color to automatically 'export' the colors: but rather a way to request an 'export' them into a particular scope. That way the proliferation of names into scopes is chosen by the programmer. import module_containing_color module_containing_color.Color.export_enumerations( globals ) or import module_containing_color module_containing_color.Color.export_enumerations( locals ) Or maybe locals is implicit, and in the file scope of a module, locals are globals anyway, so doing module_containing_color.Color.export_enumerations() locals() can't be implicit, at least not without deep black magic of inspecting frames in the call stack -- which is hardly portable. So what I'm hearing is that enumerations need to be a language feature, rather than a module: Can't combine Enum and EnumItem Can't import into locals The compiler could do those things, though. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 26/04/2013 2:38 p.m., Guido van Rossum wrote: Can't we do some kind of callable check? There may be some weird decorators that won't work, but they aren't likely to be useful in this context. Another possible solution: class Color: red = 1 white = 2 blue = 3 orange = 4 class __methods__: def wave(self, n=1): for _ in range(n): print('Waving', self) and have the metaclass pull the functions out of the __methods__ sub-object. -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 26/04/2013 1:28 p.m., Ethan Furman wrote: Interesting idea, but why does Day(3) have to be disallowed to make it work? Because it's ambiguous. Which day of the week is number 3? It depends on where you start. I should perhaps point out that the numbers assigned to the values initially are just to establish the relative ordering. They wouldn't be directly accessible once the values are created. To get an integer value corresponding to a Day value, you would have to do arithmetic: Day.wednesday - Day.sunday -- 3 -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 26/04/2013 3:06 p.m., Glenn Linderman wrote: So what I'm hearing is that enumerations need to be a language feature, rather than a module: Can't combine Enum and EnumItem Can't import into locals The compiler could do those things, though. Maybe we've found a use case for the recently advertised macro system? (One, two, five... runs for cover...) -- Greg ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 4/25/2013 8:22 PM, Greg wrote: On 26/04/2013 3:12 p.m., Glenn Linderman wrote: On 4/25/2013 7:49 PM, Nick Coghlan wrote: You couldn't create an enum of callables, but that would be a seriously weird thing to do anyway But aren't all classes callable? An enum of classes would be seriously weird as well, I think. Perhaps so, but an enumeration of objects whose class defines __call__ would not be so weird. Does your __methods__ cure this problem? It looked interesting to me, but I'm not familiar enough with metaclass to be sure of anything about it :) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Thu, Apr 25, 2013 at 8:39 PM, Glenn Linderman v+pyt...@g.nevcal.com wrote: an enumeration of objects whose class defines __call__ would not be so weird. Seriously? You'd complexificate the basic usage in order to cater for such an esoteric use case? The *only* use cases that matter at all for enum values are ints and strings, and even the latter could be considered a luxury when compared to other languages' enums. -- --Guido van Rossum (python.org/~guido) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On Fri, Apr 26, 2013 at 3:01 PM, Steven D'Aprano st...@pearwood.info wrote: On 26/04/13 13:22, Greg wrote: On 26/04/2013 3:12 p.m., Glenn Linderman wrote: On 4/25/2013 7:49 PM, Nick Coghlan wrote: You couldn't create an enum of callables, but that would be a seriously weird thing to do anyway But aren't all classes callable? An enum of classes would be seriously weird as well, I think. I don't think iscallable will work, since that descriptors like staticmethod and classmethod aren't callable. Nor are properties. My point was there *are* broad categories that we can reasonably say you can't use these as values in an enumeration. Callables are one, descriptors are probably another. Alternatively, we can flip it around and require that each enum definition nominate an expected value type (defaulting to int) and only convert class attributes that are instances of that type to instances of the enum class. Either can be made to work, so it's really Guido's call as to which he would prefer. As Barry noted, the next step is actually for someone to create a proof of concept that shows the merge is possible in practice, not just theory. Cheers, Nick. -- Nick Coghlan | ncogh...@gmail.com | Brisbane, Australia ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 07:13 PM, Nick Coghlan wrote: On Fri, Apr 26, 2013 at 8:29 AM, Barry Warsaw ba...@python.org wrote: On Apr 25, 2013, at 03:19 PM, Guido van Rossum wrote: Clearly this is a trick question. :-) A bit, yes. :) I was told when this was brought up previously (a week ago?) that it would be simple to make it truly the same class. It didn't sound simple to me, but I haven't seen any actual code yet. I'm the one who said I didn't see any obvious barriers to the merger, but I've realised there is one, and it's similar to one namedtuple struggles with: how to handle method definitions. [snip] With a merged design, it becomes *really* hard to give the instances custom behaviour, because the metaclass will somehow have to differentiate between namespace entries that are intended to be callables, and those which are intended to be instances of the enum. This is not an easy problem to solve. I'm probably going to regret asking this, but what's difficult with the following? 8- class EnumDict(dict): automatically assigns the next _int for an enum def __init__(yo): super().__init__() yo._allow_duplicates = False yo._value = 1 yo._base = 1 yo._enums = [] yo._type = None # object means enum, anything else means all must be of that type def __setitem__(yo, key, new_value): main purpose is to support auto-numbering of members existing = yo.get(key) if type(existing) is attrs: # attrs is a helper class raise TypeError('Attempted to reuse key: %s' % key) if not key[:2] == key[-2:] == '__': old_value = None if isinstance(new_value, attrs): old_value = new_value if new_value.integer is None: new_value = yo._value else: new_value = new_value.integer if not isinstance(new_value, int): raise TypeError( an enum integer must be an instance of type int, not %s % type(new_value) ) if not callable(new_value): # this if-else is probably not final if (isinstance(new_value, int) and old_value is not None or yo._type in (object, )): yo._check_duplicate_integer(new_value, key) yo._value = new_value yo._inc_integer() yo._enums.append(key) new_value = attrs(integer=new_value) elif yo._type is None: # random bunch of named constants yo._check_duplicate_integer(new_value, key) value = yo._value yo._inc_integer() yo._enums.append(key) new_value = attrs(value=new_value, integer=value) elif isinstance(new_value, yo._type): # single type of named constants if isinstance(yo._type, int): value = new_value else: value = yo._value yo._check_duplicate_integer(value, key) yo._inc_integer() yo._enums.append(key) new_value = attrs(value=new_value, integer=value) if old_value is not None: new_value, old_value.integer = old_value, new_value.integer dict.__setitem__(yo, key, new_value) def _inc_integer(yo): if yo._base == 1: yo._value += 1 else: if yo._value == 0: value = 1 else: value = floor(log(yo._value, 2)) value = 2 ** value value = 1 yo._value = value def _check_duplicate_integer(yo, new_value, key): for name, value in yo.items(): if not isinstance(value, attrs): continue if value.integer == new_value and name != key and not yo._allow_duplicates: raise TypeError('duplicate value for %s: %d' % (key, value)) 8--- Basically, if the assigned value is not `attrs` or a literal of the same type as the enum, the metaclass ignores it. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 08:14 PM, Greg wrote: On 26/04/2013 1:28 p.m., Ethan Furman wrote: Interesting idea, but why does Day(3) have to be disallowed to make it work? Because it's ambiguous. Which day of the week is number 3? It depends on where you start. Ah. I should perhaps point out that the numbers assigned to the values initially are just to establish the relative ordering. They wouldn't be directly accessible once the values are created. To get an integer value corresponding to a Day value, you would have to do arithmetic: Day.wednesday - Day.sunday -- 3 That would make it very hard to do data storage and retrieval. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 435 -- Adding an Enum type to the Python standard library
On 04/25/2013 10:01 PM, Steven D'Aprano wrote: On 26/04/13 13:22, Greg wrote: On 26/04/2013 3:12 p.m., Glenn Linderman wrote: On 4/25/2013 7:49 PM, Nick Coghlan wrote: You couldn't create an enum of callables, but that would be a seriously weird thing to do anyway But aren't all classes callable? An enum of classes would be seriously weird as well, I think. I don't think iscallable will work, since that descriptors like staticmethod and classmethod aren't callable. Nor are properties. I think a solution may be an explicit decorator that tells the metaclass not to skip the object into an enum value: Another option is to check if the item is a descriptor (class, static, property, or other); yet another option is to check if the item is the type of the enum class (int for IntEnum, str for StrEnum, etc.). The code I posted earlier checks for callable and type -- checking for descriptor also would not be much more effort. -- ~Ethan~ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com