Is hasattr really harmful?

I just stumble upon flake8-plone-hasattr that "Checks for hasattr, which is considered harmful in Plone projects".

may I ask why hasattr is considered harmful in Plone projects?

"The (hidden) problem with hasattr is that it swallows exceptions, which in your normal business logic you really don’t want to."

Also see https://github.com/plone/Products.CMFPlone/blob/master/Products/CMFPlone/utils.py#L412

In this case the ValueError is never seen.

>>> class Foo(object):
...     @property
...     def my_attr(self):
...         raise ValueError('nope, nope, nope')
...
>>> bar = Foo()
>>> bar.my_attr
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in my_attr
ValueError: nope, nope, nope
>>> hasattr(Foo, 'my_attr')
True
>>> hasattr(bar, 'my_attr')
False
>>> getattr(bar, 'my_attr', None)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 4, in my_attr
ValueError: nope, nope, nope
>>>

OMG, this should be fixed on python core.

@rodfersou I though it was fixed, but is not: https://bugs.python.org/issue2196

@gforcada it would be nice to add @jaroel example into the package documentation.

isn't it possible to make a monkey patch on it?

There is a safe_hasattr() somewhere in Plone which you should use usually.

-aj

It's a github repository, click on clone, edit the files and send a pull request, you are welcome to contribute and not only to point to others what needs to be done... I already created the distribution :smile:

1 Like

Why do you want to monkey patch it? You can use a getattr if you want, on plain python projects maybe you really don't want any exception to be raised...

Sure you can. You shouldn't because it will break a lot of code.
Just use the safe_hasattr, or getattr.

>>> def kek(*args, **kwargs):
...     raise ValueError('yay')

>>> kek()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in kek
ValueError: yay

>>> import __builtin__
>>> __builtin__.hasattr = kek

>>> hasattr
<function kek at 0x108137230>

>>> hasattr()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 2, in kek
ValueError: yay

@gforcada I just thought it was better to fix hasattr than have other method to remember in the toolbox (oh, it is plone, so don't use hasattr, it is not plone, so it is "ok").

@jaroel thank you for the example, I'll try to add the monkey path at buildout.coredev and run the test suite to see what happen.

GenericSetup does some actions when trying to access an attribute. These can create ZODB Conflict Errors, imagine what would happen if you'd use hasattr

1 Like

The hasattr problem is not Plone specific.
The Python community is aware of this "problem", but it can't really be fixed without possibly breaking loads of (legacy) customer code.

here you are: