Opened 10 years ago
Closed 10 years ago
#22839 closed Cleanup/optimization (invalid)
Many to many hasattr check fails with python 3
Reported by: | Owned by: | nobody | |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 1.6 |
Severity: | Normal | Keywords: | |
Cc: | Kevin Brown, cmawebsite@… | Triage Stage: | Accepted |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description
Example model:
class CommentModel(models.Model): users_liked = models.ManyToManyField(UserModel, blank=True, null=True) text = models.CharField(max_length=200)
With python 2 it's ok:
hasattr(CommentModel(text='hello'), 'users_liked') # => True
With python 3 it fails:
hasattr(CommentModel(text='hello'), 'users_liked') Traceback (most recent call last): File "tests.py", line 33, in test_should_use_default_saving_without_partial hasattr(CommentModel(text='hello'), 'users_liked') File ".tox/django1.6.2/lib/python3.4/site-packages/django/db/models/fields/related.py", line 825, in __get__ through=self.field.rel.through, File ".tox/django1.6.2/lib/python3.4/site-packages/django/db/models/fields/related.py", line 522, in __init__ (instance, source_field_name)) ValueError: "<CommentModel: CommentModel object>" needs to have a value for field "commentmodel" before this many-to-many relationship can be used.
As i understood ValueError
is caught somewhere in python 2, but not caught in python 3.
Change History (5)
comment:1 by , 10 years ago
Triage Stage: | Unreviewed → Accepted |
---|---|
Type: | Uncategorized → Cleanup/optimization |
comment:2 by , 10 years ago
Sorry, it return False, as you wrote, because it's descriptor binded to the class.
comment:3 by , 10 years ago
Cc: | added |
---|
comment:4 by , 10 years ago
This is the expected behavior for hasattr in Python 3:
"The arguments are an object and a string. The result is True if the string is the name of one of the object’s attributes, False if not. (This is implemented by calling getattr(object, name) and seeing whether it raises an AttributeError or not.)"
https://docs.python.org/3/library/functions.html#hasattr
While in Python 2 hasatttr would return false on any exception, not just AttributeError.
I've been bitten by this while porting Raven to python3.
comment:5 by , 10 years ago
Cc: | added |
---|---|
Resolution: | → invalid |
Status: | new → closed |
As linovia said, hasattr returns False on all exceptions on python 2, and only returns False on AttributeError on python 3. Feel free to reopen if that isn't the issue.
Hi,
I tried your example and while I get the same error on Python 3, I get a different result on Python 2 (`
hasattr(CommentModel(text='hello'), 'users_liked')` is False for me).
I'll mark this as
accepted
on the basis that there shouldn't be an inconsistency between Python 2 and 3 but I'm not sure which of the outcomes is the correct one.Thanks.