Просмотр исходного кода

#1352: Repack error into more informative one when it occurs

rafalp 2 лет назад
Родитель
Сommit
80b5398b7c
1 измененных файлов с 36 добавлено и 0 удалено
  1. 36 0
      misago/users/models/user.py

+ 36 - 0
misago/users/models/user.py

@@ -326,6 +326,42 @@ class User(AbstractBaseUser, PermissionsMixin):
         return self.username
 
     def get_real_name(self):
+        # Bug: https://github.com/rafalp/Misago/issues/1352
+        # On some very rare cases self.profile_fields is deserialized as string
+        # by Django's ORM. I am unable to reproduce this, but in case when this
+        # bug occurs, this code branch will print extra information about it
+        if not isinstance(self.profile_fields, dict):
+            from django.db import connections
+            from django.db.backends.signals import connection_created
+            from django.contrib.postgres.signals import get_hstore_oids
+
+            receivers = ", ".join([str(r[1]()) for r in connection_created.receivers])
+            dead_receivers = "TRUE" if connection_created._dead_receivers else "FALSE"
+
+            valid_oids = None
+            cached_oids = get_hstore_oids("default")
+
+            with connections["default"].cursor() as cursor:
+                cursor.execute(
+                    "SELECT t.oid, typarray "
+                    "FROM pg_type t "
+                    "JOIN pg_namespace ns ON typnamespace = ns.oid "
+                    "WHERE typname = 'hstore'"
+                )
+                oids = []
+                array_oids = []
+                for row in cursor:
+                    oids.append(row[0])
+                    array_oids.append(row[1])
+                valid_oids = tuple(oids), tuple(array_oids)
+
+            raise RuntimeError(
+                f"'profile_fields' has wrong type! Please post this WHOLE message on https://github.com/rafalp/Misago/issues/1352 "
+                f"OID: '{cached_oids}' (valid: '{valid_oids}') "
+                f"Receivers: '{receivers}' (has dead: {dead_receivers}) "
+                f"Repr: {repr(self.profile_fields)}"
+            )
+
         return self.profile_fields.get("real_name")
 
     def set_username(self, new_username, changed_by=None):