Re: [Python-ideas] Revisiting Immutable Mappings

2018-10-16 Thread George Leslie-Waksman
Would a frozendict require that keys and values be hashable?

It seems to me that we would need this restriction to make a reasonably
universal frozendict that is, itself, hashable. With this restriction for
the general case, is there still sufficient value for everyone that is
asking for a frozendict?

Without this restriction and without frozendict being hashable, is there
still sufficient value for everyone that is asking for a frozendict?

On Fri, Oct 12, 2018 at 7:31 AM Greg Ewing 
wrote:

> Chris Barker - NOAA Federal via Python-ideas wrote:
>
> > Or maybe come up with a new name
>
> We should call it a birdseyedict, because of this:
>
>
> http://www.vulture.com/2016/12/unearthing-a-rare-1971-monty-python-film-all-about-peas.html
>
> --
> Greg
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] slice[] to get more complex slices

2018-07-23 Thread George Leslie-Waksman
May I propose `slice.L` as in "slice literal":

```
class slice:
...
class L:
"""Slice literal.

slice.L[1:2:3, 1] -> (slice(1, 2, 3), slice(1))
"""

@classmethod
def __class_getitem__(cls, item):
return item
```

On Mon, Jul 23, 2018 at 12:02 PM Joseph Jevnik  wrote:

> I still think that 'operator.subscript' would be valuable to me for
> all of the same reasons discussed in the previous threads and issues.
> I don't understand why it was reverted without any serious discussion
> given that it was already accepted and many people find this useful.
>
> On Mon, Jul 23, 2018 at 2:38 PM, Serhiy Storchaka 
> wrote:
> > 23.07.18 18:16, Guido van Rossum пише:
> >>
> >> On Mon, Jul 23, 2018 at 3:24 AM, Jeroen Demeyer  >> > wrote:
> >>
> >> On 2018-07-23 11:58, Grégory Lielens wrote:
> >>
> >> Not sure slice[1::3] can be done
> >>
> >>
> >> It can be done. Since "slice" is a class, it would require a
> >> metaclass though.
> >>
> >>
> >> Since PEP 560 it won't need a metaclass -- it can be implemented as
> >> __class_getitem__.
> >
> >
> > Do you bless using __class_getitem__ for something other than typing?
> >
> >
> > ___
> > Python-ideas mailing list
> > Python-ideas@python.org
> > https://mail.python.org/mailman/listinfo/python-ideas
> > Code of Conduct: http://python.org/psf/codeofconduct/
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] PEP 505: None-aware operators

2018-07-19 Thread George Leslie-Waksman
I am rather fond of the idea of null-coalescing, at the very least, for
mutable default values:

def foo(a=None):
a ??= []
...

but I worry about the code messes we will run into with some of the other
options.

Woe be unto anyone forced to understand the behavior of:

thing?.attr?[key]?.subattr ?? 127

What if we added the Elvis operator "?:" for null coalescing and left the
rest for future consideration


On Wed, Jul 18, 2018 at 10:49 PM Tim Peters  wrote:

> [Steve Dower ]
>
>> ...
>
> * The "``None``-aware attribute access" operator ``?.`` evaluates the
>> complete expression if the left hand side evaluates to a value that is
>> not
>> ``None``
>>
>
> And if the LHS does evaluate to `None` ...?  I'll assume the result is
> also `None` then.
>
>
>> ...
>
>
>>  From ``inspect.py``::
>>
>>  for base in object.__bases__:
>>  for name in getattr(base, "__abstractmethods__", ()):
>>  value = getattr(object, name, None)
>>  if getattr(value, "__isabstractmethod__", False):
>>  return True
>>
>> After updating to use the ``?.`` operator (and deliberately not
>> converting to use ``any()``)::
>>
>>  for base in object.__bases__:
>>  for name in base?.__abstractmethods__ ?? ():
>>  if object?.name?.__isabstractmethod__:
>>  return True
>>
>
> I got lost on the `for` here.  The part following `in`:
>
> for name in getattr(base, "__abstractmethods__", ()):
>
> looks in `base` (regardless of whether `base` is `None`) for an attribute
> named "_abstractmethods__"..  If such an attribute exists, the value of
> the attribute is returned (`None` or not).  Else an AttributeError is
> swallowed and `()` is returned.  It's hard to see how
>
>
>  for name in base?.__abstractmethods__ ?? ():
>
> does the same.  If `base` itself is `None`, I guess it returns `()`, or
> if  `base` has an "_abstractmethods__" attribute then the value of that
> attribute is returned - unless its value is None, in which case `()` is
> again returned.  But if `base` is not `None` and the attribute does not
> exist, doesn't this raise AttributeError?  The later "Exception-aware
> operators" section seemed to explicitly reject the idea that `?.` and `?[]`
> would suppress AttributeError and/or TypeError.
>
> In short, the original getattr() didn't care at all whether `base` was
> `None`, or whether the value of its "__abstractmethods__" attribute was
> `None`, but cared a whole lot about whether that attribute exists.  I just
> can't see how the updated code matches that in any of those respects.
>
> Ignoring that and pressing on, I suffer the same kind of confusions on the
> `if` part.  What am I missing?  For example, do these operators swallow
> exceptions after all?
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Add the imath module

2018-07-13 Thread George Leslie-Waksman
Instead of `imath`, how about `math.integer` for the module name?

On Fri, Jul 13, 2018 at 9:20 AM Tim Peters  wrote:

> [Steven D'Aprano]
>>  > about 4.7 seconds to test 2**800 + 1;
>>
>> [Jeroen Demeyer]
>>
>>> In SageMath:
>>>
>>> sage: n = 2**800+1; timeit('is_prime(n)')
>>> 625 loops, best of 3: 303 µs per loop
>>>
>>> That's 4 orders of magnitude faster...
>>
>>
> [Tim]
>
>> More like 6, yes?
>>
>
> Heh - sorry about that.  A speck of dirt on my monitor made me read '303"
> as "3.03".
>
>
>>   My Python version is more like 3, but is way fast enough for most
>> things I do:
>>
>
> So my Python Miller-Rabin code (already shared) was about one order of
> magnitude slower.
>  ...
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Add dict.append and dict.extend

2018-06-04 Thread George Leslie-Waksman
Semantically, I'm not sure append and extend would be universally
understood to mean don't overwrite.

This can be accomplished with a custom subclass for your use case:

```
import collections


class OverwriteGuardedDict(collections.UserDict):
def append(self, key, value):
if key in self.data:
raise KeyError(key)
self.data[key] = value

def extend(self, other):
overlap = self.data.keys() & other.keys()
if overlap:
raise KeyError(','.join(overlap))
self.data.update(other)
```

On Mon, Jun 4, 2018 at 2:24 PM Ben Rudiak-Gould  wrote:

> I'd like to propose adding `append` and `extend` methods to dicts
> which behave like `__setitem__` and `update` respectively, except that
> they raise an exception (KeyError?) instead of overwriting preexisting
> entries.
>
> Very often I expect that the key I'm adding to a dict isn't already in
> it. If I want to verify that, I have to expand my single-line
> assignment statement to 3-5 lines (depending on whether the dict and
> key are expressions that I now need to assign to local variables). If
> I don't verify it, I may overwrite a dict entry and produce silently
> wrong output.
>
> The names `append` and `extend` make sense now that dicts are defined
> to preserve insertion order: they try to append the new entries, and
> if that can't be done because it would duplicate a key, they raise an
> exception.
>
> In case of error, `extend` should probably leave successfully appended
> entries in the dict, since that's consistent with list.extend and
> dict.update.
>
> The same methods would also be useful on sets. Unfortunately, the
> names make less sense.
>
> -- Ben
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Thoughts on "extended mapping unpacking"

2018-05-24 Thread George Leslie-Waksman
I have had plenty of instances where destructuring a mapping would have be
convenient. Relating to iterable destructuring, I would expect the syntax
to be of the form "variable: key". I also think the curly-braces make it
harder to visually parse what's going on. So I might suggest something a
little like:

objkey = object()
mydict = {'a': 1, 'b': 2, 'c': 3, 4: 5, None: 6, objkey: 7}
var1: 'a', var2: 4, var3: None, var4: objkey, **rest = mydict
assert var1 == 1
assert var2 == 5
assert var3 == 6
assert var4 == 7
assert rest == {'b': 2, 'c': 3}

On Thu, May 24, 2018 at 9:37 AM Serhiy Storchaka 
wrote:

> 24.05.18 18:46, Neil Girdhar пише:
> > p = parameters.pop('some_parameter')
> > q = parameters.pop('some_other_parameter')
> > if parameters:
> >   raise ValueError
> >
> > parameters is a Mapping subclass and I don't want to destroy it
>
> Oh, right. It works if parameters is a var-keyword parameter.
>
>  def __init__(self, some_kwarg, some_other_kwargs, **parameters):
>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Reuse "for" to express "given"

2018-05-24 Thread George Leslie-Waksman
I worry about the use of "for" because it will come up in contexts where
"for" already has other meanings. In the case of the example list
comprehension, the word "for" is being used to mean two entirely different
things in a single expression, that seems rather precarious to me.

I prefer "with" if we're looking for keywords to reuse. This feels fairly
clean to me:

[(x, y, x/y) for x in data with y = f(x) if y]

if m with m = pattern.search(data):
...

while m with m = pattern.search(remaining_data):
...

Of course, "with" is not without problems and I'm not so happy about being
able to:

with open(a) as b with a = filename:
...

--George

On Thu, May 24, 2018 at 9:33 AM Robert Vanden Eynde 
wrote:

> It was a long time ago I couldn't easily find the post but that's alright,
> you refreshed the idea :)
>
> Let's see what others think of for x =
>
> I also remembered some languages (like lua) use for x = range (5)
> interchangeably with for x in range (5) and guido said it will never make
> such a thing, for .. in being the iteration.
>
> Le jeu. 24 mai 2018 à 18:22, Alexander Belopolsky <
> alexander.belopol...@gmail.com> a écrit :
>
>>
>>
>> On Thu, May 24, 2018 at 12:04 PM Robert Vanden Eynde <
>> robertv...@gmail.com> wrote:
>>
>> > This idea was mentioned (by me) at a time yes, but wasn't written in
>> the document.
>>
>> Can you point me to a specific post?  There were so may that I must have
>> missed that one.
>>
>> > I think one of the thing was that it would make the grammar non LL1
>> because when seeing the token "for" in a list comprehension it wouldn't
>> know in advance if it's the loop or the assignment.
>>
>> I don't see how that can be a problem.  From the grammar point of view,
>> "for" in "for var = " may still be seen as introducing a "loop", but
>> when "=" is seen in place of "in", the compiler will resize that the "loop"
>> is one a single value and emit efficient code for it.  At the AST level,
>>   "for var = "  will look exactly the same as  "for var in "
>> only with an "=" instead of "in".
>>
>> > And also, it might confuse people because 'for' is for iteration.
>>
>> I think I addressed this in my previous post.  Yes, for people with a
>> C/C++ background, "for" may be too strongly associated with loops, but in
>> mathematical sense, it seems clear that "for var in a set" means iteration
>> over a set, while "for var = expression" means binding to a single value.
>>
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Argparse subparsers add required keyword

2018-03-08 Thread George Leslie-Waksman
With the stdlib argparse, subparsers can be defined and they can be marked
as required (though this is not documented) but they do not support a
"required" keyword. I think it would make everything more consistent if the
keyword existed.

This won't require any functional changes under the hood.

Right now, this works (and behaves as expected):

parser = argparse.ArgumentParser(...)
subparsers = parser.add_subparsers(...)
subparsers.required = True

but this does not:

parser = argparse.ArgumentParser(...)
subparsers = parser.add_subparsers(..., required=True)

--George
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Dataclasses, keyword args, and inheritance

2018-01-29 Thread George Leslie-Waksman
Given I started this thread from a perspective of this is a feature that I
would like because I need it, it feels a little dismissive to take attrs
not having the feature to mean "there's no reason to try to implement this."

On Mon, Jan 29, 2018 at 11:05 AM Guido van Rossum <gu...@python.org> wrote:

> I think that settles it -- there's no reason to try to implement this.
>
> On Mon, Jan 29, 2018 at 10:51 AM, George Leslie-Waksman <waks...@gmail.com
> > wrote:
>
>> attrs' seems to also not allow mandatory attributes to follow optional
>> one:
>>
>> In [14]: @attr.s
>> ...: class Baz:
>> ...: a = attr.ib(default=attr.Factory(list))
>> ...: b = attr.ib()
>> ...:
>>
>> ---
>> ValueErrorTraceback (most recent call
>> last)
>>  in ()
>> > 1 @attr.s
>>   2 class Baz:
>>   3 a = attr.ib(default=attr.Factory(list))
>>   4 b = attr.ib()
>>   5
>>
>> /Users/waksman/.pyenv/versions/3.6.1/envs/temp/lib/python3.6/site-packages/attr/_make.py
>> in attrs(maybe_cls, these, repr_ns, repr, cmp, hash, init, slots, frozen,
>> str, auto_attribs)
>> 700 return wrap
>> 701 else:
>> --> 702 return wrap(maybe_cls)
>> 703
>> 704
>>
>> /Users/waksman/.pyenv/versions/3.6.1/envs/temp/lib/python3.6/site-packages/attr/_make.py
>> in wrap(cls)
>> 669 raise TypeError("attrs only works with new-style
>> classes.")
>> 670
>> --> 671 builder = _ClassBuilder(cls, these, slots, frozen,
>> auto_attribs)
>> 672
>> 673 if repr is True:
>>
>> /Users/waksman/.pyenv/versions/3.6.1/envs/temp/lib/python3.6/site-packages/attr/_make.py
>> in __init__(self, cls, these, slots, frozen, auto_attribs)
>> 369
>> 370 def __init__(self, cls, these, slots, frozen, auto_attribs):
>> --> 371 attrs, super_attrs = _transform_attrs(cls, these,
>> auto_attribs)
>> 372
>> 373 self._cls = cls
>>
>> /Users/waksman/.pyenv/versions/3.6.1/envs/temp/lib/python3.6/site-packages/attr/_make.py
>> in _transform_attrs(cls, these, auto_attribs)
>> 335 "No mandatory attributes allowed after an
>> attribute with a "
>> 336 "default value or factory.  Attribute in
>> question: {a!r}"
>> --> 337 .format(a=a)
>> 338 )
>> 339 elif had_default is False and \
>>
>> ValueError: No mandatory attributes allowed after an attribute with a
>> default value or factory.  Attribute in question: Attribute(name='b',
>> default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True,
>> metadata=mappingproxy({}), type=None, converter=None)
>>
>>
>> On Fri, Jan 26, 2018 at 1:44 PM Guido van Rossum <gu...@python.org>
>> wrote:
>>
>>> What does attrs' solution for this problem look like?
>>>
>>> On Fri, Jan 26, 2018 at 11:11 AM, George Leslie-Waksman <
>>> waks...@gmail.com> wrote:
>>>
>>>> Even if we could inherit the setting, I would think that we would still
>>>> want to require the code be explicit. It seems worse to implicitly require
>>>> keyword only arguments for a class without giving any indication in the
>>>> code.
>>>>
>>>> As it stands, the current implementation does not allow a later
>>>> subclass to be declared without `keyword_only=True` so we could handle this
>>>> case by adding a note to the `TypeError` message about considering the
>>>> keyword_only flag.
>>>>
>>>> How do I got about putting together a proposal to get this into 3.8?
>>>>
>>>> --George
>>>>
>>>>
>>>> On Thu, Jan 25, 2018 at 5:12 AM Eric V. Smith <e...@trueblade.com>
>>>> wrote:
>>>>
>>>>> I'm not completely opposed to this feature. But there are some cases to
>>>>> consider. Here's the first one that occurs to me: note that due to the
>>>>> way dataclasses work, it would need to be used everywhere down an
>>>>> inheritance hierarchy. That is, if an intermediate base class required
>>>>> it, all class derived from that intermediate base would need to specify
>>>>> it, too. That's because each class ju

Re: [Python-ideas] Dataclasses, keyword args, and inheritance

2018-01-29 Thread George Leslie-Waksman
attrs' seems to also not allow mandatory attributes to follow optional one:

In [14]: @attr.s
...: class Baz:
...: a = attr.ib(default=attr.Factory(list))
...: b = attr.ib()
...:
---
ValueErrorTraceback (most recent call last)
 in ()
> 1 @attr.s
  2 class Baz:
  3 a = attr.ib(default=attr.Factory(list))
  4 b = attr.ib()
  5

/Users/waksman/.pyenv/versions/3.6.1/envs/temp/lib/python3.6/site-packages/attr/_make.py
in attrs(maybe_cls, these, repr_ns, repr, cmp, hash, init, slots, frozen,
str, auto_attribs)
700 return wrap
701 else:
--> 702 return wrap(maybe_cls)
703
704

/Users/waksman/.pyenv/versions/3.6.1/envs/temp/lib/python3.6/site-packages/attr/_make.py
in wrap(cls)
669 raise TypeError("attrs only works with new-style
classes.")
670
--> 671 builder = _ClassBuilder(cls, these, slots, frozen,
auto_attribs)
672
673 if repr is True:

/Users/waksman/.pyenv/versions/3.6.1/envs/temp/lib/python3.6/site-packages/attr/_make.py
in __init__(self, cls, these, slots, frozen, auto_attribs)
369
370 def __init__(self, cls, these, slots, frozen, auto_attribs):
--> 371 attrs, super_attrs = _transform_attrs(cls, these,
auto_attribs)
372
373 self._cls = cls

/Users/waksman/.pyenv/versions/3.6.1/envs/temp/lib/python3.6/site-packages/attr/_make.py
in _transform_attrs(cls, these, auto_attribs)
335 "No mandatory attributes allowed after an attribute
with a "
336 "default value or factory.  Attribute in question:
{a!r}"
--> 337 .format(a=a)
338 )
339 elif had_default is False and \

ValueError: No mandatory attributes allowed after an attribute with a
default value or factory.  Attribute in question: Attribute(name='b',
default=NOTHING, validator=None, repr=True, cmp=True, hash=None, init=True,
metadata=mappingproxy({}), type=None, converter=None)


On Fri, Jan 26, 2018 at 1:44 PM Guido van Rossum <gu...@python.org> wrote:

> What does attrs' solution for this problem look like?
>
> On Fri, Jan 26, 2018 at 11:11 AM, George Leslie-Waksman <waks...@gmail.com
> > wrote:
>
>> Even if we could inherit the setting, I would think that we would still
>> want to require the code be explicit. It seems worse to implicitly require
>> keyword only arguments for a class without giving any indication in the
>> code.
>>
>> As it stands, the current implementation does not allow a later subclass
>> to be declared without `keyword_only=True` so we could handle this case by
>> adding a note to the `TypeError` message about considering the keyword_only
>> flag.
>>
>> How do I got about putting together a proposal to get this into 3.8?
>>
>> --George
>>
>>
>> On Thu, Jan 25, 2018 at 5:12 AM Eric V. Smith <e...@trueblade.com> wrote:
>>
>>> I'm not completely opposed to this feature. But there are some cases to
>>> consider. Here's the first one that occurs to me: note that due to the
>>> way dataclasses work, it would need to be used everywhere down an
>>> inheritance hierarchy. That is, if an intermediate base class required
>>> it, all class derived from that intermediate base would need to specify
>>> it, too. That's because each class just makes decisions based on its
>>> fields and its base classes' fields, and not on any flags attached to
>>> the base class. As it's currently implemented, a class doesn't remember
>>> any of the decorator's arguments, so there's no way to look for this
>>> information, anyway.
>>>
>>> I think there are enough issues here that it's not going to make it in
>>> to 3.7. It would require getting a firm proposal together, selling the
>>> idea on python-dev, and completing the implementation before Monday. But
>>> if you want to try, I'd participate in the discussion.
>>>
>>> Taking Ivan's suggestion one step further, a way to do this currently is
>>> to pass init=False and then write another decorator that adds the
>>> kw-only __init__. So the usage would be:
>>>
>>> @dataclass
>>>  class Foo:
>>>  some_default: dict = field(default_factory=dict)
>>>
>>> @kw_only_init
>>> @dataclass(init=False)
>>> class Bar(Foo):
>>>  other_field: int
>>>
>>> kw_only_init(cls) would look at fields(cls) and construct the __init__.
>>> It would be a hassle to re-implement dataclasses's _init_fn function,
>>> b

Re: [Python-ideas] Dataclasses, keyword args, and inheritance

2018-01-26 Thread George Leslie-Waksman
Even if we could inherit the setting, I would think that we would still
want to require the code be explicit. It seems worse to implicitly require
keyword only arguments for a class without giving any indication in the
code.

As it stands, the current implementation does not allow a later subclass to
be declared without `keyword_only=True` so we could handle this case by
adding a note to the `TypeError` message about considering the keyword_only
flag.

How do I got about putting together a proposal to get this into 3.8?

--George

On Thu, Jan 25, 2018 at 5:12 AM Eric V. Smith <e...@trueblade.com> wrote:

> I'm not completely opposed to this feature. But there are some cases to
> consider. Here's the first one that occurs to me: note that due to the
> way dataclasses work, it would need to be used everywhere down an
> inheritance hierarchy. That is, if an intermediate base class required
> it, all class derived from that intermediate base would need to specify
> it, too. That's because each class just makes decisions based on its
> fields and its base classes' fields, and not on any flags attached to
> the base class. As it's currently implemented, a class doesn't remember
> any of the decorator's arguments, so there's no way to look for this
> information, anyway.
>
> I think there are enough issues here that it's not going to make it in
> to 3.7. It would require getting a firm proposal together, selling the
> idea on python-dev, and completing the implementation before Monday. But
> if you want to try, I'd participate in the discussion.
>
> Taking Ivan's suggestion one step further, a way to do this currently is
> to pass init=False and then write another decorator that adds the
> kw-only __init__. So the usage would be:
>
> @dataclass
>  class Foo:
>  some_default: dict = field(default_factory=dict)
>
> @kw_only_init
> @dataclass(init=False)
> class Bar(Foo):
>  other_field: int
>
> kw_only_init(cls) would look at fields(cls) and construct the __init__.
> It would be a hassle to re-implement dataclasses's _init_fn function,
> but it could be made to work (in reality, of course, you'd just copy it
> and hack it up to do what you want). You'd also need to use some private
> knowledge of InitVars if you wanted to support them (the stock
> fields(cls) doesn't return them).
>
> For 3.8 we can consider changing dataclasses's APIs if we want to add this.
>
> Eric.
>
> On 1/25/2018 1:38 AM, George Leslie-Waksman wrote:
> > It may be possible but it makes for pretty leaky abstractions and it's
> > unclear what that custom __init__ should look like. How am I supposed to
> > know what the replacement for default_factory is?
> >
> > Moreover, suppose I want one base class with an optional argument and a
> > half dozen subclasses each with their own required argument. At that
> > point, I have to write the same __init__ function a half dozen times.
> >
> > It feels rather burdensome for the user when an additional flag (say
> > "kw_only=True") and a modification to:
> > https://github.com/python/cpython/blob/master/Lib/dataclasses.py#L294
>  that
> > inserted `['*']` after `[self_name]` if the flag is specified could
> > ameliorate this entire issue.
> >
> > On Wed, Jan 24, 2018 at 3:22 PM Ivan Levkivskyi <levkivs...@gmail.com
> > <mailto:levkivs...@gmail.com>> wrote:
> >
> > It is possible to pass init=False to the decorator on the subclass
> > (and supply your own custom __init__, if necessary):
> >
> >     @dataclass
> > class Foo:
> >  some_default: dict = field(default_factory=dict)
> >
> > @dataclass(init=False) # This works
> > class Bar(Foo):
> >  other_field: int
> >
> > --
> > Ivan
> >
> >
> >
> > On 23 January 2018 at 03:33, George Leslie-Waksman
> > <waks...@gmail.com <mailto:waks...@gmail.com>> wrote:
> >
> > The proposed implementation of dataclasses prevents defining
> > fields with defaults before fields without defaults. This can
> > create limitations on logical grouping of fields and on
> inheritance.
> >
> > Take, for example, the case:
> >
> > @dataclass
> > class Foo:
> >  some_default: dict = field(default_factory=dict)
> >
> > @dataclass
> > class Bar(Foo):
> >  other_field: int
> >
> > this results in the error:
> >
> >5 @dataclass
> > > 6 class Bar(Foo):
> >7 other_field: int
> > 

Re: [Python-ideas] Dataclasses, keyword args, and inheritance

2018-01-24 Thread George Leslie-Waksman
It may be possible but it makes for pretty leaky abstractions and it's
unclear what that custom __init__ should look like. How am I supposed to
know what the replacement for default_factory is?

Moreover, suppose I want one base class with an optional argument and a
half dozen subclasses each with their own required argument. At that point,
I have to write the same __init__ function a half dozen times.

It feels rather burdensome for the user when an additional flag (say
"kw_only=True") and a modification to:
https://github.com/python/cpython/blob/master/Lib/dataclasses.py#L294 that
inserted `['*']` after `[self_name]` if the flag is specified could
ameliorate this entire issue.

On Wed, Jan 24, 2018 at 3:22 PM Ivan Levkivskyi <levkivs...@gmail.com>
wrote:

> It is possible to pass init=False to the decorator on the subclass (and
> supply your own custom __init__, if necessary):
>
> @dataclass
> class Foo:
> some_default: dict = field(default_factory=dict)
>
> @dataclass(init=False) # This works
> class Bar(Foo):
> other_field: int
>
> --
> Ivan
>
>
>
> On 23 January 2018 at 03:33, George Leslie-Waksman <waks...@gmail.com>
> wrote:
>
>> The proposed implementation of dataclasses prevents defining fields with
>> defaults before fields without defaults. This can create limitations on
>> logical grouping of fields and on inheritance.
>>
>> Take, for example, the case:
>>
>> @dataclass
>> class Foo:
>> some_default: dict = field(default_factory=dict)
>>
>> @dataclass
>> class Bar(Foo):
>> other_field: int
>>
>> this results in the error:
>>
>>   5 @dataclass
>> > 6 class Bar(Foo):
>>   7 other_field: int
>>   8
>>
>> ~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py
>> in dataclass(_cls, init, repr, eq, order, hash, frozen)
>> 751
>> 752 # We're called as @dataclass, with a class.
>> --> 753 return wrap(_cls)
>> 754
>> 755
>>
>> ~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py
>> in wrap(cls)
>> 743
>> 744 def wrap(cls):
>> --> 745 return _process_class(cls, repr, eq, order, hash, init,
>> frozen)
>> 746
>> 747 # See if we're being called as @dataclass or @dataclass().
>>
>> ~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py
>> in _process_class(cls, repr, eq, order, hash, init, frozen)
>> 675 #  in __init__.  Use "self" if
>> possible.
>> 676 '__dataclass_self__' if 'self' in
>> fields
>> --> 677 else 'self',
>> 678 ))
>> 679 if repr:
>>
>> ~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py
>> in _init_fn(fields, frozen, has_post_init, self_name)
>> 422 seen_default = True
>> 423 elif seen_default:
>> --> 424 raise TypeError(f'non-default argument {f.name!r}
>> '
>> 425 'follows default argument')
>> 426
>>
>> TypeError: non-default argument 'other_field' follows default argument
>>
>> I understand that this is a limitation of positional arguments because
>> the effective __init__ signature is:
>>
>> def __init__(self, some_default: dict = , other_field: int):
>>
>> However, keyword only arguments allow an entirely reasonable solution to
>> this problem:
>>
>> def __init__(self, *, some_default: dict = , other_field: int):
>>
>> And have the added benefit of making the fields in the __init__ call
>> entirely explicit.
>>
>> So, I propose the addition of a keyword_only flag to the @dataclass
>> decorator that renders the __init__ method using keyword only arguments:
>>
>> @dataclass(keyword_only=True)
>> class Bar(Foo):
>> other_field: int
>>
>> --George Leslie-Waksman
>>
>> ___
>> Python-ideas mailing list
>> Python-ideas@python.org
>> https://mail.python.org/mailman/listinfo/python-ideas
>> Code of Conduct: http://python.org/psf/codeofconduct/
>>
>>
>
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Dataclasses, keyword args, and inheritance

