Re: [Python-Dev] constant/enum type in stdlib

2010-11-29 Thread Greg Ewing

Rob Cliffe wrote:

But when a frozen list a.k.a. tuple would be created - either directly, 
or by setting a list's mutable flag to False which would really turn it 
into a tuple - the size *would* be known.


But at that point the object consists of two memory blocks -- one
containing just the object header and a pointer to the items, and
the other containing the items.

To turn that into a true tuple structure would require resizing
the main object block to be big enough to hold the items and
copying them into it. The main object can't be moved (because
there are PyObject *s all over the place pointing to it), so
if there's not enough room at its current location, you're out
of luck.

So lists frozen after creation would have to remain as two blocks,
making them second-class citizens compared to those that were
created frozen. Either that or store all lists/tuples as two
blocks, and give up some of the performance advantages of the
current tuple structure.

--
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] constant/enum type in stdlib

2010-11-29 Thread Greg Ewing

I don't see how the grouping can be completely separated
from the value-naming. If the named values are to be
subclassed from the base values, then you want all the
members of a group to belong to the *same* subclass.
You can't get that by treating each named value on its
own and then trying to group them together afterwards.

--
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] constant/enum type in stdlib

2010-11-29 Thread Ron Adam



On 11/28/2010 09:03 PM, Ron Adam wrote:


It does associate additional info to names and creates a nice dictionary to
reference.


  def name_values( FOO: 1,
BAR: Hello World!,
BAZ: dict(a=1, b=2, c=3) ):
... return FOO, BAR, BAZ
...
  foo(1,2,3)
(1, 2, 3)
  foo.__annotations__
{'BAR': 'Hello World!', 'FOO': 1, 'BAZ': {'a': 1, 'c': 3, 'b': 2}}


sigh... I havn't been very focused lately. That should have been:

 def named_values(FOO:1, BAR:Hello World!, BAZ:dict(a=1, b=2, c=3)):
...   return FOO, BAR, BAZ
...
 named_values.__annotations__
{'BAR': 'Hello World!', 'FOO': 1, 'BAZ': {'a': 1, 'c': 3, 'b': 2}}
 named_values(1, 2, 3)
(1, 2, 3)

Cheers,
   Ron

___
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] constant/enum type in stdlib

2010-11-29 Thread Nick Coghlan
On Tue, Nov 30, 2010 at 7:36 AM, Greg Ewing greg.ew...@canterbury.ac.nz wrote:
 I don't see how the grouping can be completely separated
 from the value-naming. If the named values are to be
 subclassed from the base values, then you want all the
 members of a group to belong to the *same* subclass.
 You can't get that by treating each named value on its
 own and then trying to group them together afterwards.

Note that my sample implementation cached the created types, so that
(for example) there was only ever one Namedint type (my
implementation wasn't quite kosher in that respect, since
functools.lru_cache has a non-optional size limit - setting maxsize to
float('inf') deals with that). A grouping API would use either single
or multiple inheritance to create members that supported both the
naming aspects as well as the grouping aspects.

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] constant/enum type in stdlib

2010-11-28 Thread Michael Foord

On 28/11/2010 03:20, Terry Reedy wrote:

On 11/27/2010 6:26 PM, Raymond Hettinger wrote:


Can I suggest that an enum-maker be offered as a third-party module


Possibly with competing versions for trial and testing ;-)


rather than prematurely adding it into the standard library.


I had same thought.



There are already *several* enum packages for Python available. The 
implementation by Ben Finney, associated with the previous PEP, is on 
PyPI and the most recent release has over 4000 downloads making it 
reasonably popular:


http://pypi.python.org/pypi/enum/

Other contenders include flufl.enum and lazr.enum. The Twisted guys 
would like a named constant type, and have a ticket for it, and PyQt has 
its own implementation (subclassing int) providing this functionality. 
In terms of assessing *general* usefulness in the wider community that 
step has already been done.


This discussion came out of yet-another-set-of-integer-constants being 
added to the Python standard library (since changed to strings). We have 
integer constants, with the associated inscrutability when used from the 
interactive interpreter or debugging, in *many* standard library 
modules. The particular features and use cases being discussed have use 
*within* the standard library in mind.


Releasing yet-another-enum-library-that-the-standard-library-can't-use 
would be a particularly pointless outcome of this discussion. The 
decision is whether or not to use named constants in the standard 
library, otherwise we can just point people at one of the several 
existing packages.


All the best,

Michael Foord

--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-28 Thread Michael Foord

On 28/11/2010 02:38, Nick Coghlan wrote:

On Sun, Nov 28, 2010 at 9:26 AM, Raymond Hettinger
raymond.hettin...@gmail.com  wrote:

On Nov 27, 2010, at 12:56 PM, Glenn Linderman wrote:


On 11/27/2010 2:51 AM, Nick Coghlan wrote:

Not quite. I'm suggesting a factory function that works for any value,
and derives the parent class from the type of the supplied value.

Nick, thanks for the much better implementation than I achieved; you seem to 
have the same goals as my implementation.  I learned a bit making mine, and 
more understanding yours to some degree.  What I still don't understand about 
your implementation, is that when adding one additional line to your file, it 
fails:

w = named_value(ABC, z )

Now I can understand why it might not be a good thing to make a named value of 
a named value (confusing, at least), but I was surprised, and still do not 
understand, that it failed reporting the __new__() takes exactly 3 arguments (2 
given).

Can I suggest that an enum-maker be offered as a third-party module rather than 
prematurely adding it into the standard library.

Indeed. Glenn's failing example suggests to me that using a new
metaclass is probably going to be a cleaner option than trying to
dance around type's default behaviour within an ordinary class
definition (if nothing else, a separate metaclass makes it much easier
to detect when you're dealing with an instance of a named type).



Yep, for representing a group of names a single class with a metaclass 
seems like a reasonable approach. See my note below about agreeing 
minimal feature-set and minimal-api before we discuss implementation 
though.



Regardless, I still see value in approaching this whole discussion as
a two-level design problem, with named values as the more
fundamental concept, and then higher level grouping APIs to get
enum-style behaviour.


It seems like using the term enum provokes a strong negative reaction 
in some of the core-devs who are basically in favour named constants and 
not actively against grouping. I'm happy with NamedConstant and 
GroupedNames (or similar) and dropping the use of the term enum.


There are also valid concerns about over-engineering (and not so valid 
concerns...). Simplicity in creating them and no additional burden in 
using them are fundamental, but in the APIs / implementations suggested 
so far I think we are keeping that in mind.



Eventually attaining One Obvious Way for the
former seems achievable to me, while the diversity of use cases for
grouping APIs suggests to me that one-size-fits-all isn't going to
work unless that one size is a Frankenstein API with more options
than anyone could reasonably hope to keep in their head at once.


Well... yes - treating it as a two level design problem is fine.

I don't think there are *many* competing features, in fact as far as 
feature requests on python-dev go I think this is a relatively 
straightforward one with a lot of *agreement* on the basic functionality.


We have had various discussions about what the API should look like, or 
what the implementation should look like, but I don't think there is a 
lot of disagreement about basic features. There are some 'optional 
features'. Many of these can be added later without backwards 
compatibility issues, so those can profitably be omitted from an initial 
implementation.


Features as I see them:

Named constant
--

* Nice repr
* Subclass of the type it represents
* Trivially easy to convert either to a string (name) and the value it 
represents
* If an integer type, can be OR'd with other named constants and retains 
a useful repr



Grouped constants

* Easy to create a group of named constants, accessible as attributes on 
group object

* Capability to go from name or value to corresponding constants


Optional Features
---

* Ability to dynamically add new named values to a group. (Suggested by 
Guido)

* Ability to test if a name or value is in a group
* Ability to list all names in a group
* ANDing as well as ORing
* Constants are unique
* OR'ing with an integer will look up the name (or calculate it if the 
int itself represents flags that have already been OR'd) and return a 
named value (with useful repr) instead of just an integer
* Named constants be named values that can wrap *any* type and not just 
immutable values. (Note that wrapping mutable types makes providing 
from_value functionality harder *unless* we guarantee that named 
values are unique. If they aren't unique named values for a mutable type 
can have different values and there is no single definition of what the 
named value actually is.)
Requiring that values only have one name - or alternatively that values 
on a group could have multiple names (obviously incompatible features).

* Requiring all names in a group to be of the same type
* Allow names to be set automatically in a namespace, for example in a 
class namespace or on a module

* Allow subclassing and 

Re: [Python-Dev] constant/enum type in stdlib

2010-11-28 Thread Michael Foord

On 28/11/2010 16:28, Michael Foord wrote:

[snip...]
I don't think there are *many* competing features, in fact as far as 
feature requests on python-dev go I think this is a relatively 
straightforward one with a lot of *agreement* on the basic functionality.


We have had various discussions about what the API should look like, 
or what the implementation should look like, but I don't think there 
is a lot of disagreement about basic features. There are some 
'optional features'. Many of these can be added later without 
backwards compatibility issues, so those can profitably be omitted 
from an initial implementation.


Features as I see them:

Named constant
--

* Nice repr
* Subclass of the type it represents
* Trivially easy to convert either to a string (name) and the value it 
represents
* If an integer type, can be OR'd with other named constants and 
retains a useful repr


Note that having an OR repr is meaningless *unless* the constants are 
intended to be flags, OR'ing should be specified.


name = NamedValue('name', value, flags=True)

Where flags defaults to False. Typically you will use this through the 
grouping API anyway - where it can either be a keyword argument 
(slightly annoying because the suggestion is to create the named values 
through keyword arguments) or we can have two group-factory functions:


Group = make_constants('Group', name1=value1, name2=value2)
Flags = make_flags('Flags', name1=value1, name2=value2)

It is sensible if flag values are only powers of 2; we could enforce 
that or not... (Another one for the optional feature list.)


I forgot auto-enumeration (specifying names only and having values 
autogenerated) from the optional feature set by the way. I think Antoine 
strongly disapproves of this feature because it reminds him of C enums.


Mark Dickinson thinks that the flags feature could be an optional 
feature too. If we have ORing it makes sense to have ANDing, so I guess 
they belong together. I think there is value in it though.


I realise that the optional feature list is now not small, and 
implementing all of it would create the franken-api Nick is worried 
about. The minimal feature list is nicely small though and provides 
useful functionality.


All the best,

Michael



Grouped constants

* Easy to create a group of named constants, accessible as attributes 
on group object

* Capability to go from name or value to corresponding constants


Optional Features
---

* Ability to dynamically add new named values to a group. (Suggested 
by Guido)

* Ability to test if a name or value is in a group
* Ability to list all names in a group
* ANDing as well as ORing
* Constants are unique
* OR'ing with an integer will look up the name (or calculate it if the 
int itself represents flags that have already been OR'd) and return a 
named value (with useful repr) instead of just an integer
* Named constants be named values that can wrap *any* type and not 
just immutable values. (Note that wrapping mutable types makes 
providing from_value functionality harder *unless* we guarantee that 
named values are unique. If they aren't unique named values for a 
mutable type can have different values and there is no single 
definition of what the named value actually is.)
Requiring that values only have one name - or alternatively that 
values on a group could have multiple names (obviously incompatible 
features).

* Requiring all names in a group to be of the same type
* Allow names to be set automatically in a namespace, for example in a 
class namespace or on a module

* Allow subclassing and adding of new values only present in subclass


I'd rather we agree a suitable (minimal) API and feature set and go to 
implementation from that.


For wrapping mutable types I'm tempted to say YAGNI. For the standard 
library wrapping integers meets almost all our use-cases except for 
one float. (At work we have a decimal constant as it happens.) Perhaps 
we could require immutable types for groups but allow arbitrary values 
for individual named values?


For the named values api:

name = NamedValue('name', value)

For the grouping (tentatively accepted as reasonable by Antoine):

Group = make_constants('Group', name1=value1, name2=value2)
name1, name2 = Group.name1, Group.name1
flag = name1 | name2

value = int(Group.name1)
name = Group('name1')
# alternatively: value = Group.from_name('name1')
name = Group.from_value(value1)
# Group(value1) could work only if values aren't strings
# perhaps: name = Group(value=value1)

Group.new_name = value3 # create new value on the group
names = Group.all_names()
# further bikeshedding on spelling of all_names required
# correspondingly 'all_values' I guess, returning the constants 
themselves


Some of the optional features couldn't later be added without 
backwards compatibility concerns (I think the type checking features 
and requiring unique values for example). We should at least 

Re: [Python-Dev] constant/enum type in stdlib

2010-11-28 Thread Michael Foord

On 28/11/2010 17:05, Michael Foord wrote:

[snip...]
It is sensible if flag values are only powers of 2; we could enforce 
that or not... (Another one for the optional feature list.)


Another 'optional' feature I omitted was Phillip J. Eby's suggestion / 
requirement that named values be pickleable. Email is clunky for 
handling this, is there enough support (there is still some objection 
that is sure) to revive the PEP or create a new one?


I also didn't include Nick's suggested API, which is slightly different 
from the one I suggested:


silly = Namegroup.from_names(Silly, FOO, BAR, BAZ)
 silly.FOO
Silly.FOO=0
 int(silly.FOO)
0
 silly(0)
Silly.FOO=0

x = named_value(FOO, 1)
y = named_value(BAR, Hello World!)
z = named_value(BAZ, dict(a=1, b=2, c=3))

set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw())

Where a named value created from an integer is an int subclass, from a 
dict a dict subclass and so on.


Michael



I forgot auto-enumeration (specifying names only and having values 
autogenerated) from the optional feature set by the way. I think 
Antoine strongly disapproves of this feature because it reminds him of 
C enums.


Mark Dickinson thinks that the flags feature could be an optional 
feature too. If we have ORing it makes sense to have ANDing, so I 
guess they belong together. I think there is value in it though.


I realise that the optional feature list is now not small, and 
implementing all of it would create the franken-api Nick is worried 
about. The minimal feature list is nicely small though and provides 
useful functionality.


All the best,

Michael



Grouped constants

* Easy to create a group of named constants, accessible as attributes 
on group object

* Capability to go from name or value to corresponding constants


Optional Features
---

* Ability to dynamically add new named values to a group. (Suggested 
by Guido)

* Ability to test if a name or value is in a group
* Ability to list all names in a group
* ANDing as well as ORing
* Constants are unique
* OR'ing with an integer will look up the name (or calculate it if 
the int itself represents flags that have already been OR'd) and 
return a named value (with useful repr) instead of just an integer
* Named constants be named values that can wrap *any* type and not 
just immutable values. (Note that wrapping mutable types makes 
providing from_value functionality harder *unless* we guarantee 
that named values are unique. If they aren't unique named values for 
a mutable type can have different values and there is no single 
definition of what the named value actually is.)
Requiring that values only have one name - or alternatively that 
values on a group could have multiple names (obviously incompatible 
features).

