Re: [Python-Dev] Why can't I encode/decode base64 without importing a module?

2013-04-25 Thread Lennart Regebro
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

2013-04-25 Thread Georg Brandl
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?

2013-04-25 Thread Stephen J. Turnbull
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?

2013-04-25 Thread Lennart Regebro
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?

2013-04-25 Thread Nick Coghlan
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?

2013-04-25 Thread Antoine Pitrou
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

2013-04-25 Thread Antoine Pitrou
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?

2013-04-25 Thread Lennart Regebro
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?

2013-04-25 Thread Xavier Morel
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

2013-04-25 Thread Eli Bendersky
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

2013-04-25 Thread Antoine Pitrou
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?

2013-04-25 Thread Antoine Pitrou
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?

2013-04-25 Thread Antoine Pitrou
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

2013-04-25 Thread Eli Bendersky
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?

2013-04-25 Thread Lennart Regebro
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?

2013-04-25 Thread Tres Seaver
-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?

2013-04-25 Thread Barry Warsaw
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?

2013-04-25 Thread MRAB

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?

2013-04-25 Thread Daniel Holth
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?

2013-04-25 Thread Lennart Regebro
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?

2013-04-25 Thread Antoine Pitrou
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?

2013-04-25 Thread Antoine Pitrou
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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Guido van Rossum
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

2013-04-25 Thread Eli Bendersky
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

2013-04-25 Thread Eli Bendersky
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?

2013-04-25 Thread MRAB

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

2013-04-25 Thread Ethan Furman

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?

2013-04-25 Thread Lennart Regebro
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?

2013-04-25 Thread Stephen J. Turnbull
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?

2013-04-25 Thread Isaac Morland

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

2013-04-25 Thread Barry Warsaw
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?

2013-04-25 Thread Stephen J. Turnbull
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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Tres Seaver
-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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Barry Warsaw
-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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Eli Bendersky
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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Guido van Rossum
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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Guido van Rossum
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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Guido van Rossum
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

2013-04-25 Thread R. David Murray
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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Glenn Linderman

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

2013-04-25 Thread Ethan Furman

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-04-25 Thread Benjamin Peterson
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

2013-04-25 Thread MRAB

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

2013-04-25 Thread Glenn Linderman

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

2013-04-25 Thread Steven D'Aprano

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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Greg Ewing

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

2013-04-25 Thread MRAB

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

2013-04-25 Thread Greg Ewing

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

2013-04-25 Thread MRAB

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

2013-04-25 Thread Greg Ewing

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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Barry Warsaw
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

2013-04-25 Thread Glenn Linderman

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

2013-04-25 Thread Nick Coghlan
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

2013-04-25 Thread Devin Jeanpierre
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

2013-04-25 Thread Guido van Rossum
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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Nick Coghlan
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

2013-04-25 Thread Glenn Linderman

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

2013-04-25 Thread Greg

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

2013-04-25 Thread Greg

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

2013-04-25 Thread Greg

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

2013-04-25 Thread Glenn Linderman

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

2013-04-25 Thread Guido van Rossum
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

2013-04-25 Thread Nick Coghlan
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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Ethan Furman

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

2013-04-25 Thread Ethan Furman

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