2018-01-22 Thread George Leslie-Waksman
The proposed implementation of dataclasses prevents defining fields with
defaults before fields without defaults. This can create limitations on
logical grouping of fields and on inheritance.

Take, for example, the case:

@dataclass
class Foo:
some_default: dict = field(default_factory=dict)

@dataclass
class Bar(Foo):
other_field: int

this results in the error:

  5 @dataclass
> 6 class Bar(Foo):
  7 other_field: int
  8

~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py
in dataclass(_cls, init, repr, eq, order, hash, frozen)
751
752 # We're called as @dataclass, with a class.
--> 753 return wrap(_cls)
754
755

~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py
in wrap(cls)
743
744 def wrap(cls):
--> 745 return _process_class(cls, repr, eq, order, hash, init,
frozen)
746
747 # See if we're being called as @dataclass or @dataclass().

~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py
in _process_class(cls, repr, eq, order, hash, init, frozen)
675 #  in __init__.  Use "self" if
possible.
676 '__dataclass_self__' if 'self' in
fields
--> 677 else 'self',
678 ))
679 if repr:

~/.pyenv/versions/3.6.2/envs/clover_pipeline/lib/python3.6/site-packages/dataclasses.py
in _init_fn(fields, frozen, has_post_init, self_name)
422 seen_default = True
423 elif seen_default:
--> 424 raise TypeError(f'non-default argument {f.name!r} '
425 'follows default argument')
426

TypeError: non-default argument 'other_field' follows default argument

I understand that this is a limitation of positional arguments because the
effective __init__ signature is:

def __init__(self, some_default: dict = , other_field: int):

However, keyword only arguments allow an entirely reasonable solution to
this problem:

def __init__(self, *, some_default: dict = , other_field: int):

And have the added benefit of making the fields in the __init__ call
entirely explicit.

So, I propose the addition of a keyword_only flag to the @dataclass
decorator that renders the __init__ method using keyword only arguments:

@dataclass(keyword_only=True)
class Bar(Foo):
other_field: int

--George Leslie-Waksman
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/