1

A Django 1.1 / Python 2.7 project that I'm attempting to run on Python 3.10 / Django 4.1.

A Python related error (i.e. old import) or a django code error (i.e. missing field that's now mandatory) pops up, I fix it and rerun.

The current error, however, is coming from django/db/models/base.py, from this function -

def _has_contribute_to_class(value):
    # Only call contribute_to_class() if it's bound.
    return not inspect.isclass(value) and hasattr(value, "contribute_to_class")

I found this ticket - https://code.djangoproject.com/ticket/30309

that explains that hasattr is unreliable, but seems to be ignored.

Has anyone encountered this issue, and managed to find a solution other than staying on Django 1.1?

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
Jay
  • 2,535
  • 3
  • 32
  • 44
  • note, `hasattr` isn't unreliable, it just works *as one would expect*, i.e., not to silence anything but `AttributeErrors`, which is probably why that example wasn't removed – juanpa.arrivillaga Aug 03 '22 at 18:06
  • Shouldn't `hasattr()` return `True` or `False`, given an object and a string? – Jay Aug 04 '22 at 04:29
  • Not if retrieving the value raises an error that isn't an AttributeError. Just the same as if you did `try: obj.attr; return True except AttributeError: return False` if it was the same as a bare `except: return False` that would mask all sorts of things that are probably bugs and should error – juanpa.arrivillaga Aug 04 '22 at 05:01
  • Show the full stack trace. – aaron Aug 06 '22 at 15:21
  • 3
    Read [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example). – aaron Aug 06 '22 at 15:21
  • it is interesting that value object you have. Value should be a Class. Can you give a little bit more information about Value. If there you override getaattribute dunder, i can imagine those behaviour – Maxim Danilov Aug 07 '22 at 20:28
  • I won't do/recommend upgrading versions with a huge gap instead I would try to upgrade to the next possible version (or next possible LTS). Things may take more time - but, that's more reliable (from personal experience :wink) – JPG Aug 10 '22 at 04:16

1 Answers1

0

hasattr Python2 vs hasattr Python3. They have different behavior

How works hasattr() in python 2:

try:
    getattr(foo, 'bar')
    return True
except:
    pass
return False #This is important part

How works hasattr() in python 3:

try:
    getattr(foo, 'bar')
    return True
except AttributeError as error:
    return False
raise AttributeError from error

It means - if you have any other problem in class - in python2 hasattr suppressed all. But Python3 give you an AttributeError Exception.

That's why i ask you to give us the code of class of your "value".

By the way: Django 4.1 call this method _has_contribute_to_class in ModelBase. Django 1.xx don't have this method and don't call it.

Maxim Danilov
  • 2,472
  • 1
  • 3
  • 8