* Requiring all names in a group to be of the same type
* Allow names to be set automatically in a namespace, for example in 
a class namespace or on a module

* Allow subclassing and adding of new values only present in subclass


I'd rather we agree a suitable (minimal) API and feature set and go 
to implementation from that.


For wrapping mutable types I'm tempted to say YAGNI. For the standard 
library wrapping integers meets almost all our use-cases except for 
one float. (At work we have a decimal constant as it happens.) 
Perhaps we could require immutable types for groups but allow 
arbitrary values for individual named values?


For the named values api:

name = NamedValue('name', value)

For the grouping (tentatively accepted as reasonable by Antoine):

Group = make_constants('Group', name1=value1, name2=value2)
name1, name2 = Group.name1, Group.name1
flag = name1 | name2

value = int(Group.name1)
name = Group('name1')
# alternatively: value = Group.from_name('name1')
name = Group.from_value(value1)
# Group(value1) could work only if values aren't strings
# perhaps: name = Group(value=value1)

Group.new_name = value3 # create new value on the group
names = Group.all_names()
# further bikeshedding on spelling of all_names required
# correspondingly 'all_values' I guess, returning the constants 
themselves


Some of the optional features couldn't later be added without 
backwards compatibility concerns (I think the type checking features 
and requiring unique values for example). We should at least consider 
these if we are to make adding them later difficult. I would be fine 
with not having these features.


All the best,

Michael


Cheers,
Nick.










--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without 

Re: [Python-Dev] constant/enum type in stdlib

2010-11-28 Thread Steven D'Aprano

Michael Foord wrote:

Another 'optional' feature I omitted was Phillip J. Eby's suggestion / 
requirement that named values be pickleable. Email is clunky for 
handling this, is there enough support (there is still some objection 
that is sure) to revive the PEP or create a new one?


I think it definitely needs a PEP. I don't care whether you revive the 
old PEP or write a new one.




--
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] constant/enum type in stdlib

2010-11-28 Thread Michael Foord

On 28/11/2010 18:05, Steven D'Aprano wrote:

Michael Foord wrote:

Another 'optional' feature I omitted was Phillip J. Eby's suggestion 
/ requirement that named values be pickleable. Email is clunky for 
handling this, is there enough support (there is still some objection 
that is sure) to revive the PEP or create a new one?


I think it definitely needs a PEP. I don't care whether you revive the 
old PEP or write a new one.


Well, if it were to be accepted it would need a PEP and the next step 
should be a PEP are slightly different statements. :-)


As I agree with the former *anyway* at the worst starting a PEP will 
waste time, so I guess I'll get that underway when I get a chance...


Thanks

Michael

--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-28 Thread Greg Ewing

Rob Cliffe wrote:

But couldn't they be presented to the Python programmer as a single 
type, with the implementation details hidden under the hood?


Not in CPython, because tuple items are kept in the same block
of memory as the object header. Because CPython can't move
objects, this means that the size of the tuple must be known
when the object is created.

--
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] constant/enum type in stdlib

2010-11-28 Thread Nick Coghlan
On Mon, Nov 29, 2010 at 2:28 AM, Michael Foord
fuzzy...@voidspace.org.uk wrote:
 For wrapping mutable types I'm tempted to say YAGNI. For the standard
 library wrapping integers meets almost all our use-cases except for one
 float. (At work we have a decimal constant as it happens.) Perhaps we could
 require immutable types for groups but allow arbitrary values for individual
 named values?

Whereas my opinion is that immutable vs mutable is such a blurry
distinction that we shouldn't try to make it at the lowest level.
Would it be possible to name frozenset instances? Tuples? How about
objects that are conceptually immutable, but don't close all the
loopholes allowing you to mutate them? (e.g. Decimal, Fraction)

Better to design a named value API that doesn't care about mutability,
and then leave questions of reverse mappings from values back to names
to the grouping API level. At that level, it would be trivial (and
natural) to limit names to referencing Hashable values so that a
reverse lookup table would be easy to implement. For standard library
purposes, we could even reasonably provide an int-only grouping API,
since the main use case is almost certainly to be in managing
translation of OS-level integer constants to named values.

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] constant/enum type in stdlib

2010-11-28 Thread Michael Foord

On 29/11/2010 00:48, Nick Coghlan wrote:

On Mon, Nov 29, 2010 at 2:28 AM, Michael Foord
fuzzy...@voidspace.org.uk  wrote:

For wrapping mutable types I'm tempted to say YAGNI. For the standard
library wrapping integers meets almost all our use-cases except for one
float. (At work we have a decimal constant as it happens.) Perhaps we could
require immutable types for groups but allow arbitrary values for individual
named values?

Whereas my opinion is that immutable vs mutable is such a blurry
distinction that we shouldn't try to make it at the lowest level.
Would it be possible to name frozenset instances? Tuples? How about
objects that are conceptually immutable, but don't close all the
loopholes allowing you to mutate them? (e.g. Decimal, Fraction)

Better to design a named value API that doesn't care about mutability,
and then leave questions of reverse mappings from values back to names
to the grouping API level. At that level, it would be trivial (and
natural) to limit names to referencing Hashable values so that a
reverse lookup table would be easy to implement. For standard library
purposes, we could even reasonably provide an int-only grouping API,
since the main use case is almost certainly to be in managing
translation of OS-level integer constants to named values.


Sounds reasonable to me.

Michael


Cheers,
Nick.




--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-28 Thread Rob Cliffe



On 28/11/2010 21:23, Greg Ewing wrote:

Rob Cliffe wrote:

But couldn't they be presented to the Python programmer as a single 
type, with the implementation details hidden under the hood?


Not in CPython, because tuple items are kept in the same block
of memory as the object header. Because CPython can't move
objects, this means that the size of the tuple must be known
when the object is created.

But when a frozen list a.k.a. tuple would be created - either directly, 
or by setting a list's mutable flag to False which would really turn it 
into a tuple - the size *would* be known.  And since the object would 
now be immutable, there would be no requirement for its size to change.  
(My idea doesn't require additional functionality, just a different API.)

Rob Cliffe
___
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] constant/enum type in stdlib

2010-11-28 Thread Ron Adam



On 11/27/2010 04:51 AM, Nick Coghlan wrote:

x = named_value(FOO, 1)
y = named_value(BAR, Hello World!)
z = named_value(BAZ, dict(a=1, b=2, c=3))

print(x, y, z, sep=\n)
print(\n.join(map(repr, (x, y, z
print(\n.join(map(str, map(type, (x, y, z)

set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw())
print(\n.join(map(repr, (foo, bar, baz
print(type(x) is type(foo), type(y) is type(bar), type(z) is type(baz))

==

# Session output for the last 6 lines

  print(x, y, z, sep=\n)

1
Hello World!
{'a': 1, 'c': 3, 'b': 2}


  print(\n.join(map(repr, (x, y, z

FOO=1
BAR='Hello World!'
BAZ={'a': 1, 'c': 3, 'b': 2}


This reminds me of python annotations.  Which seem like an already 
forgotten new feature.  Maybe they can help with this?



It does associate additional info to names and creates a nice dictionary to 
reference.



 def name_values( FOO: 1,
 BAR: Hello World!,
 BAZ: dict(a=1, b=2, c=3) ):
...   return FOO, BAR, BAZ
...
 foo(1,2,3)
(1, 2, 3)
 foo.__annotations__
{'BAR': 'Hello World!', 'FOO': 1, 'BAZ': {'a': 1, 'c': 3, 'b': 2}}


Cheers,
  Ron










___
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] constant/enum type in stdlib

2010-11-27 Thread Nick Coghlan
On Thu, Nov 25, 2010 at 3:41 AM, Michael Foord
fuzzy...@voidspace.org.uk wrote:
 Can you explain what you see as the difference?

 I'm not particularly interested in type validation but I like the fact that
 typical enum APIs allow you to group constants: the generated constant class
 acts as a namespace for all the defined constants.

The problem with blessing one particular enum API is that people
have so many different ideas as to what an enum API should look like.

However, the one thing they all have in common is the ability to take
a value and give it a name, then present *both* of those in debugging
information.

 Are you just suggesting something along the lines of:

 class NamedConstant(int):
 def __new__(cls, name, val):
 return int.__new__(cls, val)

 def __init__(self, name, val):
 self._name = name

 def __repr__(self):
 return 'NamedConstant %s' % self._name

 FOO = NamedConstant('FOO', 3)

 In general the less features the better, but I'd like a few more features
 than that. :-)

Not quite. I'm suggesting a factory function that works for any value,
and derives the parent class from the type of the supplied value.
However, what you wrote is still the essence of the idea - we would be
primarily providing a building block that makes it easier for people
to *create* enum APIs if they want to, but for simple use cases (where
all they really wanted was the enhanced debugging information) they
wouldn't need to bother. In the standard library, wherever we do
enum-like things we would switch to using named values where it
makes sense to do so.

Doing so may actually make sense for more than just constants - it may
make sense for significant mutable globals as well.

==
# Implementation (more than just a sketch, since it handles some
interesting corner cases)
import functools
@functools.lru_cache()
def _make_named_value_type(base_type):
class _NamedValueType(base_type):
def __new__(cls, name, value):
return base_type.__new__(cls, value)
def __init__(self, name, value):
self.__name = name
super().__init__(value)
@property
def _name(self):
return self.__name
def _raw(self):
return base_type(self)
def __repr__(self):
return {}={}.format(self._name, super().__repr__())
if base_type.__str__ is object.__str__:
__str__ = base_type.__repr__
_NamedValueType.__name__ = Named{}.format(base_type.__name__)
return _NamedValueType

def named_value(name, value):
return _make_named_value_type(type(value))(name, value)

def set_named_values(namespace, **kwds):
for k, v in kwds.items():
namespace[k] = named_value(k, v)

x = named_value(FOO, 1)
y = named_value(BAR, Hello World!)
z = named_value(BAZ, dict(a=1, b=2, c=3))

print(x, y, z, sep=\n)
print(\n.join(map(repr, (x, y, z
print(\n.join(map(str, map(type, (x, y, z)

set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw())
print(\n.join(map(repr, (foo, bar, baz
print(type(x) is type(foo), type(y) is type(bar), type(z) is type(baz))

==

# Session output for the last 6 lines
 print(x, y, z, sep=\n)
1
Hello World!
{'a': 1, 'c': 3, 'b': 2}

 print(\n.join(map(repr, (x, y, z
FOO=1
BAR='Hello World!'
BAZ={'a': 1, 'c': 3, 'b': 2}

 print(\n.join(map(str, map(type, (x, y, z)
class '__main__.Namedint'
class '__main__.Namedstr'
class '__main__.Nameddict'

 set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw())
 print(\n.join(map(repr, (foo, bar, baz
foo=1
bar='Hello World!'
baz={'a': 1, 'c': 3, 'b': 2}

 print(type(x) is type(foo), type(y) is type(bar), type(z) is type(baz))
True True True

For normal use, such objects would look like ordinary instances of
their class. They would only behave differently when their
representation is printed (prepending their name), or when their type
is interrogated (being an instance of the named subclass rather than
the ordinary type).

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] constant/enum type in stdlib

2010-11-27 Thread Michael Foord

On 27/11/2010 10:51, Nick Coghlan wrote:

On Thu, Nov 25, 2010 at 3:41 AM, Michael Foord
fuzzy...@voidspace.org.uk  wrote:

Can you explain what you see as the difference?

I'm not particularly interested in type validation but I like the fact that
typical enum APIs allow you to group constants: the generated constant class
acts as a namespace for all the defined constants.

The problem with blessing one particular enum API is that people
have so many different ideas as to what an enum API should look like.



There actually seemed to be quite a bit of agreement around basic 
functionality though.



However, the one thing they all have in common is the ability to take
a value and give it a name, then present *both* of those in debugging
information.


And this is the most important functionality. I would say that the 
grouping (namespacing) of constants is also useful, provided by *most* 
Python enum APIs and easy to implement without over complexifying the API.


(Note that there is no *particular* hurry to get this into 3.2 - the 
beta is due imminently. I wouldn't object to it )



Are you just suggesting something along the lines of:

class NamedConstant(int):
def __new__(cls, name, val):
return int.__new__(cls, val)

def __init__(self, name, val):
self._name = name

def __repr__(self):
return 'NamedConstant %s' % self._name

FOO = NamedConstant('FOO', 3)

In general the less features the better, but I'd like a few more features
than that. :-)

Not quite. I'm suggesting a factory function that works for any value,
and derives the parent class from the type of the supplied value.
However, what you wrote is still the essence of the idea - we would be
primarily providing a building block that makes it easier for people
to *create* enum APIs if they want to, but for simple use cases (where
all they really wanted was the enhanced debugging information) they
wouldn't need to bother. In the standard library, wherever we do
enum-like things we would switch to using named values where it
makes sense to do so.

Doing so may actually make sense for more than just constants - it may
make sense for significant mutable globals as well.


Very interesting proposal (typed named values rather than just named 
constants). It doesn't handle flag values, which I would still like, but 
that only really makes sense for integers (sets can be OR'd but their 
representation is already understandable). Perhaps the integer named 
type could be special cased for that.


Without the grouping functionality (associating a bunch of names 
together) you lose the 'from_name' functionality. Guido was in favour of 
this, and it is an obvious feature where you have grouping: 
http://mail.python.org/pipermail/python-dev/2010-November/105912.html


I expect that the API to convert between enums and bare ints should be
i = int(e) and e = enumclass(i). It would be nice if s = str(e) and
e = enumclass(s) would work too.

This wouldn't work with your suggested implementation (as it is). 
Grouping and mutable named values could be inefficient and have issues 
around identity / equality. Maybe restrict the API to the immutable 
primitives.


All the best,

Michael

==
# Implementation (more than just a sketch, since it handles some
interesting corner cases)
import functools
@functools.lru_cache()
def _make_named_value_type(base_type):
 class _NamedValueType(base_type):
 def __new__(cls, name, value):
 return base_type.__new__(cls, value)
 def __init__(self, name, value):
 self.__name = name
 super().__init__(value)
 @property
 def _name(self):
 return self.__name
 def _raw(self):
 return base_type(self)
 def __repr__(self):
 return {}={}.format(self._name, super().__repr__())
 if base_type.__str__ is object.__str__:
 __str__ = base_type.__repr__
 _NamedValueType.__name__ = Named{}.format(base_type.__name__)
 return _NamedValueType

def named_value(name, value):
 return _make_named_value_type(type(value))(name, value)

def set_named_values(namespace, **kwds):
 for k, v in kwds.items():
 namespace[k] = named_value(k, v)

x = named_value(FOO, 1)
y = named_value(BAR, Hello World!)
z = named_value(BAZ, dict(a=1, b=2, c=3))

print(x, y, z, sep=\n)
print(\n.join(map(repr, (x, y, z
print(\n.join(map(str, map(type, (x, y, z)

set_named_values(globals(), foo=x._raw(), bar=y._raw(), baz=z._raw())
print(\n.join(map(repr, (foo, bar, baz
print(type(x) is type(foo), type(y) is type(bar), type(z) is type(baz))

==

# Session output for the last 6 lines

print(x, y, z, sep=\n)

1
Hello World!
{'a': 1, 'c': 3, 'b': 2}


print(\n.join(map(repr, (x, y, z

FOO=1
BAR='Hello World!'
BAZ={'a': 1, 'c': 3, 'b': 2}


print(\n.join(map(str, 

Re: [Python-Dev] constant/enum type in stdlib

2010-11-27 Thread Nick Coghlan
On Sun, Nov 28, 2010 at 12:01 AM, Michael Foord
fuzzy...@voidspace.org.uk wrote:
 Very interesting proposal (typed named values rather than just named
 constants). It doesn't handle flag values, which I would still like, but
 that only really makes sense for integers (sets can be OR'd but their
 representation is already understandable). Perhaps the integer named type
 could be special cased for that.

 Without the grouping functionality (associating a bunch of names together)
 you lose the 'from_name' functionality. Guido was in favour of this, and it
 is an obvious feature where you have grouping:
 http://mail.python.org/pipermail/python-dev/2010-November/105912.html

 I expect that the API to convert between enums and bare ints should be
 i = int(e) and e = enumclass(i). It would be nice if s = str(e) and
 e = enumclass(s) would work too.

Note that the i = int(e) and s = str(e) parts of Guido's
expectation do work (they are, in fact, the underling implementation
of the _raw() method), so an enum class would only be needed to
provide the other half of the equation. The named values have no
opinion on equivalence at all (they just defer to the parent class),
but change the rules for identity (which are always murky anyway,
since caching is optional even for immutable types).


 This wouldn't work with your suggested implementation (as it is). Grouping
 and mutable named values could be inefficient and have issues around
 identity / equality. Maybe restrict the API to the immutable primitives.

My proposal doesn't say anything about grouping at all - it's just an
idea for here's a standard way to associate a canonical name with a
particular object, independent of the namespaces that happen to
reference that object.

Now, a particular *grouping* API may want to restrict itself in
various ways, but that's my point. We should be looking at a standard
solution for the ground level problem (i.e. the idea named_value
attempts to solve) and then let various 3rd party enum/name grouping
implementations flourish on top of that, rather than trying to create
an all-singing all-dancing value grouping API (which is going to be
far more intrusive than a simple API for here's a way to give your
constants and important data structures names that show up in their
representations).

For example, using named_value as a primitive, you can fairly easily do:

class Namegroup:
# Missing lots of niceties of a real enum class, but shows the idea
# as to how a real implementation could leverage named_value
def __init__(self, _groupname, **kwds):
self._groupname = _groupname
pattern = _groupname + .{}
self._value_map = {}
for k, v in kwds.items():
attr = named_value(pattern.format(k), v)
setattr(self, k, attr)
self._value_map[v] = attr
@classmethod
def from_names(cls, groupname, *args):
kwds = dict(zip(args, range(len(args
return cls(groupname, **kwds)
def __call__(self, arg):
return self._value_map[arg]

silly = Namegroup.from_names(Silly, FOO, BAR, BAZ)

 silly.FOO
Silly.FOO=0
 int(silly.FOO)
0
 silly(0)
Silly.FOO=0

named_value deals with all the stuff to do with pretending to be the
original type of object (only with an associated name), leaving the
grouping API to deal with issues of creating groups of names and
mapping between them and the original values in various ways.

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] constant/enum type in stdlib

2010-11-27 Thread Barry Warsaw
On Nov 27, 2010, at 02:01 PM, Michael Foord wrote:

(Note that there is no *particular* hurry to get this into 3.2 - the beta is
due imminently. I wouldn't object to it )

Indeed.  I don't think the time is right to try to get this into 3.2.

-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] constant/enum type in stdlib

2010-11-27 Thread Glenn Linderman

On 11/27/2010 2:51 AM, Nick Coghlan wrote:

Not quite. I'm suggesting a factory function that works for any value,
and derives the parent class from the type of the supplied value.


Nick, thanks for the much better implementation than I achieved; you 
seem to have the same goals as my implementation.  I learned a bit 
making mine, and more understanding yours to some degree.  What I still 
don't understand about your implementation, is that when adding one 
additional line to your file, it fails:


w = named_value(ABC, z )

Now I can understand why it might not be a good thing to make a named 
value of a named value (confusing, at least), but I was surprised, and 
still do not understand, that it failed reporting the __new__() takes 
exactly 3 arguments (2 given).



___
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] constant/enum type in stdlib

2010-11-27 Thread Raymond Hettinger

On Nov 27, 2010, at 12:56 PM, Glenn Linderman wrote:

 On 11/27/2010 2:51 AM, Nick Coghlan wrote:
 
 Not quite. I'm suggesting a factory function that works for any value,
 and derives the parent class from the type of the supplied value.
 
 Nick, thanks for the much better implementation than I achieved; you seem to 
 have the same goals as my implementation.  I learned a bit making mine, 
 and more understanding yours to some degree.  What I still don't understand 
 about your implementation, is that when adding one additional line to your 
 file, it fails:
 
 w = named_value(ABC, z )
 
 Now I can understand why it might not be a good thing to make a named value 
 of a named value (confusing, at least), but I was surprised, and still do not 
 understand, that it failed reporting the __new__() takes exactly 3 arguments 
 (2 given).

Can I suggest that an enum-maker be offered as a third-party module rather than 
prematurely adding it into the standard library.


Raymond
___
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] constant/enum type in stdlib

2010-11-27 Thread Glenn Linderman

On 11/27/2010 12:56 PM, Glenn Linderman wrote:

On 11/27/2010 2:51 AM, Nick Coghlan wrote:

Not quite. I'm suggesting a factory function that works for any value,
and derives the parent class from the type of the supplied value.


Nick, thanks for the much better implementation than I achieved; you 
seem to have the same goals as my implementation.  I learned a bit 
making mine, and more understanding yours to some degree.  What I 
still don't understand about your implementation, is that when adding 
one additional line to your file, it fails:


w = named_value(ABC, z )

Now I can understand why it might not be a good thing to make a named 
value of a named value (confusing, at least), but I was surprised, and 
still do not understand, that it failed reporting the __new__() takes 
exactly 3 arguments (2 given).


OK, I puzzled out the error, and here is a cure of sorts.

def __new__(cls, name, value):
try:
return base_type.__new__(cls, value)
except TypeError:
return base_type.__new__(cls, name, value)
def __init__(self, name, value):
self.__name = name
try:
super().__init__(value)
except TypeError:
super().__init__(name, value)

Probably it would be better for the except clause to raise a different 
type of error ( Can't recursively create named value ) or to cleverly 
bypass the intermediate named value, and simply apply a new name to the 
original value.  Hmm...  For this, only __new__ need be changed:


def __new__(cls, name, value):
try:
return base_type.__new__(cls, value)
except TypeError:
return _make_named_value_type( type( value._raw() ))( 
name, value._raw() )

def __init__(self, name, value):
self.__name = name
super().__init__(value)

Thanks for not responding too quickly, I figured out more, and learned more.
___
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] constant/enum type in stdlib

2010-11-27 Thread Nick Coghlan
On Sun, Nov 28, 2010 at 9:26 AM, Raymond Hettinger
raymond.hettin...@gmail.com wrote:

 On Nov 27, 2010, at 12:56 PM, Glenn Linderman wrote:

 On 11/27/2010 2:51 AM, Nick Coghlan wrote:

 Not quite. I'm suggesting a factory function that works for any value,
 and derives the parent class from the type of the supplied value.

 Nick, thanks for the much better implementation than I achieved; you seem to 
 have the same goals as my implementation.  I learned a bit     making mine, 
 and more understanding yours to some degree.  What I still don't understand 
 about your implementation, is that when adding one additional line to your 
 file, it fails:

 w = named_value(ABC, z )

 Now I can understand why it might not be a good thing to make a named value 
 of a named value (confusing, at least), but I was surprised, and still do 
 not understand, that it failed reporting the __new__() takes exactly 3 
 arguments (2 given).

 Can I suggest that an enum-maker be offered as a third-party module rather 
 than prematurely adding it into the standard library.

Indeed. Glenn's failing example suggests to me that using a new
metaclass is probably going to be a cleaner option than trying to
dance around type's default behaviour within an ordinary class
definition (if nothing else, a separate metaclass makes it much easier
to detect when you're dealing with an instance of a named type).

Regardless, I still see value in approaching this whole discussion as
a two-level design problem, with named values as the more
fundamental concept, and then higher level grouping APIs to get
enum-style behaviour. Eventually attaining One Obvious Way for the
former seems achievable to me, while the diversity of use cases for
grouping APIs suggests to me that one-size-fits-all isn't going to
work unless that one size is a Frankenstein API with more options
than anyone could reasonably hope to keep in their head at once.

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] constant/enum type in stdlib

2010-11-27 Thread Terry Reedy

On 11/27/2010 6:26 PM, Raymond Hettinger wrote:


Can I suggest that an enum-maker be offered as a third-party module


Possibly with competing versions for trial and testing ;-)


rather than prematurely adding it into the standard library.


I had same thought.

--
Terry Jan Reedy

___
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] constant/enum type in stdlib

2010-11-25 Thread Glenn Linderman
So the following code defines constants with associated names that get 
put in the repr.


I'm still a Python newbie in some areas, particularly classes and 
metaclasses, maybe more.
But this Python 3 code seems to create constants with names ... works 
for int and str at least.


Special case for int defines a special  __or__ operator to OR both the 
values and the names, which some might like.


Dunno why it doesn't work for dict, and it is too late to research that 
today.  That's the last test case in the code below, so you can see how 
it works for int and string before it bombs.


There's some obvious cleanup work to be done, and it would be nice to 
make the names actually be constant... but they do lose their .name if 
you ignorantly assign the base type, so at least it is hard to change 
the value and keep the associated .name that gets reported by repr, 
which might reduce some confusion at debug time.


An idea I had, but have no idea how to implement, is that it might be 
nice to say:


with imported_constants_from_module:
   do_stuff

where do_stuff could reference the constants without qualifying them by 
module.  Of course, if you knew it was just a module of constants, you 
could import * from module :)  But the idea of with is that they'd go 
away at the end of that scope.


Some techniques here came from Raymond's namedtuple code.


def constant( name, val ):
typ = str( type( val ))
if typ.startswith(class ')  and  typ[ -2: ] == ':
typ = typ[ 8:-2 ]
ev = '''
class constant_%s( %s ):
def __new__( cls, val, name ):
self = %s.__new__( cls, val )
self.name = name
return self
def __repr__( self ):
return self.name + ': ' + str( self )
'''
if typ == 'int':
ev += '''
def __or__( self, other ):
if isinstance( other, constant_int ):
return constant_int( int( self ) | int( other ),
 self.name + ' | ' + other.name )
'''
ev += '''
%s = constant_%s( %s, '%s' )

'''
ev = ev % ( typ, typ, typ, name, typ, repr( val ), name )
print( ev )
exec( ev, globals())

constant('O_RANDOM', val=16 )

constant('O_SEQUENTIAL', val=32 )

constant(O_STRING, val=string)

def foo( x ):
print( str( x ))
print( repr( x ))
print( type( x ))

foo( O_RANDOM )
foo( O_SEQUENTIAL )
foo( O_STRING )

zz = O_RANDOM | O_SEQUENTIAL

foo( zz )

y = {'ab': 2, 'yz': 3 }
constant('O_DICT', y )

___
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] constant/enum type in stdlib

2010-11-25 Thread Nadeem Vawda
On Thu, Nov 25, 2010 at 11:34 AM, Glenn Linderman v+pyt...@g.nevcal.com wrote:
 So the following code defines constants with associated names that get put
 in the repr.

The code you gave doesn't work if the constant() function is moved
into a separate module from the code that calls it.  The globals()
function, as I understand it, gives you access to the global namespace
*of the current module*, so the constants end up being defined in the
module containing constant(), not the module you're calling it from.

You could get around this by passing the globals of the calling module
to constant(), but I think it's cleaner to use a class to provide a
distinct namespace for the constants.

 An idea I had, but have no idea how to implement, is that it might be nice
 to say:

     with imported_constants_from_module:
        do_stuff

 where do_stuff could reference the constants without qualifying them by
 module.  Of course, if you knew it was just a module of constants, you could
 import * from module :)  But the idea of with is that they'd go away at
 the end of that scope.

I don't think this is possible - the context manager protocol doesn't
allow you to modify the namespace of the caller like that.  Also, a
with statement does not have its own namespace; any names defined
inside its body will continue to be visible in the containing scope.

Of course, if you want to achieve something similar (at function
scope), you could say:

def foo(bar, baz):
from module import *
...
___
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] constant/enum type in stdlib

2010-11-25 Thread Michael Foord

On 25/11/2010 10:12, Nadeem Vawda wrote:

On Thu, Nov 25, 2010 at 11:34 AM, Glenn Lindermanv+pyt...@g.nevcal.com  wrote:

So the following code defines constants with associated names that get put
in the repr.

The code you gave doesn't work if the constant() function is moved
into a separate module from the code that calls it.  The globals()
function, as I understand it, gives you access to the global namespace
*of the current module*, so the constants end up being defined in the
module containing constant(), not the module you're calling it from.

You could get around this by passing the globals of the calling module
to constant(), but I think it's cleaner to use a class to provide a
distinct namespace for the constants.


An idea I had, but have no idea how to implement, is that it might be nice
to say:

 with imported_constants_from_module:
do_stuff

where do_stuff could reference the constants without qualifying them by
module.  Of course, if you knew it was just a module of constants, you could
import * from module :)  But the idea of with is that they'd go away at
the end of that scope.

I don't think this is possible - the context manager protocol doesn't
allow you to modify the namespace of the caller like that.  Also, a
with statement does not have its own namespace; any names defined
inside its body will continue to be visible in the containing scope.

Of course, if you want to achieve something similar (at function
scope), you could say:

def foo(bar, baz):
 from module import *
 ...


Not in Python 3 you can't. :-)

That's invalid syntax, import * can only be used at module level. This 
makes *testing* import * (i.e. testing your __all__) annoying - you have 
to exec('from module import *') instead.


Michael


___
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/fuzzyman%40voidspace.org.uk



--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-25 Thread Michael Foord

On 25/11/2010 09:34, Glenn Linderman wrote:
So the following code defines constants with associated names that get 
put in the repr.


I'm still a Python newbie in some areas, particularly classes and 
metaclasses, maybe more.
But this Python 3 code seems to create constants with names ... works 
for int and str at least.


Special case for int defines a special  __or__ operator to OR both the 
values and the names, which some might like.


Dunno why it doesn't work for dict, and it is too late to research 
that today.  That's the last test case in the code below, so you can 
see how it works for int and string before it bombs.


There's some obvious cleanup work to be done, and it would be nice to 
make the names actually be constant... but they do lose their .name if 
you ignorantly assign the base type, so at least it is hard to change 
the value and keep the associated .name that gets reported by repr, 
which might reduce some confusion at debug time.


An idea I had, but have no idea how to implement, is that it might be 
nice to say:


with imported_constants_from_module:
   do_stuff

where do_stuff could reference the constants without qualifying them 
by module.  Of course, if you knew it was just a module of constants, 
you could import * from module :)  But the idea of with is that 
they'd go away at the end of that scope.


Some techniques here came from Raymond's namedtuple code.


def constant( name, val ):
typ = str( type( val ))
if typ.startswith(class ')  and  typ[ -2: ] == ':
typ = typ[ 8:-2 ]
ev = '''
class constant_%s( %s ):
def __new__( cls, val, name ):
self = %s.__new__( cls, val )
self.name = name
return self
def __repr__( self ):
return self.name + ': ' + str( self )
'''
if typ == 'int':
ev += '''
def __or__( self, other ):
if isinstance( other, constant_int ):
return constant_int( int( self ) | int( other ),
 self.name + ' | ' + other.name )
'''


Not quite correct. If you or a value you with itself you should get back 
just the value not something with name|name as the repr.


We can hold off on implementations until we have general agreement that 
some kind of named constant *should* be added, and what the feature set 
should look like.


All the best,

Michael


ev += '''
%s = constant_%s( %s, '%s' )

'''
ev = ev % ( typ, typ, typ, name, typ, repr( val ), name )
print( ev )
exec( ev, globals())

constant('O_RANDOM', val=16 )

constant('O_SEQUENTIAL', val=32 )

constant(O_STRING, val=string)

def foo( x ):
print( str( x ))
print( repr( x ))
print( type( x ))

foo( O_RANDOM )
foo( O_SEQUENTIAL )
foo( O_STRING )

zz = O_RANDOM | O_SEQUENTIAL

foo( zz )

y = {'ab': 2, 'yz': 3 }
constant('O_DICT', y )


___
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/fuzzyman%40voidspace.org.uk



--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (BOGUS AGREEMENTS) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-25 Thread Rob Cliffe



On 25/11/2010 03:46, Greg Ewing wrote:

On 25/11/10 12:38, average wrote:

Is immutability a general need that should have general solution?


Yes, I have sometimes thought this.  Might be nice to have a mutable 
attribute that could be read and could be changed from True to False, 
though presumably not vice versa.

I don't think it really generalizes. Tuples are not just frozen
lists, for example -- they have a different internal structure
that's more efficient to create and access.

But couldn't they be presented to the Python programmer as a single 
type, with the implementation details hidden under the hood?

So
MyList.__mutable__ = False
would have the same effect as the present
MyList = tuple(MyList)
This would simplify some code that copes with either list(s) or tuple(s) 
as input data.

One would need syntax for (im)mutable literals, e.g.
[]i# immutable list (really a tuple).  Bit of a shame that 
i[] doesn't work.

or
[]f# frozen list (same thing)
[] # mutable list (same as now)
[]m  # alternative syntax for mutable list
This would reduce the overloading on parentheses and avoid having to 
write a tuple of one item as (t,) which often trips up newbies.  It woud 
also avoid one FAQ: Why does Python have separate list and tuple types?  
Also the syntax could be extended, e.g.

{a,b,c}f  # frozen set with 3 objects
{p:x,q:y}f  # frozen dictionary with 2 items
{:}f,  {}f  # (re the thread on set literals) frozen empty 
dictionary and frozen empty set!

Just some thoughts for Python 4.
Best wishes
Rob Cliffe
___
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] constant/enum type in stdlib

2010-11-24 Thread Michael Foord

On 23/11/2010 14:16, Nick Coghlan wrote:

On Tue, Nov 23, 2010 at 11:50 PM, Michael Foord
fuzzy...@voidspace.org.uk  wrote:

PEP 354 was rejected for two primary reasons - lack of interest and nowhere
obvious to put it. Would it be *so bad* if an enum type lived in its own
module? There is certainly more interest now, and if we are to use something
like this in the standard library it *has* to be in the standard library
(unless every module implements their own private _Constant class).

Time to revisit the PEP?

If you (or anyone else) wanted to revisit the PEP, then I would advise
trawling through the standard library looking for constants that could
be sensibly converted to enum values.


Based on a non-exhaustive search, Python standard library modules 
currently using integers for constants:


* re - has flags (OR'able constants) defined in sre_constants, each flag 
has two names (e.g. re.IGNORECASE and re.I)
* os has SEEK_SET, SEEK_CUR, SEEK_END - *plus* those implemented in 
posix / nt
* doctest has its own flag system, but is really just using integer 
flags / constants (quite a few of them)

* token has a tonne of constants (autogenerated)
* socket exports a bunch of constants defined in _socket
* gzip has flags: FTEXT, FHCRC, FEXTRA, FNAME, FCOMMENT

* errno (builtin module)

EALREADY, EINPROGRESS, EWOULDBLOCK, ECONNRESET, EINVAL,
ENOTCONN, ESHUTDOWN, EINTR, EISCONN, EBADF, ECONNABORTED

* opcode has HAVE_ARGUMENT, EXTENDED_ARG. In fact pretty much the whole 
of opcode is about defining and exposing named constants

* msilib uses flag constants
* multiprocessing.pool - RUN, CLOSE, TERMINATE
* multiprocessing.util - NOTSET, SUBDEBUG, DEBUG, INFO, SUBWARNING
* xml.dom and xml.dom.Node (in __init__.py) have a bunch of constants
* xml.dom.NodeFilter.NodeFilter holds a bunch of constants (some of them 
flags)

* xmlrpc.client has a bunch of error constants
* calendar uses constants to represent weekdays, plus one for the EPOCH 
that is best left alone
* http.client has a tonne of constants - recognisable as ports / error 
codes though
* dis has flags in COMPILER_FLAG_NAMES, which are then set as locals in 
inspect

* io defines SEEK_SET, SEEK_CUR, SEEK_END (same as os)

Where constants are implemented in C but exported via a Python module 
(the constants exported by os and socket for example) they could be 
wrapped. Where they are exported directly by a C extension or builtin 
module (e.g. errno) they are probably best left.


Raymond feels that having an enum / constant type would be Javaesque and 
unused. If we used it in the standard library the unused fear at least 
would be unwarranted. The change would be largely transparent to 
developers, except they get better debugging info. Twisted is also 
looking for an enum / constant type:


http://twistedmatrix.com/trac/ticket/4671

Because we would need to subclass from int for backwards compatibility 
we can't (unless the base class is set dynamically which I don't 
propose) it couldn't replace float / string constants. Hopefully it 
would still be sufficient to allow Twisted to use it. (Although they do 
so love reimplementing parts of the standard library - usually better 
than the standard library it has to be said.)


All the best,

Michael

There are a tonne of constants that are used as numbers (MAX_LINE_LENGTH 
appears in a few places) and aren't just arbitrary constants. There are 
also some other interesting ones:


* pty has STDIN_FILENO, STDOUT_FILENO, STDERR_FILENO, CHILD
* poplib has POP3_PORT, POP3_SSL_PORT - recognisable as port numbers, 
should be left as ints

* datetime.py has MINYEAR and MAXYEAR
* colorsys has float constants
* tty uses constants for termios list indexes (used as numbers I guess)
* curses.ascii has a whole bunch of integer constants referring to ascii 
characters
* Several modules - decimal, concurrent.futures, uuid (and now inspect) 
already use strings




A decision would also need to be made as to whether or not to subclass
int, or just provide __index__ (the former has the advantage of being
able to drop cleanly into OS level APIs that expect a numerical
constant).

Whether enums should provide arbitrary name-value mappings (ala C
enums) or were restricted to sequential indices starting from zero
would be another question best addressed by a code survey of at least
the stdlib.

And getgeneratorstate() doesn't count as a use case, since the
ordering isn't needed and using string literals instead of integers
will cover the debugging aspect :)

Cheers,
Nick.




--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents 

Re: [Python-Dev] constant/enum type in stdlib

2010-11-24 Thread Nick Coghlan
On Wed, Nov 24, 2010 at 10:30 PM, Michael Foord
fuzzy...@voidspace.org.uk wrote:
 Based on a non-exhaustive search, Python standard library modules currently
 using integers for constants:

Thanks for that review. I think following up on the NamedConstant
idea may make more sense than pursuing enums in their own right. That
way we could get the debugging benefits on the Python side regardless
of any type constraints on the value (e.g. needing to be an integer in
order to interface to C code), without needing to design an enum API
that suited all purposes.

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] constant/enum type in stdlib

2010-11-24 Thread Steven D'Aprano

Nick Coghlan wrote:

On Wed, Nov 24, 2010 at 10:30 PM, Michael Foord
fuzzy...@voidspace.org.uk wrote:

Based on a non-exhaustive search, Python standard library modules currently
using integers for constants:


Thanks for that review. I think following up on the NamedConstant
idea may make more sense than pursuing enums in their own right. 


Pardon me if I've missed something in this thread, but when you say 
NamedConstant, do you mean actual constants that can only be bound 
once but not re-bound? If so, +1. If not, what do you mean?


I thought PEP 3115 could be used to implement such constants, but I 
can't get it to work...


class readonlydict(dict):
def __setitem__(self, key, value):
if key in self:
raise TypeError(can't rebind constant)
dict.__setitem__(self, key, value)
# Need to also handle updates, del, pop, etc.

class MetaConstant(type):
@classmethod
def __prepare__(metacls, name, bases):
return readonlydict()
def __new__(cls, name, bases, classdict):
assert type(classdict) is readonlydict
return type.__new__(cls, name, bases, classdict)

class Constant(metaclass=MetaConstant):
a = 1
b = 2
c = 3


What I expect is that Constant.a should return 1, and Constant.a=2 
should raise TypeError, but what I get is a normal class __dict__.


 Constant.a
1
 Constant.a = 2
 Constant.a
2


--
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] constant/enum type in stdlib

2010-11-24 Thread Benjamin Peterson
2010/11/24 Steven D'Aprano st...@pearwood.info:
 Nick Coghlan wrote:

 On Wed, Nov 24, 2010 at 10:30 PM, Michael Foord
 fuzzy...@voidspace.org.uk wrote:

 Based on a non-exhaustive search, Python standard library modules
 currently
 using integers for constants:

 Thanks for that review. I think following up on the NamedConstant
 idea may make more sense than pursuing enums in their own right.

 Pardon me if I've missed something in this thread, but when you say
 NamedConstant, do you mean actual constants that can only be bound once
 but not re-bound? If so, +1. If not, what do you mean?

 I thought PEP 3115 could be used to implement such constants, but I can't
 get it to work...

 class readonlydict(dict):
    def __setitem__(self, key, value):
        if key in self:
            raise TypeError(can't rebind constant)
        dict.__setitem__(self, key, value)
    # Need to also handle updates, del, pop, etc.

 class MetaConstant(type):
   �...@classmethod
    def __prepare__(metacls, name, bases):
        return readonlydict()
    def __new__(cls, name, bases, classdict):
        assert type(classdict) is readonlydict
        return type.__new__(cls, name, bases, classdict)

 class Constant(metaclass=MetaConstant):
    a = 1
    b = 2
    c = 3


 What I expect is that Constant.a should return 1, and Constant.a=2 should
 raise TypeError, but what I get is a normal class __dict__.

The construction namespace can be customized, but class.__dict__ must
always be a real dict.



-- 
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] constant/enum type in stdlib

2010-11-24 Thread Michael Foord

On 24/11/2010 14:08, Nick Coghlan wrote:

On Wed, Nov 24, 2010 at 10:30 PM, Michael Foord
fuzzy...@voidspace.org.uk  wrote:

Based on a non-exhaustive search, Python standard library modules currently
using integers for constants:

Thanks for that review. I think following up on the NamedConstant
idea may make more sense than pursuing enums in their own right. That
way we could get the debugging benefits on the Python side regardless
of any type constraints on the value (e.g. needing to be an integer in
order to interface to C code), without needing to design an enum API
that suited all purposes.


Can you explain what you see as the difference?

I'm not particularly interested in type validation but I like the fact 
that typical enum APIs allow you to group constants: the generated 
constant class acts as a namespace for all the defined constants.


Are you just suggesting something along the lines of:

class NamedConstant(int):
def __new__(cls, name, val):
return int.__new__(cls, val)

def __init__(self, name, val):
self._name = name

def __repr__(self):
return 'NamedConstant %s' % self._name

FOO = NamedConstant('FOO', 3)

In general the less features the better, but I'd like a few more 
features than that. :-)


All the best,

Michael



Cheers,
Nick.




--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-24 Thread average
Is immutability a general need that should have general solution?  By
generalizing the idea to lists/tuples, set/frozenset, dicts, and strings
(for example), it seems one could simplify the container classes, eliminate
code complexity, and perhaps improve resource utilization.

mark
___
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] constant/enum type in stdlib

2010-11-24 Thread Greg Ewing

On 25/11/10 12:38, average wrote:

Is immutability a general need that should have general solution?


I don't think it really generalizes. Tuples are not just frozen
lists, for example -- they have a different internal structure
that's more efficient to create and access.

--
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] constant/enum type in stdlib

2010-11-23 Thread Michael Foord

On 23/11/2010 13:41, Nick Coghlan wrote:

On Tue, Nov 23, 2010 at 2:46 AM,exar...@twistedmatrix.com  wrote:

On 04:24 pm, solip...@pitrou.net wrote:

On Mon, 22 Nov 2010 17:08:36 +0100
Hrvoje Niksichrvoje.nik...@avl.com  wrote:

On 11/22/2010 04:37 PM, Antoine Pitrou wrote:

+1.  The problem with int constants is that the int gets printed, not
the name, when you dump them for debugging purposes :)

Well, it's trivial to subclass int to something with a nicer __repr__.
PyGTK uses that technique for wrapping C enums:

Nice. It might be useful to add a private _Constant class somewhere for
stdlib purposes.

http://www.python.org/dev/peps/pep-0354/

Indeed, it is difficult to do enums is such a way that they feel
sufficiently robust to be worth the effort of including them (although
these days, I would be inclined to follow the namedtuple API style
rather than that presented in PEP 354).
Right. As it happens I just submitted a patch to Barry Warsaw's enum 
package (nice), flufl.enum [1], to allow namedtuple style creation of 
named constants:


 from flufl.enum import make_enum
 Colors = make_enum('Colors', 'red green blue')
 Colors
Colors {red: 1, green: 2, blue: 3}


PEP 354 was rejected for two primary reasons - lack of interest and 
nowhere obvious to put it. Would it be *so bad* if an enum type lived in 
its own module? There is certainly more interest now, and if we are to 
use something like this in the standard library it *has* to be in the 
standard library (unless every module implements their own private 
_Constant class).


Time to revisit the PEP?

All the best,

Michael

[1] https://launchpad.net/flufl.enum


Cheers,
Nick.




--
http://www.voidspace.org.uk/

___
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] constant/enum type in stdlib

2010-11-23 Thread Nick Coghlan
On Tue, Nov 23, 2010 at 11:50 PM, Michael Foord
fuzzy...@voidspace.org.uk wrote:
 PEP 354 was rejected for two primary reasons - lack of interest and nowhere
 obvious to put it. Would it be *so bad* if an enum type lived in its own
 module? There is certainly more interest now, and if we are to use something
 like this in the standard library it *has* to be in the standard library
 (unless every module implements their own private _Constant class).

 Time to revisit the PEP?

If you (or anyone else) wanted to revisit the PEP, then I would advise
trawling through the standard library looking for constants that could
be sensibly converted to enum values.

A decision would also need to be made as to whether or not to subclass
int, or just provide __index__ (the former has the advantage of being
able to drop cleanly into OS level APIs that expect a numerical
constant).

Whether enums should provide arbitrary name-value mappings (ala C
enums) or were restricted to sequential indices starting from zero
would be another question best addressed by a code survey of at least
the stdlib.

And getgeneratorstate() doesn't count as a use case, since the
ordering isn't needed and using string literals instead of integers
will cover the debugging aspect :)

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] constant/enum type in stdlib

2010-11-23 Thread Michael Foord

On 23/11/2010 14:16, Nick Coghlan wrote:

On Tue, Nov 23, 2010 at 11:50 PM, Michael Foord
fuzzy...@voidspace.org.uk  wrote:

PEP 354 was rejected for two primary reasons - lack of interest and nowhere
obvious to put it. Would it be *so bad* if an enum type lived in its own
module? There is certainly more interest now, and if we are to use something
like this in the standard library it *has* to be in the standard library
(unless every module implements their own private _Constant class).

Time to revisit the PEP?

If you (or anyone else) wanted to revisit the PEP, then I would advise
trawling through the standard library looking for constants that could
be sensibly converted to enum values.

A decision would also need to be made as to whether or not to subclass
int, or just provide __index__ (the former has the advantage of being
able to drop cleanly into OS level APIs that expect a numerical
constant).

Whether enums should provide arbitrary name-value mappings (ala C
enums) or were restricted to sequential indices starting from zero
would be another question best addressed by a code survey of at least
the stdlib.

And getgeneratorstate() doesn't count as a use case, since the
ordering isn't needed and using string literals instead of integers
will cover the debugging aspect :)

Well, for backwards compatibility reasons the new constants would have 
to *behave* like the old ones (including having the same underlying 
value and comparing equal to it).


In many cases it is *likely* that subclassing int is a better way of 
achieving that. Actually looking through the standard library to 
evaluate it is the only way of confirming that.


Another API, that reduces the duplication of creating the enum and 
setting the names, could be something like:


make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int, 
module=__name__)


Using __name__ we can set the module globals in the call to make_enums.

All the best,

Michael



Cheers,
Nick.




--
http://www.voidspace.org.uk/

___
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] constant/enum type in stdlib

2010-11-23 Thread Antoine Pitrou
On Tue, 23 Nov 2010 14:24:18 +
Michael Foord fuzzy...@voidspace.org.uk wrote:
 Well, for backwards compatibility reasons the new constants would have 
 to *behave* like the old ones (including having the same underlying 
 value and comparing equal to it).
 
 In many cases it is *likely* that subclassing int is a better way of 
 achieving that. Actually looking through the standard library to 
 evaluate it is the only way of confirming that.
 
 Another API, that reduces the duplication of creating the enum and 
 setting the names, could be something like:
 
  make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int, 
 module=__name__)
 
 Using __name__ we can set the module globals in the call to make_enums.

I don't understand why people insist on calling that an enum. enum is
a C legacy and it doesn't bring anything useful as I can tell. Instead,
just assign the values explicitly.

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] constant/enum type in stdlib

2010-11-23 Thread Benjamin Peterson
2010/11/23 Antoine Pitrou solip...@pitrou.net:
 On Tue, 23 Nov 2010 14:24:18 +
 Michael Foord fuzzy...@voidspace.org.uk wrote:
 Well, for backwards compatibility reasons the new constants would have
 to *behave* like the old ones (including having the same underlying
 value and comparing equal to it).

 In many cases it is *likely* that subclassing int is a better way of
 achieving that. Actually looking through the standard library to
 evaluate it is the only way of confirming that.

 Another API, that reduces the duplication of creating the enum and
 setting the names, could be something like:

      make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int,
 module=__name__)

 Using __name__ we can set the module globals in the call to make_enums.

 I don't understand why people insist on calling that an enum. enum is
 a C legacy and it doesn't bring anything useful as I can tell. Instead,
 just assign the values explicitly.

The concept of a enumeration of values is still useful outside its
stunted C incarnation.

Out of curiosity, why is enum legacy in C?



-- 
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] constant/enum type in stdlib

2010-11-23 Thread Michael Foord

On 23/11/2010 14:42, Antoine Pitrou wrote:

On Tue, 23 Nov 2010 14:24:18 +
Michael Foordfuzzy...@voidspace.org.uk  wrote:

Well, for backwards compatibility reasons the new constants would have
to *behave* like the old ones (including having the same underlying
value and comparing equal to it).

In many cases it is *likely* that subclassing int is a better way of
achieving that. Actually looking through the standard library to
evaluate it is the only way of confirming that.

Another API, that reduces the duplication of creating the enum and
setting the names, could be something like:

  make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int,
module=__name__)

Using __name__ we can set the module globals in the call to make_enums.

I don't understand why people insist on calling that an enum. enum is
a C legacy and it doesn't bring anything useful as I can tell. Instead,
just assign the values explicitly.



enum isn't only in C. (They are in C# as well at least.) Wikipedia links 
enum to enumerated type and says:


an enumerated type (also called enumeration or enum) is a data type 
consisting of a set of named values


It sounds entirely appropriate. I have no problem with explicitly 
assigning values instead of doing it automagically.


All the best,

Michael


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/fuzzyman%40voidspace.org.uk



--
http://www.voidspace.org.uk/

___
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] constant/enum type in stdlib

2010-11-23 Thread Antoine Pitrou
Le mardi 23 novembre 2010 à 08:52 -0600, Benjamin Peterson a écrit :
 2010/11/23 Antoine Pitrou solip...@pitrou.net:
  On Tue, 23 Nov 2010 14:24:18 +
  Michael Foord fuzzy...@voidspace.org.uk wrote:
  Well, for backwards compatibility reasons the new constants would have
  to *behave* like the old ones (including having the same underlying
  value and comparing equal to it).
 
  In many cases it is *likely* that subclassing int is a better way of
  achieving that. Actually looking through the standard library to
  evaluate it is the only way of confirming that.
 
  Another API, that reduces the duplication of creating the enum and
  setting the names, could be something like:
 
   make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int,
  module=__name__)
 
  Using __name__ we can set the module globals in the call to make_enums.
 
  I don't understand why people insist on calling that an enum. enum is
  a C legacy and it doesn't bring anything useful as I can tell. Instead,
  just assign the values explicitly.
 
 The concept of a enumeration of values is still useful outside its
 stunted C incarnation.

Well, it is easy to assign range(N) to a tuple of names when desired. I
don't think an automatically-enumerating constant generator is needed.

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] constant/enum type in stdlib

2010-11-23 Thread Antoine Pitrou
Le mardi 23 novembre 2010 à 14:56 +, Michael Foord a écrit :
 On 23/11/2010 14:42, Antoine Pitrou wrote:
  On Tue, 23 Nov 2010 14:24:18 +
  Michael Foordfuzzy...@voidspace.org.uk  wrote:
  Well, for backwards compatibility reasons the new constants would have
  to *behave* like the old ones (including having the same underlying
  value and comparing equal to it).
 
  In many cases it is *likely* that subclassing int is a better way of
  achieving that. Actually looking through the standard library to
  evaluate it is the only way of confirming that.
 
  Another API, that reduces the duplication of creating the enum and
  setting the names, could be something like:
 
make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int,
  module=__name__)
 
  Using __name__ we can set the module globals in the call to make_enums.
  I don't understand why people insist on calling that an enum. enum is
  a C legacy and it doesn't bring anything useful as I can tell. Instead,
  just assign the values explicitly.
 
 
 enum isn't only in C. (They are in C# as well at least.)

Well, it's been inherited by C-like languages, no doubt. Like braces and
semicolumns :)

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] constant/enum type in stdlib

2010-11-23 Thread Michael Foord

On 23/11/2010 15:01, Antoine Pitrou wrote:

Le mardi 23 novembre 2010 à 08:52 -0600, Benjamin Peterson a écrit :

2010/11/23 Antoine Pitrousolip...@pitrou.net:

On Tue, 23 Nov 2010 14:24:18 +
Michael Foordfuzzy...@voidspace.org.uk  wrote:

Well, for backwards compatibility reasons the new constants would have
to *behave* like the old ones (including having the same underlying
value and comparing equal to it).

In many cases it is *likely* that subclassing int is a better way of
achieving that. Actually looking through the standard library to
evaluate it is the only way of confirming that.

Another API, that reduces the duplication of creating the enum and
setting the names, could be something like:

  make_enums(Names, NAME_ONE NAME_TWO NAME_THREE, base_type=int,
module=__name__)

Using __name__ we can set the module globals in the call to make_enums.

I don't understand why people insist on calling that an enum. enum is
a C legacy and it doesn't bring anything useful as I can tell. Instead,
just assign the values explicitly.

The concept of a enumeration of values is still useful outside its
stunted C incarnation.

Well, it is easy to assign range(N) to a tuple of names when desired. I
don't think an automatically-enumerating constant generator is needed.

Right, and that is current practise. It has the disadvantage (that you 
seemed to acknowledge) that when debugging the integer values are seen 
instead of something with a useful repr.


Having a *simple* class (and API to create them) that produces named 
constants with a useful repr, is what we are discussing, and that seems 
awfully like an enum (in the general sense not in a C specific sense). 
For backwards compatibility these constants, where they replace integer 
constants, would need to be integer subclasses with the same behaviour. 
Like the Qt example you appreciated so much. ;-)


There are still two reasonable APIs (unless you have changed your mind 
and think that sticking with plain integers is best), of which I prefer 
the latter:


SOME_CONST = Constant('SOME_CONST', 1)
OTHER_CONST = Constant('OTHER_CONST', 2)

or:

Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1)
SOME_CONST = Constants.SOME_CONST
OTHER_CONST = Constants.OTHER_CONST

(Well, there is a third option that takes __name__ and sets the 
constants in the module automagically. I can understand why people would 
dislike that though.)


All the best,

Michael Foord

Michael


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/fuzzyman%40voidspace.org.uk



--
http://www.voidspace.org.uk/

___
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] constant/enum type in stdlib

2010-11-23 Thread Antoine Pitrou
Le mardi 23 novembre 2010 à 15:15 +, Michael Foord a écrit :
 There are still two reasonable APIs (unless you have changed your mind 
 and think that sticking with plain integers is best), of which I prefer 
 the latter:
 
 SOME_CONST = Constant('SOME_CONST', 1)
 OTHER_CONST = Constant('OTHER_CONST', 2)
 
 or:
 
 Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1)

Or:

Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST',   
   values=range(1, 3))

Again, auto-enumeration is useless since it's trivial to achieve
explicitly.

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] constant/enum type in stdlib

2010-11-23 Thread Michael Foord

On 23/11/2010 15:30, Antoine Pitrou wrote:

Le mardi 23 novembre 2010 à 15:15 +, Michael Foord a écrit :

There are still two reasonable APIs (unless you have changed your mind
and think that sticking with plain integers is best), of which I prefer
the latter:

SOME_CONST = Constant('SOME_CONST', 1)
OTHER_CONST = Constant('OTHER_CONST', 2)

or:

Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1)

Or:

Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST',
values=range(1, 3))

Again, auto-enumeration is useless since it's trivial to achieve
explicitly.


Ah, I see. It is the auto-enumeration you disliked. Sure - not a problem.

I think the step that Nick described, of evaluating places in the 
standard library that this could be used, is a good one. I'll try to get 
around to it and perhaps attempt to resuscitate the PEP. (Any 
suggestions as to an appropriate module if having it live in its own 
module is still an objection?)


Michael


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/fuzzyman%40voidspace.org.uk



--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-23 Thread Antoine Pitrou
Le mardi 23 novembre 2010 à 15:40 +, Michael Foord a écrit :
 On 23/11/2010 15:30, Antoine Pitrou wrote:
  Le mardi 23 novembre 2010 à 15:15 +, Michael Foord a écrit :
  There are still two reasonable APIs (unless you have changed your mind
  and think that sticking with plain integers is best), of which I prefer
  the latter:
 
  SOME_CONST = Constant('SOME_CONST', 1)
  OTHER_CONST = Constant('OTHER_CONST', 2)
 
  or:
 
  Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1)
  Or:
 
  Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST',
  values=range(1, 3))
 
  Again, auto-enumeration is useless since it's trivial to achieve
  explicitly.
 
 Ah, I see. It is the auto-enumeration you disliked. Sure - not a problem.
 
 I think the step that Nick described, of evaluating places in the 
 standard library that this could be used, is a good one. I'll try to get 
 around to it and perhaps attempt to resuscitate the PEP. (Any 
 suggestions as to an appropriate module if having it live in its own 
 module is still an objection?)

We already have a bunch of bizarrely unrelated stuff in collections
(such as Callable), so we could put enum there too.

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] constant/enum type in stdlib

2010-11-23 Thread Michael Foord

On 23/11/2010 16:05, Antoine Pitrou wrote:

Le mardi 23 novembre 2010 à 15:40 +, Michael Foord a écrit :

On 23/11/2010 15:30, Antoine Pitrou wrote:

Le mardi 23 novembre 2010 à 15:15 +, Michael Foord a écrit :

There are still two reasonable APIs (unless you have changed your mind
and think that sticking with plain integers is best), of which I prefer
the latter:

SOME_CONST = Constant('SOME_CONST', 1)
OTHER_CONST = Constant('OTHER_CONST', 2)

or:

Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1)

Or:

Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST',
 values=range(1, 3))

Again, auto-enumeration is useless since it's trivial to achieve
explicitly.

Ah, I see. It is the auto-enumeration you disliked. Sure - not a problem.

I think the step that Nick described, of evaluating places in the
standard library that this could be used, is a good one. I'll try to get
around to it and perhaps attempt to resuscitate the PEP. (Any
suggestions as to an appropriate module if having it live in its own
module is still an objection?)

We already have a bunch of bizarrely unrelated stuff in collections
(such as Callable), so we could put enum there too.



I guess it creates collections of constants...

Michael


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/fuzzyman%40voidspace.org.uk



--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-23 Thread Ben . Cottrell
On Tue, 23 Nov 2010 15:15:29 +, Michael Foord wrote:
 There are still two reasonable APIs (unless you have changed your mind 
 and think that sticking with plain integers is best), of which I prefer 
 the latter:
 
 SOME_CONST = Constant('SOME_CONST', 1)
 OTHER_CONST = Constant('OTHER_CONST', 2)
 
 or:
 
 Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1)
 SOME_CONST = Constants.SOME_CONST
 OTHER_CONST = Constants.OTHER_CONST

I prefer the latter too, because that makes it possible to have
'Constants' be a rendezvous point for making sure that you're
passing something valid. Perhaps using 'in':

def func(foo):
if foo not in Constants:
raise ValueError('foo must be SOME_CONST or OTHER_CONST')
...

I know this is probably not going to happen, but I would *so much*
like it if functions would start rejecting the wrong kind of 2.
Constants that are valid, integer-wise, but which aren't part of
the set of constants allowed for that argument. I'd prefer not to
think of the number of times I've made the following mistake:

s = socket.socket(socket.SOCK_DGRAM, socket.AF_INET)

~Ben
___
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] constant/enum type in stdlib

2010-11-23 Thread Michael Foord

On 23/11/2010 15:37, ben.cottr...@nominum.com wrote:

On Tue, 23 Nov 2010 15:15:29 +, Michael Foord wrote:

There are still two reasonable APIs (unless you have changed your mind
and think that sticking with plain integers is best), of which I prefer
the latter:

SOME_CONST = Constant('SOME_CONST', 1)
OTHER_CONST = Constant('OTHER_CONST', 2)

or:

Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST', start=1)
SOME_CONST = Constants.SOME_CONST
OTHER_CONST = Constants.OTHER_CONST

I prefer the latter too, because that makes it possible to have
'Constants' be a rendezvous point for making sure that you're
passing something valid. Perhaps using 'in':

def func(foo):
 if foo not in Constants:
 raise ValueError('foo must be SOME_CONST or OTHER_CONST')
 ...

I know this is probably not going to happen, but I would *so much*
like it if functions would start rejecting the wrong kind of 2.
Constants that are valid, integer-wise, but which aren't part of
the set of constants allowed for that argument. I'd prefer not to
think of the number of times I've made the following mistake:

s = socket.socket(socket.SOCK_DGRAM, socket.AF_INET)


Well it would be perfectly possible for the __contains__ method (on the 
metaclass so that a Constants class can act as a container) to permit a 
*raw integer* (to be backwards compatible with code using hard coded 
values) but not permit other constants that aren't valid. Code that is 
*deliberately* using the wrong constants would be screwed of course...


All the best,

Michael

~Ben
___
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/fuzzyman%40voidspace.org.uk



--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-23 Thread Barry Warsaw
On Nov 23, 2010, at 01:50 PM, Michael Foord wrote:

Right. As it happens I just submitted a patch to Barry Warsaw's enum package
(nice), flufl.enum [1], to allow namedtuple style creation of named
constants:

Thanks for the plug (and the nice patch).

FWIW, the documentation for the package is here:

http://packages.python.org/flufl.enum/

I made some explicit decisions about the API and semantics of this package, to
fit my own use cases and sensibilities.  I guess you wouldn't expect anything
else wink, but I'm willing to acknowledge that others would make different
decisions, and certainly the number of existing enum implementations out there
proves that there are lots of interesting ways to go about it.

That said, there are several things I like about my package:

* Enums are not subclassed from ints or strs.  They are a distinct data type
  that can be converted to and from ints and strs.  EIBTI.

* The typical way to create them is through a simple, but explicit class
  definition.  I personally like being explicit about the item values, and the
  assignments are required to make the metaclass work properly, but Michael's
  convenience patch is totally appropriate for cases where you don't care, or
  you want a one-liner.

* Enum items are singletons and are intended to be compared by identity.  They
  can be compared by equality but are not ordered.

* Enum items have an unambiguous symbolic repr and a nice human readable str.

* Given an enum item, you can get to its enum class, and given the class you
  can get to the set of items.

* Enums can be subclassed (though all items in the subclass must have unique
  values).

In any case it may be that enums are too tied to specific use cases to find a
good common ground for the stdlib.  I've been using my module for years and if
there's interest I would of course be happy to donate it for use in the
stdlib.  Like the original sets implementation, it makes perfect sense to
provide them in a separate module rather than as a built-in type.

-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] constant/enum type in stdlib

2010-11-23 Thread Barry Warsaw
On Nov 23, 2010, at 03:15 PM, Michael Foord wrote:

(Well, there is a third option that takes __name__ and sets the constants in
the module automagically. I can understand why people would dislike that
though.)

Personally, I think if you want that, then the explicit class definition is a
better way to go.

-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] constant/enum type in stdlib

2010-11-23 Thread P.J. Eby

At 11:31 AM 11/23/2010 -0500, Barry Warsaw wrote:

On Nov 23, 2010, at 03:15 PM, Michael Foord wrote:

(Well, there is a third option that takes __name__ and sets the constants in
the module automagically. I can understand why people would dislike that
though.)

Personally, I think if you want that, then the explicit class definition is a
better way to go.


This reminds me: a stdlib enum should support proper pickling and 
copying; i.e.:


   assert SomeEnum.anEnum is pickle.loads(pickle.dumps(SomeEnum.anEnum))

This could probably be implemented by adding something like:

   def __reduce__(self):
   return getattr, (self._class, self._enumname)

in the EnumValue class.

___
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] constant/enum type in stdlib

2010-11-23 Thread Michael Foord

On 23/11/2010 16:27, Barry Warsaw wrote:

On Nov 23, 2010, at 01:50 PM, Michael Foord wrote:


Right. As it happens I just submitted a patch to Barry Warsaw's enum package
(nice), flufl.enum [1], to allow namedtuple style creation of named
constants:

Thanks for the plug (and the nice patch).

FWIW, the documentation for the package is here:

http://packages.python.org/flufl.enum/

I made some explicit decisions about the API and semantics of this package, to
fit my own use cases and sensibilities.  I guess you wouldn't expect anything
elsewink, but I'm willing to acknowledge that others would make different
decisions, and certainly the number of existing enum implementations out there
proves that there are lots of interesting ways to go about it.

That said, there are several things I like about my package:

* Enums are not subclassed from ints or strs.  They are a distinct data type
   that can be converted to and from ints and strs.  EIBTI.


But if we are to use it *in* the standard library (as opposed to merely 
adding a module *to* the standard library) there are backwards 
compatibility concerns. Where modules are already using integers for 
constants then integers still need to work.


One easy way to achieve this is to subclass integer. If we don't do that 
(assuming we decide that putting a solution in the standard library is 
appropriate) then we'll have to evaluate what we mean by backwards 
compatible. If the modules that use the constants aren't to change then 
comparing equal to the underlying value is the minimum (so that the 
original value can still be used in place of the new named constant). 
Not sure if you'd be happy to make that change in flufl.enum.




* The typical way to create them is through a simple, but explicit class
   definition.  I personally like being explicit about the item values, and the
   assignments are required to make the metaclass work properly, but Michael's
   convenience patch is totally appropriate for cases where you don't care, or
   you want a one-liner.


If make_enum was to take a set of values to use (as Antoine suggested) I 
don't see what's un-explicit about it.


All the best,

Michael


* Enum items are singletons and are intended to be compared by identity.  They
   can be compared by equality but are not ordered.

* Enum items have an unambiguous symbolic repr and a nice human readable str.

* Given an enum item, you can get to its enum class, and given the class you
   can get to the set of items.

* Enums can be subclassed (though all items in the subclass must have unique
   values).

In any case it may be that enums are too tied to specific use cases to find a
good common ground for the stdlib.  I've been using my module for years and if
there's interest I would of course be happy to donate it for use in the
stdlib.  Like the original sets implementation, it makes perfect sense to
provide them in a separate module rather than as a built-in type.

-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/fuzzyman%40voidspace.org.uk



--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (BOGUS AGREEMENTS) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-23 Thread Antoine Pitrou
Le mardi 23 novembre 2010 à 12:32 -0500, Isaac Morland a écrit :
 On Tue, 23 Nov 2010, Antoine Pitrou wrote:
 
  We already have a bunch of bizarrely unrelated stuff in collections
  (such as Callable), so we could put enum there too.
 
 Why not just enum (i.e., from enum import [...] or import 
 enum.[...])?  Enumerations are one of the basic kinds of types overall 
 (speaking informally and independent of any specific language) - they 
 aren't at all exotic.

Enumerations aren't a type at all (they have no distinguishing
property).

 And Flat is better than nested, after all.

Not when it means creating a separate module for every micro-feature.

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] constant/enum type in stdlib

2010-11-23 Thread Isaac Morland

On Tue, 23 Nov 2010, Antoine Pitrou wrote:


We already have a bunch of bizarrely unrelated stuff in collections
(such as Callable), so we could put enum there too.


Why not just enum (i.e., from enum import [...] or import 
enum.[...])?  Enumerations are one of the basic kinds of types overall 
(speaking informally and independent of any specific language) - they 
aren't at all exotic.  And Flat is better than nested, after all.


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] constant/enum type in stdlib

2010-11-23 Thread Isaac Morland

On Tue, 23 Nov 2010, Antoine Pitrou wrote:


Le mardi 23 novembre 2010 à 12:32 -0500, Isaac Morland a écrit :

On Tue, 23 Nov 2010, Antoine Pitrou wrote:


We already have a bunch of bizarrely unrelated stuff in collections
(such as Callable), so we could put enum there too.


Why not just enum (i.e., from enum import [...] or import
enum.[...])?  Enumerations are one of the basic kinds of types overall
(speaking informally and independent of any specific language) - they
aren't at all exotic.


Enumerations aren't a type at all (they have no distinguishing
property).


Each enumeration is a type (well, OK, not in every language, presumably, 
but certainly in many languages).  The word basic is more important than 
types in my sentence - the point is that an enumeration capability is a 
very common one in a type system, and is very general, not specific to any 
particular application.



And Flat is better than nested, after all.


Not when it means creating a separate module for every micro-feature.


Classes have their own keyword.  I don't think it's disproportionate to 
give enums a top-level module name.


Having said that, I understand we're trying to have a not-too-flat module 
namespace and I can see the sense in putting it in collections.  But I 
think the idea that enumerations are of very wide applicability and hence 
deserve a shorter name should be seriously considered.


I'll leave it at that, except for:

Hey, how about this syntax:

enum Colors:
red = 0
green = 10
blue

(blue gets the value 11)

;-)

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] constant/enum type in stdlib

2010-11-23 Thread Fred Drake
On Tue, Nov 23, 2010 at 12:37 PM, Antoine Pitrou solip...@pitrou.net wrote:
 Enumerations aren't a type at all (they have no distinguishing
 property).

In any given language, this may be true, or not.  Whether they should
be distinct in Python is core to the current discussion.

From a backward-compatibility perspective, what makes sense depends on
whether they're used to implement existing constants (socket.AF_INET,
etc.) or if they reserved for new features only.


  -Fred

--
Fred L. Drake, Jr.    fdrake at acm.org
A storm broke loose in my mind.  --Albert Einstein
___
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] constant/enum type in stdlib

2010-11-23 Thread Antoine Pitrou
Le mardi 23 novembre 2010 à 12:57 -0500, Fred Drake a écrit :
 On Tue, Nov 23, 2010 at 12:37 PM, Antoine Pitrou solip...@pitrou.net wrote:
  Enumerations aren't a type at all (they have no distinguishing
  property).
 
 In any given language, this may be true, or not.  Whether they should
 be distinct in Python is core to the current discussion.

I meant type in the structural sense (hence the parenthesis). enums
are just auto-generated constants. Since Python makes it trivial to
generate sequential integers, there's no need for a specific enum
construct.

Now you may argue that enums should be strongly-typed, but that would be
a bit backwards given Python's preference for duck-typing.

 From a backward-compatibility perspective, what makes sense depends on
 whether they're used to implement existing constants (socket.AF_INET,
 etc.) or if they reserved for new features only.

It's not only backwards compatibility. New features relying on C APIs
have to be able to map constants to the integers used in the C library.
It would be much better if this were done naturally rather than through
explicit conversion maps.
(this really means subclassing int, if we don't want to complicate
C-level code)

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] constant/enum type in stdlib

