Skip to content

PURE_PYTHON: Name check for setting attributes is applied to all classes, not just C classes #36

@jamadden

Description

@jamadden

(Tested with 4.5.1, but this goes back to the very oldest code in this repo.)

The Python version of ExtensionClass applies the check for special methods to all classes:

def __setattr__(self, name, value):
if name not in ('__get__', '__doc__', '__of__'):
if (name.startswith('__') and name.endswith('__') and
name.count('_') == 4):
raise TypeError(
"can't set attributes of built-in/extension type '%s.%s' "
"if the attribute name begins and ends with __ and "
"contains only 4 _ characters" %
(self.__module__, self.__name__))
return type.__setattr__(self, name, value)

But the intent in the C version is to only apply the check to other built-in types:

if (! (type->tp_flags & Py_TPFLAGS_HEAPTYPE)) {
PyObject* as_bytes = convert_name(name);
if (as_bytes == NULL) {
return -1;
}
if (_is_bad_setattr_name(type, as_bytes)) {
Py_DECREF(as_bytes);
return -1;
}

This leads to a noticeable difference in PURE_PYTHON mode, such that code that works with the C extension fails in PURE_PYTHON. Compare the C version:

>>> os.environ.get("PURE_PYTHON")
None
>>> from ExtensionClass import Base
>>> class X(Base):
...     pass
...
>>> X.__eq__ = 'added by decorator'
>>>

to the Python version:

>>> os.environ['PURE_PYTHON'] = '1'
>>> from ExtensionClass import Base
>>> class X(Base):
...     pass
...
>>> X.__eq__ = 'added by decorator'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/lib/python3.10/site-packages/ExtensionClass/__init__.py", line 214, in __setattr__
    raise TypeError(
TypeError: can't set attributes of built-in/extension type '__main__.X' if the attribute name begins and ends with __ and contains only 4 _ characters

I'm not sure how to reliably detect built-in classes in Python, so I'm not sure how to fix this?

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions