attrs icon indicating copy to clipboard operation
attrs copied to clipboard

attr.ibs that will be __name-mangled should be attrs-init-mangled to <name> not ClassName_<name>

Open graingert opened this issue 5 years ago • 5 comments

all attrs does is remove the leading "_" which is a bit unfortunate

import attr

@attr.s
class Breakfast:
    __spam = attr.ib()
    __eggs = attr.ib()

    @classmethod
    def create(cls):
        return cls(Breakfast__spam=1, Breakfast__eggs=2)

    def with_ham(self, ham):
       return attr.evolve(self, Breakfast__spam=process(ham))

I think it might be nicer as:

import attr

@attr.s
class Breakfast:
    __spam = attr.ib()
    __eggs = attr.ib()

    @classmethod
    def create(cls):
        return cls(**{cls.__spam: 1, cls.__eggs: 2})

    def with_ham(self, ham):
       return attr.evolve(self, **{type(self).__spam: process(ham)})

I currently work around it with

import re

import attr

class _Mangle:
    def __getattr__(self, name):
        return re.sub(pattern=r"\A_", repl="", string=name)

M = _Mangle()


@attr.s
class Breakfast:
    __spam = attr.ib()
    __eggs = attr.ib()

    @classmethod
    def create(cls):
        return cls(**{M.__spam: 1, M.__eggs: 2})


    def with_ham(self, ham):
       return attr.evolve(self, **{M.__spam: process(ham)})

graingert avatar Jan 27 '20 17:01 graingert

I suspect (and just quickly half-confirmed) the fact that this does anything at all is just "by accident", and that the code just checks the first character of the attribute name.

Personally I'm on the "don't use mangled attributes" team, but I guess if you're going to use them, then yeah the logical thing to do is strip the class name too. Worth noting that the same "issue" happens if you want double-underscore names, i.e.

@attr.s
class Foo(object):
    __foo__ = attr.ib()

has to be initialized via Foo(foo__=12) which is yeah...

Julian avatar Feb 29 '20 15:02 Julian

OK, y'all win: @attr.s(strip_underscores=True) – go! ;)

hynek avatar Feb 29 '20 15:02 hynek

@hynek well I don't that will help

You'd have to use cls(__Breakfast_ham=...) I think it should strip the classname

graingert avatar Feb 29 '20 15:02 graingert

OK, y'all win: @attr.s(strip_underscores=True) – go! ;)

@hynek could I read this as... you'd be open to a PR on https://github.com/python-attrs/attrs/issues/945?

asford avatar Apr 02 '22 19:04 asford

So I believe the worst brunt of this bug is fixed by #950 and I wonder if it's possible to fix this (i.e. __spam field becoming a spam argument) without breaking the whole ecosystem?

hynek avatar Apr 05 '23 09:04 hynek