python-attrs / python-attrs/attrs
Why descriptor don't work with attr?
Nobody has claimed this yet.
- Dominant language
- Python
- Stars
- 5.8k
- Forks
- 480
- Avg merge
- 2h 15m
- Merged PRs (30d)
- 2
Description
I am reading Architecture Patterns with Python and at some point the frozen dataclasses just don't work with sqlalchemy, so the author suggests setting unsafe_hash=True. To avoid making the class hashable I am using the descriptor bellow. I was also using @attr.s instead of @dataclass to get some of the features it has, like validators, but for some reason the descriptor works fine with dataclass, but not with attr and I can't understand why and if there is a way to make it work. If I set init=False on the attr.s class the descriptor will work for self.vid the I am only setting inside the init, but don't work with street and number.
from dataclasses import dataclass
import attr
import uuid
class Frozen:
"""cannot change attribute if it already exists"""
def __set_name__(self, owner, name):
self.storage_name = '_' + name
def __set__(self, instance, value):
if hasattr(instance, self.storage_name):
raise AttributeError(
f'readonly attribute {value.__class__.__name__}')
else:
setattr(instance, self.storage_name, value)
def __get__(self, instance, objtype=None):
return getattr(instance, self.storage_name)
# Frozen descriptor works fine here
@dataclass
class Address:
vid = Frozen()
street = Frozen()
number = Frozen()
street: str
number: str
def __init__(self, street: str, number: str, vid=None) -> None:
self.street = street
self.number = number
self.vid = vid if vid else uuid.uuid4().hex
# Frozen descriptor don't work here
@attr.s
class Address:
vid = Frozen()
street = Frozen()
number = Frozen()
street: str = attr.ib
number: str = attr.ib
def __init__(self, street: str, number: str, vid=None) -> None:
self.street = street
self.number = number
self.vid = vid if vid else uuid.uuid4().hex
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
No repository file or test is named. Reproduce the comparison between the dataclass and @attr.s examples, focusing on the Frozen descriptor, generated initialization, and the custom init. Done means establishing whether this is expected behavior and identifying the appropriate fix or documentation change.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- python
- Domain
- tooling
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Stale
- Clarity
- Mostly clear
- Newbie friendliness
- 25/100