[issue34776] Postponed annotations break inspection of dataclasses

2019-10-23 Thread David Hagen


David Hagen  added the comment:

This PR has been sitting for a while. Any chance we can bring it over the 
finish line?

--

___
Python tracker 
<https://bugs.python.org/issue34776>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36424] Pickle fails on frozen dataclass that has slots

2021-10-13 Thread David Hagen


David Hagen  added the comment:

Because the implementation in GH-25786 relies on the new 
`dataclass(slots=True)` feature (i.e. it does not work if the slots are 
specified with `__slots__`), I don't think this can be trivially backported to 
versions before 3.10.

--

___
Python tracker 
<https://bugs.python.org/issue36424>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue39442] from __future__ import annotations makes dataclasses.Field.type a string, not type

2020-01-24 Thread David Hagen


David Hagen  added the comment:

Should `dataclass.Field.type` become a property that evaluates the annotation 
at runtime much in the same way that `get_type_hints` works?

--
nosy: +drhagen

___
Python tracker 
<https://bugs.python.org/issue39442>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue31385] `import as` does not work when module has same same as parent module

2017-09-07 Thread David Hagen

New submission from David Hagen:

Consider the following Python project:

bugtest/
  __init__.py (Contents: from .foo import *)
  foo/
__init__.py (Contents: from .foo import *)
foo.py (Contents: )

Then in a Python session, the following line executes without error (as 
expected):

>>> import bugtest.foo.foo

However, the following line gives an error (not as expected):

>>> import bugtest.foo.foo as bar
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: module 'bugtest.foo.foo' has no attribute 'foo'

Note that this behavior is dependent on the folder foo and the file foo.py 
having the same base name. But is not dependent on actually trying to import 
bugtest.foo.foo. Trying to import bugtest.foo.baz will also fail as long as 
bugtest.foo.foo exists.

It is also dependent on the __init__.py files importing something from their 
respective submodules.

--
messages: 301614
nosy: David Hagen
priority: normal
severity: normal
status: open
title: `import as` does not work when module has same same as parent module
type: behavior
versions: Python 3.5, Python 3.6

___
Python tracker 
<https://bugs.python.org/issue31385>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue36424] Pickle fails on frozen dataclass that has slots

2019-03-25 Thread David Hagen


New submission from David Hagen :

If a dataclass is `frozen` and has `__slots__`, then unpickling an instance of 
it fails because the default behavior is to use `setattr` which `frozen` does 
not allow.

```
import pickle
from dataclasses import dataclass

@dataclass(frozen=True)
class A:
  __slots__ = ('a',)
  a: int

b = pickle.dumps(A(5))
pickle.loads(b)
```

```
Traceback (most recent call last):
  File "", line 1, in 
  File "", line 3, in __setattr__
dataclasses.FrozenInstanceError: cannot assign to field 'a'
```

This has a straightforward workaround, namely to use `object.setattr`.

```
import pickle
from dataclasses import dataclass

@dataclass(frozen=True)
class A:
__slots__ = ('a',)
a: int

def __getstate__(self):
return dict(
(slot, getattr(self, slot))
for slot in self.__slots__
if hasattr(self, slot)
)

def __setstate__(self, state):
for slot, value in state.items():
object.__setattr__(self, slot, value)


b = pickle.dumps(A(5))
pickle.loads(b)
```

It would be nice if this was fixed for all frozen, slotted dataclasses.

Originally report on SO: 
https://stackoverflow.com/questions/55307017/pickle-a-frozen-dataclass-that-has-slots

--
messages: 338803
nosy: drhagen
priority: normal
severity: normal
status: open
title: Pickle fails on frozen dataclass that has slots
type: behavior
versions: Python 3.7

___
Python tracker 
<https://bugs.python.org/issue36424>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue34776] Postponed annotations break inspection of dataclasses

2018-09-23 Thread David Hagen


New submission from David Hagen :

The new postponed annotations have an unexpected interaction with dataclasses. 
Namely, you cannot get the type hints of any of the data classes methods.

For example, I have some code that inspects the type parameters of a class's 
`__init__` method. (The real use case is to provide a default serializer for 
the class, but that is not important here.)  

```
from dataclasses import dataclass
from typing import get_type_hints

class Foo:
pass

@dataclass
class Bar:
foo: Foo

print(get_type_hints(Bar.__init__))
```

In Python 3.6 and 3.7, this does what is expected; it prints `{'foo': , 'return': }`.

