[RFC] A shortcut to define a classvar with the same name as an attribute
Nobody has claimed this yet.
Assessment
- Difficulty
- 5/5
- Estimated time
- Over a week
- Newbie friendliness
- 20/100
Research direction
Start with the examples in the issue and review the existing attr.ib and decorator behavior; no source files or tests are named. The first milestone is maintainer agreement on whether the classvar proposal, skippable-init proposal, or neither should be pursued, after which the chosen scope can be implemented and validated.
Written by the indexing model from the issue text.
Description
Hello!
Thanks again for the great library! :)
After answering in a couple of issues regarding default values on class-level and debugging another mess with self-using factory which was fixed by migration to @cached_property, I thought that it may be good to have a simple way to set a class-level attribute with the same name as an attr.ib on attrs class.
The issue can be illustrated by a following example:
import attr
@attr.dataclass
class BaseClass:
value: int
magic: str
@attr.s
class FixedMagicClass(BaseClass):
magic = attr.ib(init=False, default='alohomora')
@attr.s
class _ReprMagicClass(BaseClass):
# A proxy class to exclude 'magic' from init
magic = attr.ib(init=False)
@attr.s
class ReprMagicClass(_ReprMagicClass):
@cached_property
def magic(self):
return repr(self.value)
I'd like to add classvar parameter in attr.ib and decorator syntactic sugar like this:
@attr.s
class FixedMagicClass(BaseClass):
magic = attr.ib(init=False, classvar='alohomora') # Almost no difference, but it can be accessed on the class object
@attr.s
class ReprMagicClass(BaseClass):
@attr.ib(init=False).classvar
@cached_property # Property is a descriptor and is set on class object itself
def magic(self):
return repr(self.value)
Alternative approach may be implementing it via metadata + field_transformer, but syntax becomes clumsy. From my perspective this seems more like a core feature than like an extension.
Though, it may be a non-desired feature as it wouldn't work with slotted classes - they use their own slot descriptors - and therefore may complicate migration from dict-classes to slot-classes.
Other possible related feature, which may blend in perfectly with property and class-level constants, is a way to make an attr.ib skippable during __init__ - e.g. if an attribute is init=True and has default=attr.UNSET the generated __init__ code will be like following:
def __init__(self, required_attribute, attribute=attr.UNSET):
self.required_attribute = required_attribute # This attribute had `attr.NOTHING` default in `attr.ib`
if attribute is not attr.UNSET: # If it wasn't set, we'll take the classvar instead
self.attribute = attribute
I'll be happy to implement this proposal (actually - both of them) if it would be considered useful.
- Dominant language
- Python
- Stars
- 5.8k
- Forks
- 480
- Avg merge
- 2h 15m
- Merged PRs (30d)
- 2
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.
More from python-attrs/attrs
-
Difficulty 5/5 Over a week Newbie friendliness 20/100
python-attrs/attrs#1620 ·
-
Difficulty 3/5 1-2 days Newbie friendliness 55/100
python-attrs/attrs#1596 · 2 comments · 1 reaction ·
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
python-attrs/attrs#1549 · 3 comments ·
-
Difficulty 4/5 3-5 days Newbie friendliness 38/100
python-attrs/attrs#1543 · 2 comments ·
-
Difficulty 4/5 3-5 days Newbie friendliness 35/100
python-attrs/attrs#1532 ·
All issues in python-attrs/attrs
Similar issues
-
documentation help wanted
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 90/100
simonw/sqlite-utils#872 ·
-
Difficulty 2/5 1-3 hours Newbie friendliness 88/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 82/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 78/100