2010-11-23 Thread Antoine Pitrou
Le mardi 23 novembre 2010 à 12:50 -0500, Isaac Morland a écrit :
 Each enumeration is a type (well, OK, not in every language, presumably, 
 but certainly in many languages).  The word basic is more important than 
 types in my sentence - the point is that an enumeration capability is a 
 very common one in a type system, and is very general, not specific to any 
 particular application.

Python already has an enumeration capability. It's called range().
There's nothing else that C enums have. AFAICT, neither do enums in
other mainstream languages (assuming they even exist; I don't remember
Perl, PHP or Javascript having anything like that, but perhaps I'm
mistaken).

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] constant/enum type in stdlib

2010-11-23 Thread Bill Janssen
Isaac Morland ijmor...@uwaterloo.ca wrote:

 On Tue, 23 Nov 2010, Antoine Pitrou wrote:
 
  Le mardi 23 novembre 2010 à 12:32 -0500, Isaac Morland a écrit :
  On Tue, 23 Nov 2010, Antoine Pitrou wrote:
 
  We already have a bunch of bizarrely unrelated stuff in collections
  (such as Callable), so we could put enum there too.
 
  Why not just enum (i.e., from enum import [...] or import
  enum.[...])?  Enumerations are one of the basic kinds of types overall
  (speaking informally and independent of any specific language) - they
  aren't at all exotic.
 
  Enumerations aren't a type at all (they have no distinguishing
  property).

