Can only populate attrs classes with `_CountingAttr` instances

Open
#1,424 1 comment 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Assessment

Difficulty
4/5
Estimated time
3-5 days
Newbie friendliness
35/100
Issue type
Feature
Clarity
Mostly clear
Activity status
Stale
Tech stack
python
Domain
tooling

Research direction

Start with the _ClassBuilder path used by attrs.make_class and attrs.define, and reproduce the examples with attrs.fields(Example).a. Determine whether existing Attribute instances should be accepted directly or converted through a supported API; done means the reported examples no longer raise the shown AttributeError and the chosen behavior is covered.

Written by the indexing model from the issue text.

Description

A user might want to use attributes from an already @defined class to populate a new attrs class. However, _ClassBuilder expects all given attributes to be instances of _CountingAttr instead of Attribute instances, which raises an exception when provided:

import attrs

@attrs.define
class Example:
    a: int

ExampleCopy = attrs.make_class("ExampleCopy", attrs={"a": attrs.fields(Example).a})
# AttributeError: 'Attribute' object has no attribute '_validator'. Did you mean: 'validator'?

@attrs.define(these={"a": attrs.fields(Example).a})
class ExampleCopy:
    pass
# AttributeError: 'Attribute' object has no attribute '_validator'. Did you mean: 'validator'?

I would either expect _ClassBuilder to handle both kinds of attributes, or there be an officially sanctioned function allowing you to convert an Attribute to a _CountingAttr for cases like this. You can write this conversion function manually, something like:

def convert_to_countingattr(attr):
    """
    Convert an `Attribute` instance to an equivalent `_CountingAttr` instance.
    """
    return attrs.field(**{
        slot: getattr(attr, slot) 
        for slot in attr.__slots__ 
        if slot not in {"name", "eq_key", "order_key", "inherited"}
    })

But this feels janky and prone to breakage.

Dominant language
Python
Stars
5.8k
Forks
480
Avg merge
2h 15m
Merged PRs (30d)
2

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

More from python-attrs/attrs

All issues in python-attrs/attrs

Similar issues

More Python issues

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.