Making third-party extensions a bit easier
Nobody has claimed this yet.
Assessment
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Newbie friendliness
- 38/100
- Issue type
- Feature
- Clarity
- Mostly clear
- Activity status
- Quiet
- Tech stack
- python
- Domain
- developer-experience
Research direction
Start in src/attr/_make.py, especially the referenced _CountingAttr handling around lines 403-407 and _determine_whether_to_implement. Trace how field decorators and classmethod handling are currently recognized, then compare the extension patterns described in the issue. Done means proposing and validating a supported way to extend fields or expose the needed helpers, with maintainer agreement on the API and tests for the chosen behavior.
Written by the indexing model from the issue text.
Description
I am researching how we can expand the field with more metadata on our project. The documentation was very helpful for getting started, but I've hit a few places where there is a bit of friction
Adding field decorators requires extending attr._make._CountingAttr
This is way more complicated then it seems at first glance because:
- the
_CountingAttrkeeps an internal counter for the ordering - changing the return type of
fieldmakes it be picked up as a customdefaultinstead of an extension of_CountingAttr
The initial design I considered was
def field(*, metadata=None, **kwargs: Any) -> Any:
if not metadata:
metadata = {}
metadata.setdefault("my_ext", MyMetadata())
return MyCountingAttr(attrs.field(**kwargs, metadata=metadata))
class MyCountingAttr(attr._make._CountingAttr):
def __init__(self, ca):
for f in ca.__slots__:
setattr(self, f, getattr(ca, f))
attr._make._CountingAttr.cls_counter -= 1
self.counter -= 1
def new_decorator(self, meth):
my_metadata: TmtAttrsMetadata = self.metadata["my_ext"]
my_metadata.func = meth
return meth
@attrs.define
class MyMetadata:
func: Callable[..., Any] | None = None
@attrs.define
class Example:
x: field()
@x.new_decorator
def _x_my_func(self):
pass
but this fails when it gets to
https://github.com/python-attrs/attrs/blob/f0e420b71af1a5cd5dbf43efd1a42aece6ce8f4e/src/attr/_make.py#L403-L407
Could not find a way around it besides changing that to a issubclass check
Many useful internal functions are not exposed
For example attr._make._determine_whether_to_implement would be really nice to not have to re-implement, especially when it comes to the correct handling of classmethod. Admittedly my usage there is quite weird (injecting some methods/classmethods based on inputs to the @define decorator) and it could be better handled with inheritance/metaclass, but it's the first example of the internal helpers that I've found in my code.
- 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 35/100
python-attrs/attrs#1532 ·
-
Difficulty 5/5 Over a week Newbie friendliness 25/100
python-attrs/attrs#1500 · 1 comment ·
All issues in python-attrs/attrs
Similar issues
-
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
-
enhancement
Difficulty 2/5 1-3 hours Newbie friendliness 72/100
-
Difficulty 2/5 1-3 hours Newbie friendliness 74/100