Not in C, but in some other languages.

 Each enumeration is a type (well, OK, not in every language,
 presumably, but certainly in many languages).

The main purpose of that is to be able to catch type mismatches with
static typing, though.  Seems kind of pointless for Python.

 Classes have their own keyword.  I don't think it's disproportionate
 to give enums a top-level module name.

I do.

 Hey, how about this syntax:
 
 enum Colors:
   red = 0
   green = 10
   blue

Why not

  class Color:
 red = (255, 0, 0)
 green = (0, 255, 0)
 blue = (0, 0, 255)

Seems to handle the situation OK.

Bill
___
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] constant/enum type in stdlib

2010-11-23 Thread Guido van Rossum
On Tue, Nov 23, 2010 at 10:06 AM, Antoine Pitrou solip...@pitrou.net wrote:
 Le mardi 23 novembre 2010 à 12:57 -0500, Fred Drake a écrit :
 On Tue, Nov 23, 2010 at 12:37 PM, Antoine Pitrou solip...@pitrou.net wrote:
  Enumerations aren't a type at all (they have no distinguishing
  property).

 In any given language, this may be true, or not.  Whether they should
 be distinct in Python is core to the current discussion.

 I meant type in the structural sense (hence the parenthesis). enums
 are just auto-generated constants. Since Python makes it trivial to
 generate sequential integers, there's no need for a specific enum
 construct.

 Now you may argue that enums should be strongly-typed, but that would be
 a bit backwards given Python's preference for duck-typing.

Please take a step back.

The best example of the utility of enums even for Python is bool. I
resisted this for the longest time but people kept asking for it. Some
properties of bool:

(a) bool is a (final) subclass of int, and an int is acceptable in a
pinch where a bool is expected
(b) bool values are guaranteed unique -- there is only one instance
with value True, and only one with value False
(c) bool values have a str() and repr() that shows their name instead
of their value (but not their class -- that's rarely an issue, and
makes the output more compact)

I think it makes sense to add a way to the stdlib to add other types
like bool. I think (c) is probably the most important feature,
followed by (a) -- except the *final* part: I want to subclass enums.
(b) is probably easy to do but I don't think it matters that much in
practice.

 From a backward-compatibility perspective, what makes sense depends on
 whether they're used to implement existing constants (socket.AF_INET,
 etc.) or if they reserved for new features only.

 It's not only backwards compatibility. New features relying on C APIs
 have to be able to map constants to the integers used in the C library.
 It would be much better if this were done naturally rather than through
 explicit conversion maps.

I'm not sure what you mean here. Can you give an example of what you
mean? I agree that it should be possible to make pretty much any
constant in the OS modules enums -- even if the values vary across
platforms.

 (this really means subclassing int, if we don't want to complicate
 C-level code)

Right.

FWIW I don't think I'm particular about the exact API to construct a
new enum type in Python code; I think in most cases explicitly
assigning values is fine. Often the values are constrained by
something external anyway; it should be easy to dynamically set the
values of a particular enum type (even add new values after the fact).
There might also be enums with the same value (even though the mapping
from int to enum will then have to pick one).

I expect that the API to convert between enums and bare ints should be
i = int(e) and e = enumclass(i). It would be nice if s = str(e) and
e = enumclass(s) would work too.

-- 
--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] constant/enum type in stdlib

2010-11-23 Thread Barry Warsaw
On Nov 23, 2010, at 12:57 PM, Fred Drake wrote:

From a backward-compatibility perspective, what makes sense depends on
whether they're used to implement existing constants (socket.AF_INET,
etc.) or if they reserved for new features only.

As is usually the case, there's little reason to change existing working code.
Enums can be used whenever a module or API is updated.

-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] constant/enum type in stdlib

2010-11-23 Thread Barry Warsaw
On Nov 23, 2010, at 05:02 PM, Michael Foord wrote:

 * Enums are not subclassed from ints or strs.  They are a distinct data type
that can be converted to and from ints and strs.  EIBTI.

But if we are to use it *in* the standard library (as opposed to merely
adding a module *to* the standard library) there are backwards compatibility
concerns. Where modules are already using integers for constants then
integers still need to work.

Is int(enum_value) enough, or must the enum value actually *be* an int?

One easy way to achieve this is to subclass integer. If we don't do that
(assuming we decide that putting a solution in the standard library is
appropriate) then we'll have to evaluate what we mean by backwards
compatible. If the modules that use the constants aren't to change then
comparing equal to the underlying value is the minimum (so that the original
value can still be used in place of the new named constant). Not sure if
you'd be happy to make that change in flufl.enum.

I'm not sure either.  In flufl.enum enum_class(i) also works as expected.

 * The typical way to create them is through a simple, but explicit class
definition.  I personally like being explicit about the item values, and
the assignments are required to make the metaclass work properly, but
Michael's convenience patch is totally appropriate for cases where you
don't care, or you want a one-liner.

If make_enum was to take a set of values to use (as Antoine suggested) I
don't see what's un-explicit about it.

When I saw your patch I immediately thought that I could add a default
argument that was something like `int_iter`, i.e. an iterator of integers for
the values in the string.  I suspect YAGNI, which is why I didn't just add it,
but I'm not totally opposed to it.

-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] constant/enum type in stdlib

2010-11-23 Thread Barry Warsaw
On Nov 23, 2010, at 11:52 AM, P.J. Eby wrote:

This reminds me: a stdlib enum should support proper pickling and copying;
i.e.:

assert SomeEnum.anEnum is pickle.loads(pickle.dumps(SomeEnum.anEnum))

This could probably be implemented by adding something like:

def __reduce__(self):
return getattr, (self._class, self._enumname)

in the EnumValue class.

Excellent idea, thanks.  Added to flufl.enum in r38.  However, only enums
created with the class syntax can be pickled though.

Cheers,
-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] constant/enum type in stdlib

2010-11-23 Thread Guido van Rossum
On Tue, Nov 23, 2010 at 11:47 AM, Barry Warsaw ba...@python.org wrote:
 On Nov 23, 2010, at 05:02 PM, Michael Foord wrote:

 * Enums are not subclassed from ints or strs.  They are a distinct data type
    that can be converted to and from ints and strs.  EIBTI.

But if we are to use it *in* the standard library (as opposed to merely
adding a module *to* the standard library) there are backwards compatibility
concerns. Where modules are already using integers for constants then
integers still need to work.

 Is int(enum_value) enough, or must the enum value actually *be* an int?

I vote for *be*, following bool's example.

One easy way to achieve this is to subclass integer. If we don't do that
(assuming we decide that putting a solution in the standard library is
appropriate) then we'll have to evaluate what we mean by backwards
compatible. If the modules that use the constants aren't to change then
comparing equal to the underlying value is the minimum (so that the original
value can still be used in place of the new named constant). Not sure if
you'd be happy to make that change in flufl.enum.

 I'm not sure either.  In flufl.enum enum_class(i) also works as expected.

 * The typical way to create them is through a simple, but explicit class
    definition.  I personally like being explicit about the item values, and
    the assignments are required to make the metaclass work properly, but
    Michael's convenience patch is totally appropriate for cases where you
    don't care, or you want a one-liner.

If make_enum was to take a set of values to use (as Antoine suggested) I
don't see what's un-explicit about it.

 When I saw your patch I immediately thought that I could add a default
 argument that was something like `int_iter`, i.e. an iterator of integers for
 the values in the string.  I suspect YAGNI, which is why I didn't just add it,
 but I'm not totally opposed to it.

 -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/guido%40python.org





-- 
--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] constant/enum type in stdlib

2010-11-23 Thread Glenn Linderman

On 11/23/2010 11:34 AM, Guido van Rossum wrote:

The best example of the utility of enums even for Python is bool. I
resisted this for the longest time but people kept asking for it. Some
properties of bool:

(a) bool is a (final) subclass of int, and an int is acceptable in a
pinch where a bool is expected
(b) bool values are guaranteed unique -- there is only one instance
with value True, and only one with value False
(c) bool values have a str() and repr() that shows their name instead
of their value (but not their class -- that's rarely an issue, and
makes the output more compact)

I think it makes sense to add a way to the stdlib to add other types
like bool. I think (c) is probably the most important feature,
followed by (a) -- except the *final* part: I want to subclass enums.
(b) is probably easy to do but I don't think it matters that much in
practice.


I was concerned about uniqueness constraints some were touting.  While 
that can be a useful property for some enumerations, it can also be 
convenient for other enumerations to have multiple names map to the same 
value.


Bool seems appropriately not extensible to additional values.  While 
there are tri-valued (and other) logic systems, they deserve a separate 
namespace.


Bool seems to be an example, then of a set of distingushed names, with 
values associated to the names, and is restricted to [two] [unique] 
integer values.  C/C++/C# enum is somewhat like that, and is also 
restricted to integer values [not necessarily unique].  I wonder if a 
set of distinguished names need to be restricted to integer values to be 
useful, although I have no doubt that distinguished names with integer 
values are useful.  Someone used an example of color names class having 
RGB tuple values, which is a counter example to a restriction to 
integers.  I can think of others as well.


Perhaps a set of distinguished names, with values associated to the 
names is really a dict, with the unique names restricted to Python 
identifier syntax (to be useful), and the values unrestricted. The type 
of the named value, and the value of the named value, seem not to need 
to be restricted.


But the implementations

Bool = dict('False': 0, 'True': 1)

or alternately

class Bool():
self.False = 0
self.True = 1

is missing a couple characteristics of Python's present bool: the names 
are not special, and the values are not immutable.  Perhaps games could 
be played to make the second implementation effectively immutable.


So I think the real trick of the enum (or a generalized distinguished 
names) is in the naming.  A technique to import the keys that are legal 
Python identifiers from a dict into a namespace, and retain henceforth 
immutable values for those names would permit the syntactical usage that 
people are accustomed to from the C/C++/C# enum, but with extended 
ranges and types of values, and it seems Bool could be mostly 
reimplemented via that technique.


What is still missing?  The debugging help: the values, once imported, 
should not become just values of their type, but rather a new type of 
value, that has an associated name (and type, I think).  Whatever magic 
is worked under the covers to make sure that there is just one True and 
just one False, so that they can be distinguished from the values 1 and 
0, and so reported, should also be applied to these values.


So there need not be new syntax for creating the name/value pairs; just 
use dict.  The only new API would be the code that imports the dict 
into the local namespace.


Note that other scoped definitions of True and False are not possible 
today because True and False are keywords.  It would be inappropriate to 
define these distinguished names as all being keywords, so it seems like 
one could still override the names, even once defined, but such 
overridden names would lose their special value that makes them a 
distinguished name.
___
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] constant/enum type in stdlib

2010-11-23 Thread Antoine Pitrou
Le mardi 23 novembre 2010 à 11:34 -0800, Guido van Rossum a écrit :
  From a backward-compatibility perspective, what makes sense depends on
  whether they're used to implement existing constants (socket.AF_INET,
  etc.) or if they reserved for new features only.
 
  It's not only backwards compatibility. New features relying on C APIs
  have to be able to map constants to the integers used in the C library.
  It would be much better if this were done naturally rather than through
  explicit conversion maps.
 
 I'm not sure what you mean here. Can you give an example of what you
 mean? I agree that it should be possible to make pretty much any
 constant in the OS modules enums -- even if the values vary across
 platforms.

I mean that PyArg_ParseTuple should continue to be pratical even if e.g.
os.SEEK_SET and friends become named constants.  It implies that the
various format codes such as i, l, etc. are still usable with those
constants. Hence:

  (this really means subclassing int, if we don't want to complicate
  C-level code)
 
 Right.

:-)

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] constant/enum type in stdlib

2010-11-23 Thread Ron Adam



On 11/23/2010 12:07 PM, Antoine Pitrou wrote:

Le mardi 23 novembre 2010 à 12:50 -0500, Isaac Morland a écrit :

Each enumeration is a type (well, OK, not in every language, presumably,
but certainly in many languages).  The word basic is more important than
types in my sentence - the point is that an enumeration capability is a
very common one in a type system, and is very general, not specific to any
particular application.


Python already has an enumeration capability. It's called range().
There's nothing else that C enums have. AFAICT, neither do enums in
other mainstream languages (assuming they even exist; I don't remember
Perl, PHP or Javascript having anything like that, but perhaps I'm
mistaken).



Aren't we forgetting enumerate?

 colors = 'BLACK BROWN RED ORANGE YELLOW GREEN BLUE VIOLET GREY WHITE'

 dict(e for e in enumerate(colors.split()))
{0: 'BLACK', 1: 'BROWN', 2: 'RED', 3: 'ORANGE', 4: 'YELLOW', 5: 'GREEN', 6: 
'BLUE', 7: 'VIOLET', 8: 'GREY', 9: 'WHITE'}


 dict((f, n) for (n, f) in enumerate(colors.split()))
{'BLUE': 6, 'BROWN': 1, 'GREY': 8, 'YELLOW': 4, 'GREEN': 5, 'VIOLET': 7, 
'ORANGE': 3, 'BLACK': 0, 'WHITE': 9, 'RED': 2}



Most other languages that use numbered constants number them by base n^2.

 [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]


Binary flags have the advantage of saving memory because you can assign 
more than one to a single integer.  Another advantage is other languages 
use them so it can make it easier interface with them.   There also may be 
some performance advantages as well since you can test for multiple flags 
with a single comparison.


Sets of strings can also work when you don't need to associate a numeric 
value to the constant.  ie... the constant is the value.  In this case the 
set supplies the api.


Cheers,
  Ron

___
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] constant/enum type in stdlib