However, if in Python 3.7, I add `from __future__ import annotations`, then 
this fails with an error:

```
NameError: name 'Foo' is not defined
```

I know why this is happening. The `__init__` method is defined in the 
`dataclasses` module which does not have the `Foo` object in its environment, 
and the `Foo` annotation is being passed to `dataclass` and attached to 
`__init__` as the string `"Foo"` rather than as the original object `Foo`, but 
`get_type_hints` for the new annotations only does a name lookup in the module 
where `__init__` is defined not where the annotation is defined.

I know that the use of lambdas to implement PEP 563 was rejected for 
performance reasons. I could be wrong, but I think this was motivated by 
variable annotations because the lambda would have to be constructed each time 
the function body ran. I was wondering if I could motivate storing the 
annotations as lambdas in class bodies and function signatures, in which the 
environment is already being captured and is code that usually only runs once.

Original mailing list discussion: 
https://mail.python.org/pipermail/python-dev/2018-September/155289.html

--
messages: 326148
nosy: drhagen
priority: normal
severity: normal
status: open
title: Postponed annotations break inspection of dataclasses
type: behavior
versions: Python 3.7

___
Python tracker 
<https://bugs.python.org/issue34776>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue26988] Add AutoNumberedEnum to stdlib

2016-08-17 Thread David Hagen

David Hagen added the comment:

> Secondarily, the doesn't seem to be any use case that can't be readily 
> covered by the existing classes.

The use case that doesn't have a clean interface in 3.5 at the moment is the 
most common use case of enums: just a collection of named objects of given 
type; I don't care about the values because they don't really have values apart 
from their object identities.

When writing enums in Rust, Swift, C#, etc., the bare identifier not only saves 
typing--it allows the developer to explicitly indicate that the underlying 
value has no meaning. (It may be better to use "object()" rather than an 
integer on AutoEnum, but that is not very important.)

It was said that Python has this feature already:

> Yes, Python 3.4 too: Animal = Enum('Animal', 'ant bee cat dog')

I will concede that this can do what I want. I hope others will concede that 
this is not a clean interface. The class name is duplicated and the members are 
regexed out of a space-delimited string. This same argument could be made to 
deprecate the unnecessary "class" keyword in favor of the "type" function.

I will also concede that there is some deep magic going on in AutoEnum and that 
magic should be avoided when it obscures. I personally think the only people 
who will be truly surprised will be those who already know Python at a deep 
enough level to know that deep magic must be required here. Everyone else will 
see "Enum" and a list of bare identifiers, and correctly conclude that this is 
your basic enum from everyone other language.

Perhaps an ideal solution would be an enum keyword:

enum PrimaryColor:
red
blue
green

But that's not happening ever.

The next best solution is the current implementation:

class PrimaryColor(AutoEnum):
red
blue
green

But because of the magic, it only barely beats out what I think is the other 
great solution already mentioned here:

class PrimaryColor(AutoEnum):
red = ()
blue = ()
green = ()

These two solutions are isomorphic. Both save the developer from having to 
provide a (possibly meaningless) value. Both let docstrings be added. Both 
provide the ability to reorganize without renumbering. The last one trades 
magic for boilerplate.

I'll keep using them from the aenum package if they don't make it into 3.6, but 
I think this is a fundamental enough construct that it belongs in the standard 
library. It is hard to convince tool maintainers to fully support these until 
they are blessed here.

--
nosy: +David Hagen

___
Python tracker 
<http://bugs.python.org/issue26988>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com



[issue26988] Add AutoNumberedEnum to stdlib

2016-08-19 Thread David Hagen

David Hagen added the comment:

One solution similar to one proposed by Vedran works with the current Enum:

class Color(Enum):
red = object()
green = object()
blue= object()

I tested this in PyCharm and it is perfectly happy with the autocomplete and 
everything. The main disadvantage is the boilerplate, of course. And perhaps 
"object()" does not show the clearest intent, but it depends on your 
perspective. The repr also looks kind of funny:

>>>  repr(Color.red)
>

One possibility would be to add an auto() function to enum as a wrapper around 
object(), providing a more explicit name and a cleaner repr:

from enum import Enum, auto

class Color(Enum):
red = auto()
blue = auto()
green = auto()

repr(Color.red)

# auto() means it has no (meaningful) value, so show nothing

--

___
Python tracker 
<http://bugs.python.org/issue26988>
___
___
Python-bugs-list mailing list
Unsubscribe: 
https://mail.python.org/mailman/options/python-bugs-list/archive%40mail-archive.com