[Python-Dev] AutoNumber Enum

2016-06-29 Thread Ethan Furman
There is a several-month-old request to add aenum's [1] AutoNumberEnum 
to the stdlib [2].


The requester and two of the three developers of Enum are in favor (the 
third hasn't chimed in yet).


This new addition would enable the following:

  from Enum import AutoNumberEnum

  class Color(AutoNumberEnum):
  # auto-number magic is on
  Red
  Green
  Blue
  Cyan
  # magic turns off when non-enum is defined

  def is_primary(self):
  # typos in methods, etc, will raise
  return self in (self.Red, self.Grene, self.Blue)

  # typos after the initial definition stanza will raise
  BlueGreen = Blue + Grene

There is, of course, the risk of typos during the initial member 
definition stanza, but since this magic only happens when the user 
explicitly asks for it (AutoNumberEnum), I think it is acceptable.


The `start` parameter is still available, and assigning a number is 
supported (subsequent numbers will (re)start from the assigned number).


Thoughts?  Opinions?  Flames?

--
~Ethan~



[1] https://pypi.python.org/pypi/aenum
[2] http://bugs.python.org/issue26988
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Brett Cannon
On Wed, 29 Jun 2016 at 10:41 Ethan Furman  wrote:

> There is a several-month-old request to add aenum's [1] AutoNumberEnum
> to the stdlib [2].
>
> The requester and two of the three developers of Enum are in favor (the
> third hasn't chimed in yet).
>
> This new addition would enable the following:
>
>from Enum import AutoNumberEnum
>
>class Color(AutoNumberEnum):
># auto-number magic is on
>Red
>Green
>Blue
>Cyan
># magic turns off when non-enum is defined
>
>def is_primary(self):
># typos in methods, etc, will raise
>return self in (self.Red, self.Grene, self.Blue)
>
># typos after the initial definition stanza will raise
>BlueGreen = Blue + Grene
>
> There is, of course, the risk of typos during the initial member
> definition stanza, but since this magic only happens when the user
> explicitly asks for it (AutoNumberEnum), I think it is acceptable.
>
> The `start` parameter is still available, and assigning a number is
> supported (subsequent numbers will (re)start from the assigned number).
>
> Thoughts?  Opinions?  Flames?
>

Is it going to subclass Enum or IntEnum? Personally I would be quite happy
to never have to specify a value for enums ever again, but only if they
subclass Enum (since IntEnum is for compatibility with C stuff where a
specific value is needed I don't think users need to mess that up by having
the automatic numbering not work how they would expect).
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


[Python-Dev] Issue 27417: Call CoInitializeEx on startup

2016-06-29 Thread Steve Dower
I know this is of fairly limited interest, so this is just advertising 
http://bugs.python.org/issue27417 where I propose enabling COM by 
default on startup.


If you are someone who knows what CoInitializeEx is or why you may want 
to call it, I'm interested in your feedback/concerns. Come and post on 
http://bugs.python.org/issue27417.


Cheers,
Steve
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Guido van Rossum
And how would you implement that without support from the compiler?
Does it use a hook that catches the NameError?

On Wed, Jun 29, 2016 at 11:15 AM, Brett Cannon  wrote:
>
>
> On Wed, 29 Jun 2016 at 10:41 Ethan Furman  wrote:
>>
>> There is a several-month-old request to add aenum's [1] AutoNumberEnum
>> to the stdlib [2].
>>
>> The requester and two of the three developers of Enum are in favor (the
>> third hasn't chimed in yet).
>>
>> This new addition would enable the following:
>>
>>from Enum import AutoNumberEnum
>>
>>class Color(AutoNumberEnum):
>># auto-number magic is on
>>Red
>>Green
>>Blue
>>Cyan
>># magic turns off when non-enum is defined
>>
>>def is_primary(self):
>># typos in methods, etc, will raise
>>return self in (self.Red, self.Grene, self.Blue)
>>
>># typos after the initial definition stanza will raise
>>BlueGreen = Blue + Grene
>>
>> There is, of course, the risk of typos during the initial member
>> definition stanza, but since this magic only happens when the user
>> explicitly asks for it (AutoNumberEnum), I think it is acceptable.
>>
>> The `start` parameter is still available, and assigning a number is
>> supported (subsequent numbers will (re)start from the assigned number).
>>
>> Thoughts?  Opinions?  Flames?
>
>
> Is it going to subclass Enum or IntEnum? Personally I would be quite happy
> to never have to specify a value for enums ever again, but only if they
> subclass Enum (since IntEnum is for compatibility with C stuff where a
> specific value is needed I don't think users need to mess that up by having
> the automatic numbering not work how they would expect).
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/guido%40python.org
>



-- 
--Guido van Rossum (python.org/~guido)
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Ethan Furman

On 06/29/2016 11:15 AM, Brett Cannon wrote:

On Wed, 29 Jun 2016 at 10:41 Ethan Furman wrote:



There is a several-month-old request to add aenum's [1] AutoNumberEnum
to the stdlib [2].

The requester and two of the three developers of Enum are in favor (the
third hasn't chimed in yet).

This new addition would enable the following:

from Enum import AutoNumberEnum

class Color(AutoNumberEnum):
# auto-number magic is on
Red
Green
Blue
Cyan
# magic turns off when non-enum is defined


Is it going to subclass Enum or IntEnum?


Enum.


Personally I would be quite
happy to never have to specify a value for enums ever again, but only if
they subclass Enum (since IntEnum is for compatibility with C stuff
where a specific value is needed I don't think users need to mess that
up by having the automatic numbering not work how they would expect).


If a user really wants that they can, of course, specify both 
AutoNuberEnum and IntEnum in the class header.


--
~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Ethan Furman

On 06/29/2016 12:11 PM, Guido van Rossum wrote:


And how would you implement that without support from the compiler?
Does it use a hook that catches the NameError?


It's built into the _EnumDict class dictionary used during class creation.

Current (edited) code from the aenum package that implements this:

class _EnumDict(dict):
"""Track enum member order and ensure member names are not reused.

EnumMeta will use the names found in self._member_names as the
enumeration member names.
"""
def __init__(self, locked=True, start=1, multivalue=False):
super(_EnumDict, self).__init__()
# list of enum members
self._member_names = []
# starting value for AutoNumber
self._value = start - 1
# when the magic turns off
self._locked = locked
...

def __getitem__(self, key):
if (
self._locked
or key in self
or _is_sunder(key)
or _is_dunder(key)
):
return super(_EnumDict, self).__getitem__(key)
try:
# try to generate the next value
value = self._value + 1
self.__setitem__(key, value)
return value
except:
# couldn't work the magic, report error
raise KeyError('%s not found' % key)

def __setitem__(self, key, value):
"""Changes anything not sundured, dundered, nor a descriptor.
Single underscore (sunder) names are reserved.
"""
if _is_sunder(key):
raise ValueError('_names_ are reserved for future Enum use')
elif _is_dunder(key):
if key == '__order__':
key = '_order_'
if _is_descriptor(value):
self._locked = True
elif key in self._member_names:
# descriptor overwriting an enum?
raise TypeError('Attempted to reuse name: %r' % key)
elif not _is_descriptor(value):
if key in self:
# enum overwriting a descriptor?
raise TypeError('%s already defined as: %r' % ...
self._member_names.append(key)
if not self._locked:
if isinstance(value, int):
self._value = value
else:
count = self._value + 1
self._value = count
value = count, value
else:
# not a new member, turn off the autoassign magic
self._locked = True
super(_EnumDict, self).__setitem__(key, value)

Disclaimer:  some errors may have crept in as I deleted unrelated 
content.  For the full code check out the _EnumDict class in the aenum 
package.


--
~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Ivan Levkivskyi
It looks like the values in AutoNumberEnum are consecutive integers
1,2,3,...
Have you considered an option (keyword argument) to change this to powers
of two 1,2,4,8,...?

--
Ivan



On 29 June 2016 at 21:23, Ethan Furman  wrote:

> On 06/29/2016 12:11 PM, Guido van Rossum wrote:
>
> And how would you implement that without support from the compiler?
>> Does it use a hook that catches the NameError?
>>
>
> It's built into the _EnumDict class dictionary used during class creation.
>
> Current (edited) code from the aenum package that implements this:
>
> class _EnumDict(dict):
> """Track enum member order and ensure member names are not reused.
>
> EnumMeta will use the names found in self._member_names as the
> enumeration member names.
> """
> def __init__(self, locked=True, start=1, multivalue=False):
> super(_EnumDict, self).__init__()
> # list of enum members
> self._member_names = []
> # starting value for AutoNumber
> self._value = start - 1
> # when the magic turns off
> self._locked = locked
> ...
>
> def __getitem__(self, key):
> if (
> self._locked
> or key in self
> or _is_sunder(key)
> or _is_dunder(key)
> ):
> return super(_EnumDict, self).__getitem__(key)
> try:
> # try to generate the next value
> value = self._value + 1
> self.__setitem__(key, value)
> return value
> except:
> # couldn't work the magic, report error
> raise KeyError('%s not found' % key)
>
> def __setitem__(self, key, value):
> """Changes anything not sundured, dundered, nor a descriptor.
> Single underscore (sunder) names are reserved.
> """
> if _is_sunder(key):
> raise ValueError('_names_ are reserved for future Enum use')
> elif _is_dunder(key):
> if key == '__order__':
> key = '_order_'
> if _is_descriptor(value):
> self._locked = True
> elif key in self._member_names:
> # descriptor overwriting an enum?
> raise TypeError('Attempted to reuse name: %r' % key)
> elif not _is_descriptor(value):
> if key in self:
> # enum overwriting a descriptor?
> raise TypeError('%s already defined as: %r' % ...
> self._member_names.append(key)
> if not self._locked:
> if isinstance(value, int):
> self._value = value
> else:
> count = self._value + 1
> self._value = count
> value = count, value
> else:
> # not a new member, turn off the autoassign magic
> self._locked = True
> super(_EnumDict, self).__setitem__(key, value)
>
> Disclaimer:  some errors may have crept in as I deleted unrelated
> content.  For the full code check out the _EnumDict class in the aenum
> package.
>
> --
> ~Ethan~
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/levkivskyi%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Ethan Furman

On 06/29/2016 01:01 PM, Ivan Levkivskyi wrote:


It looks like the values in AutoNumberEnum are consecutive integers
1,2,3,...
Have you considered an option (keyword argument) to change this to
powers of two 1,2,4,8,...?


There is another issue relating to bitwise enums that deals with that. 
It is not part of this proposal.


--
~Ethan~
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Larry Hastings

On 06/29/2016 01:01 PM, Ivan Levkivskyi wrote:
It looks like the values in AutoNumberEnum are consecutive integers 
1,2,3,...
Have you considered an option (keyword argument) to change this to 
powers of two 1,2,4,8,...?


Why would you want that?  I remind you that this descends from Enum, so 
its members won't be directly interchangeable with ints. Presumably you 
want a bitfield enum, and those should descend from IntEnum.


TBH I'd prefer the AutoNumberEnum *not* have this feature; it's already 
a little too magical for my tastes.



//arry/
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Ivan Levkivskyi
> Presumably you want a bitfield enum, and those should descend from
IntEnum.

Yes, and probably having an AutoNumberIntEnum would indeed be too much
magic in one place.
Anyway, it is easy to implement bitfield IntEnum without magic.

To be clear, I like the Ethan's original proposal.

--
Ivan



> TBH I'd prefer the AutoNumberEnum *not* have this feature; it's already a
> little too magical for my tastes.
>
>
> */arry*
>
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/levkivskyi%40gmail.com
>
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Roberto Martínez
Why the 'start' parameter default is 1? 0 (zero) is more consistent with
other parts of the language: indexes, enumerate, range...

El mié., 29 de jun. de 2016 21:26, Ethan Furman 
escribió:

> On 06/29/2016 12:11 PM, Guido van Rossum wrote:
>
> > And how would you implement that without support from the compiler?
> > Does it use a hook that catches the NameError?
>
> It's built into the _EnumDict class dictionary used during class creation.
>
> Current (edited) code from the aenum package that implements this:
>
> class _EnumDict(dict):
>  """Track enum member order and ensure member names are not reused.
>
>  EnumMeta will use the names found in self._member_names as the
>  enumeration member names.
>  """
>  def __init__(self, locked=True, start=1, multivalue=False):
>  super(_EnumDict, self).__init__()
>  # list of enum members
>  self._member_names = []
>  # starting value for AutoNumber
>  self._value = start - 1
>  # when the magic turns off
>  self._locked = locked
>  ...
>
>  def __getitem__(self, key):
>  if (
>  self._locked
>  or key in self
>  or _is_sunder(key)
>  or _is_dunder(key)
>  ):
>  return super(_EnumDict, self).__getitem__(key)
>  try:
>  # try to generate the next value
>  value = self._value + 1
>  self.__setitem__(key, value)
>  return value
>  except:
>  # couldn't work the magic, report error
>  raise KeyError('%s not found' % key)
>
>  def __setitem__(self, key, value):
>  """Changes anything not sundured, dundered, nor a descriptor.
>  Single underscore (sunder) names are reserved.
>  """
>  if _is_sunder(key):
>  raise ValueError('_names_ are reserved for future Enum use')
>  elif _is_dunder(key):
>  if key == '__order__':
>  key = '_order_'
>  if _is_descriptor(value):
>  self._locked = True
>  elif key in self._member_names:
>  # descriptor overwriting an enum?
>  raise TypeError('Attempted to reuse name: %r' % key)
>  elif not _is_descriptor(value):
>  if key in self:
>  # enum overwriting a descriptor?
>  raise TypeError('%s already defined as: %r' % ...
>  self._member_names.append(key)
>  if not self._locked:
>  if isinstance(value, int):
>  self._value = value
>  else:
>  count = self._value + 1
>  self._value = count
>  value = count, value
>  else:
>  # not a new member, turn off the autoassign magic
>  self._locked = True
>  super(_EnumDict, self).__setitem__(key, value)
>
> Disclaimer:  some errors may have crept in as I deleted unrelated
> content.  For the full code check out the _EnumDict class in the aenum
> package.
>
> --
> ~Ethan~
> ___
> Python-Dev mailing list
> Python-Dev@python.org
> https://mail.python.org/mailman/listinfo/python-dev
> Unsubscribe:
> https://mail.python.org/mailman/options/python-dev/robertomartinezp%40gmail.com
>
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Ethan Furman

On 06/29/2016 03:40 PM, Roberto Martínez wrote:


Why the 'start' parameter default is 1? 0 (zero) is more consistent with
other parts of the language: indexes, enumerate, range...


An excerpt from [1]:


The reason for defaulting to 1 as the starting number and not 0 is that 0 is 
False in a boolean sense, but enum members all evaluate to True.


--
~Ethan~


[1] https://docs.python.org/3/library/enum.html#functional-api

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


Re: [Python-Dev] AutoNumber Enum

2016-06-29 Thread Wes Turner
It may be worth mentioning that pandas Categoricals are mutable and
zero-based:
https://pandas-docs.github.io/pandas-docs-travis/categorical.html

Serialization to SQL and CSV is (also?) lossy, though:
-
https://pandas-docs.github.io/pandas-docs-travis/categorical.html#getting-data-in-out
-
https://pandas-docs.github.io/pandas-docs-travis/io.html#io-stata-categorical
On 06/29/2016 03:40 PM, Roberto Martínez wrote:

Why the 'start' parameter default is 1? 0 (zero) is more consistent with
> other parts of the language: indexes, enumerate, range...
>

An excerpt from [1]:

The reason for defaulting to 1 as the starting number and not 0 is that 0
> is False in a boolean sense, but enum members all evaluate to True.
>

--
~Ethan~


[1] https://docs.python.org/3/library/enum.html#functional-api

___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe:
https://mail.python.org/mailman/options/python-dev/wes.turner%40gmail.com
___
Python-Dev mailing list
Python-Dev@python.org
https://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
https://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com