2010-11-23 Thread Glyph Lefkowitz

On Nov 23, 2010, at 10:37 AM, ben.cottr...@nominum.com wrote:

 I'd prefer not to think of the number of times I've made the following 
 mistake:
 
 s = socket.socket(socket.SOCK_DGRAM, socket.AF_INET)

If it's any consolation, it's fewer than the number of times I have :).

(More fun, actually, is where you pass a file descriptor to the wrong argument 
of 'fromfd'...)

___
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] constant/enum type in stdlib

2010-11-23 Thread Steven D'Aprano

Antoine Pitrou wrote:

Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST',   
   values=range(1, 3))


Again, auto-enumeration is useless since it's trivial to achieve
explicitly.


That doesn't make auto-enumeration useless. Unnecessary, perhaps, but 
not useless.


But even then it's only unnecessary if the number of constants are small 
enough that you can see how many there are without counting 
(essentially, 4 or fewer). When you have more, it becomes error-prone 
and a nuisance to have to count them by hand:


Constants = make_constants(
'Constants',
'ST_MODE ST_INO ST_DEV ST_NLINK ST_UID ST_GID' \
'ST_SIZE ST_ATIME ST_MTIME ST_CTIME',
values=range(10)
)


--
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] constant/enum type in stdlib

2010-11-23 Thread Glyph Lefkowitz

On Nov 23, 2010, at 10:01 AM, Antoine Pitrou wrote:

 Well, it is easy to assign range(N) to a tuple of names when desired. I
 don't think an automatically-enumerating constant generator is needed.

I don't think that numerical enumerations are the only kind of constants we're 
talking about.  Others have already mentioned strings.  Also, see 
http://tm.tl/4671 for some other use-cases.  Since this isn't coming to 2.x, 
we're probably going to do our own thing anyway (unless it turns out that 
flufl.enum is so great that we want to add another dependency...) but I'm 
hoping that the outcome of this discussion will point to something we can be 
compatible with.

___
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] constant/enum type in stdlib

2010-11-23 Thread Antoine Pitrou
Le mardi 23 novembre 2010 à 16:10 -0500, Glyph Lefkowitz a écrit :
 
 On Nov 23, 2010, at 10:01 AM, Antoine Pitrou wrote:
 
  Well, it is easy to assign range(N) to a tuple of names when
  desired. I
  don't think an automatically-enumerating constant generator is
  needed.
 
 I don't think that numerical enumerations are the only kind of
 constants we're talking about.  Others have already mentioned strings.
 Also, see http://tm.tl/4671 for some other use-cases.  Since this
 isn't coming to 2.x, we're probably going to do our own thing anyway
 (unless it turns out that flufl.enum is so great that we want to add
 another dependency...) but I'm hoping that the outcome of this
 discussion will point to something we can be compatible with.

I think that asking for too many features would get in the way, and also
make the API quite un-Pythonic. If you want your values to be e.g.
OR'able, just choose your values wisely ;)

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] constant/enum type in stdlib

2010-11-23 Thread Ron Adam

Oops..  x**2 should have been 2**x below.


On 11/23/2010 03:03 PM, Ron Adam wrote:



On 11/23/2010 12:07 PM, Antoine Pitrou wrote:

Le mardi 23 novembre 2010 à 12:50 -0500, Isaac Morland a écrit :

Each enumeration is a type (well, OK, not in every language, presumably,
but certainly in many languages). The word basic is more important than
types in my sentence - the point is that an enumeration capability is a
very common one in a type system, and is very general, not specific to any
particular application.


Python already has an enumeration capability. It's called range().
There's nothing else that C enums have. AFAICT, neither do enums in
other mainstream languages (assuming they even exist; I don't remember
Perl, PHP or Javascript having anything like that, but perhaps I'm
mistaken).



Aren't we forgetting enumerate?

  colors = 'BLACK BROWN RED ORANGE YELLOW GREEN BLUE VIOLET GREY WHITE'

  dict(e for e in enumerate(colors.split()))
{0: 'BLACK', 1: 'BROWN', 2: 'RED', 3: 'ORANGE', 4: 'YELLOW', 5: 'GREEN', 6:
'BLUE', 7: 'VIOLET', 8: 'GREY', 9: 'WHITE'}

  dict((f, n) for (n, f) in enumerate(colors.split()))
{'BLUE': 6, 'BROWN': 1, 'GREY': 8, 'YELLOW': 4, 'GREEN': 5, 'VIOLET': 7,
'ORANGE': 3, 'BLACK': 0, 'WHITE': 9, 'RED': 2}


Most other languages that use numbered constants number them by base n^2.

  [x**2 for x in range(10)]
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]



 [2**x for x in range(10)]
[1, 2, 4, 8, 16, 32, 64, 128, 256, 512]



Binary flags have the advantage of saving memory because you can assign
more than one to a single integer. Another advantage is other languages use
them so it can make it easier interface with them. There also may be some
performance advantages as well since you can test for multiple flags with a
single comparison.

Sets of strings can also work when you don't need to associate a numeric
value to the constant. ie... the constant is the value. In this case the
set supplies the api.

Cheers,
Ron

___
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/python-python-dev%40m.gmane.org



___
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] constant/enum type in stdlib

2010-11-23 Thread Steven D'Aprano

Antoine Pitrou wrote:


Python already has an enumeration capability. It's called range().
There's nothing else that C enums have. AFAICT, neither do enums in
other mainstream languages (assuming they even exist; I don't remember
Perl, PHP or Javascript having anything like that, but perhaps I'm
mistaken).



In Pascal, enumerations are a type, and the value of the named values 
are an implementation detail. E.g. one would define an enumerated type:


type
  flavour = (sweet, salty, sour, bitter, umame);
var
  x: flavour;

and then you would write something like:

x := sour;

Notice that the constants sweet etc. aren't explicitly predefined, since 
they're purely internal details and the compiler is allowed to number 
them any way it likes. In Python, we would need stronger guarantees 
about the values chosen, so that they could be exposed to external 
modules, pickled, etc.


But that doesn't mean we should be forced to specify the values ourselves.


--
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] constant/enum type in stdlib

2010-11-23 Thread Greg Ewing

Antoine Pitrou wrote:


I don't understand why people insist on calling that an enum. enum is
a C legacy and it doesn't bring anything useful as I can tell.


The usefulness is that they can have a str() or repr() that
displays the name of the value instead of an integer.

The bool type was added for much the same reason -- otherwise
we would simply have gotten builtin names False = 0 and
True = 1.

--
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] constant/enum type in stdlib

2010-11-23 Thread Greg Ewing

Antoine Pitrou wrote:


Well, it's been inherited by C-like languages, no doubt. Like braces and
semicolumns :)


The idea isn't confined to the C family. Pascal and many of the
languages inspired by it also have enumerated types.

--
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] constant/enum type in stdlib

2010-11-23 Thread Isaac Morland

On Tue, 23 Nov 2010, Bill Janssen wrote:


The main purpose of that is to be able to catch type mismatches with
static typing, though.  Seems kind of pointless for Python.


The concept can work dynamically.  In fact, the flufl.enum package which 
has been discussed here makes each enumeration into a separate class so 
many of the advantages of catching type mismatches are obtained.



Hey, how about this syntax:

enum Colors:
red = 0
green = 10
blue


Why not

 class Color:
red = (255, 0, 0)
green = (0, 255, 0)
blue = (0, 0, 255)

Seems to handle the situation OK.


Yes, this looks almost exactly like flufl.enum syntax.  In any case my 
suggestion of a new keyword was not meant to be taken seriously.  If I 
ever think I have a good reason to suggest a new keyword I'll sleep on it, 
take a vacation, and then if I still think a new keyword is justified I 
will specifically disclaim any possibility of the suggestion being a joke.


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] constant/enum type in stdlib

2010-11-23 Thread Greg Ewing

Antoine Pitrou wrote:


I think that asking for too many features would get in the way, and also
make the API quite un-Pythonic. If you want your values to be e.g.
OR'able, just choose your values wisely ;)


On the other hand it could be useful to have an easy way to
request power-of-2 value assignment, seeing as it's another
common pattern.

--
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] constant/enum type in stdlib

2010-11-23 Thread Greg Ewing

Bill Janssen wrote:


The main purpose of that is to be able to catch type mismatches with
static typing, though.  Seems kind of pointless for Python.


But catching type mismatches with dynamic typing doesn't
seem pointless for Python. There's nothing static about
the proposals being made here that I can see.


Why not

  class Color:
 red = (255, 0, 0)
 green = (0, 255, 0)
 blue = (0, 0, 255)


If all you want is a bunch of named constants, that's fine.
But the facilities being discussed here are designed to give
you other things as well, such as

  c = Color.red
  print(c)

printing red rather than (255, 0, 0).

--
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] constant/enum type in stdlib

2010-11-23 Thread Greg Ewing

Antoine Pitrou wrote:

Constants = make_constants('Constants', 'SOME_CONST OTHER_CONST',   
   values=range(1, 3))


Again, auto-enumeration is useless since it's trivial to achieve
explicitly.


But seeing as it's going to be a common thing to do, why not
make it the default?

When defining an enum, often you don't *care* what the
underlying values are, so assigning sequential natural numbers
is as good a default as any.

In fact, with the Pascal concept of an enumerated type you
don't get any choice in the matter. It's only in the C family
that you get this bastardised conflation of enumerations with
arbitrary named constants...

--
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] constant/enum type in stdlib

2010-11-23 Thread Greg Ewing

Isaac Morland wrote:
In any case my 
suggestion of a new keyword was not meant to be taken seriously.


I don't think it need be taken entirely as a joke, either.
All the proposed patterns for creating enums that I've seen
end up leaving something to be desired. They violate DRY
by requiring you to write the class name twice, or they
make you write the names of the values in quotes, or some
other minor ugliness.

While it may be possible to work around these things with
sufficient levels of metaclass hackery and black magic, at
some point one has to consider whether new syntax might
be the least worst option.

--
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] constant/enum type in stdlib

2010-11-23 Thread Michael Foord

On 23/11/2010 21:15, Antoine Pitrou wrote:

Le mardi 23 novembre 2010 à 16:10 -0500, Glyph Lefkowitz a écrit :

On Nov 23, 2010, at 10:01 AM, Antoine Pitrou wrote:


Well, it is easy to assign range(N) to a tuple of names when
desired. I
don't think an automatically-enumerating constant generator is
needed.

I don't think that numerical enumerations are the only kind of
constants we're talking about.  Others have already mentioned strings.
Also, seehttp://tm.tl/4671  for some other use-cases.  Since this
isn't coming to 2.x, we're probably going to do our own thing anyway
(unless it turns out that flufl.enum is so great that we want to add
another dependency...) but I'm hoping that the outcome of this
discussion will point to something we can be compatible with.

I think that asking for too many features would get in the way, and also
make the API quite un-Pythonic. If you want your values to be e.g.
OR'able, just choose your values wisely ;)



Well, the point of an OR'able flag is that the result shows the OR'd 
values in the repr. Raymond suggests using a set of strings where you 
need flag constants. For new apis (so no backwards compatibility 
constraints) where you don't need to use integers (i.e. not wrapping a C 
library) that's a great suggestion:


flags = {'FOO', 'BAR'}

Michael

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/fuzzyman%40voidspace.org.uk



--

http://www.voidspace.org.uk/

READ CAREFULLY. By accepting and reading this email you agree,
on behalf of your employer, to release me from all obligations
and waivers arising from any and all NON-NEGOTIATED agreements,
licenses, terms-of-service, shrinkwrap, clickwrap, browsewrap,
confidentiality, non-disclosure, non-compete and acceptable use
policies (”BOGUS AGREEMENTS”) that I have entered into with your
employer, its partners, licensors, agents and assigns, in
perpetuity, without prejudice to my ongoing rights and privileges.
You further represent that you have the authority to release me
from any BOGUS AGREEMENTS on behalf of your employer.

___
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] constant/enum type in stdlib

2010-11-23 Thread Raymond Hettinger

On Nov 23, 2010, at 3:41 PM, Greg Ewing wrote:

 While it may be possible to work around these things with
 sufficient levels of metaclass hackery and black magic, at
 some point one has to consider whether new syntax might
 be the least worst option.

The least worst option is to do nothing at all.
That's better than creating a new little monster with its 
own nuances and limitations.

We've gotten by well for almost two decades without
this particular static language feature creeping into Python.

For the most part, strings work well enough (see
decimal.ROUND_UP for example).  They are self-documenting
and work well with the rest of the language.

When a cluster of names cries out for its own namespace,
the usual technique is to put the names in class (see the examples
in the namedtuple docs for a way to make this a one-liner) 
or in a module (see opcode.py for example).

For xor'able and or'able flags, sets of strings work well:
   flags = {'runnable', 'callable'}
   flags |= {'runnable', 'kissable'}
   if 'callable' in flags:
  . . .

We have a hard enough time getting people to not program
Java in Python.  IMO, adding a new enumeration type
would make this situation worse.  Also, it adds weight to
the language -- Python is not in needs of yet another fundamental
construct.


Raymond


P.S.  I do recognize that lots of people have written their own
versions of Enum(), but I think they do it either out of habits formed
from statically compiled languages that lack all of our namespace
mechanisms or they do it because it is easy and fun to write
(just like people seem to enjoy writing flatten() recipes more
than they like actually using them).

One other thought:  With Py3.x, the language had its one chance
to get smaller.  Old-style classes were tossed, some built-ins 
vanished, and a few obsolete modules got nuked.  It would be
easy to have a let's add thingie x fest and lose those benefits.
There are many devs who find that the language does not 
fit-in-their-heads anymore, so considerable restraint needs to
be exercised before adding a new language feature that would
soon permeate everyone's code base and add yet another thing
that infrequent users have to learn before being able to read 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] constant/enum type in stdlib

2010-11-23 Thread Fred Drake
On Tue, Nov 23, 2010 at 9:35 PM, Raymond Hettinger
raymond.hettin...@gmail.com wrote:
 The least worst option is to do nothing at all.

For the standard library, I agree.

There are enough variants that are needed/desired in different
contexts, and there isn't a single clear winner.  Nor is there any
compelling reason to have a winner.

I'm generally in favor of enums (or whatever you want to call them),
and I'm in favor of importing support for the flavor you need, or just
defining constants in whatever way makes sense for your library or
application.

I don't see any problems that aren't solved by that.


  -Fred

--
Fred L. Drake, Jr.    fdrake at acm.org
A storm broke loose in my mind.  --Albert Einstein
___
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