From 60b823686f212f28f32aefacbc847c981b7b0280 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Laur=C3=A9line=20Gu=C3=A9rin?= <zebuline@entrouvert.com>
Date: Thu, 17 Sep 2020 14:48:37 +0200
Subject: [PATCH] misc: prefix CardData & FormData class name to avoid conflict
 (#46588)

---
 .../concerned_roles-_submitter                | Bin 0 -> 15 bytes
 .../card-bar/.indexes/status/status-None      | Bin 0 -> 15 bytes
 .../card-bar/.indexes/user_id/user_id-None    | Bin 0 -> 15 bytes
 .../workflow_roles/workflow_roles-None        | Bin 0 -> 15 bytes
 tests/data/oldpickledata/card-bar/.max_id     |   1 +
 tests/data/oldpickledata/card-bar/1           | Bin 0 -> 76 bytes
 .../backoffice_submission_roles-None          | Bin 0 -> 15 bytes
 tests/data/oldpickledata/carddefs/1           | Bin 0 -> 315 bytes
 .../concerned_roles-_submitter                | Bin 0 -> 15 bytes
 .../form-foo/.indexes/status/status-None      | Bin 0 -> 15 bytes
 .../form-foo/.indexes/user_id/user_id-None    | Bin 0 -> 15 bytes
 .../workflow_roles/workflow_roles-None        | Bin 0 -> 15 bytes
 tests/data/oldpickledata/form-foo/.max_id     |   1 +
 tests/data/oldpickledata/form-foo/1           | Bin 0 -> 76 bytes
 .../backoffice_submission_roles-None          | Bin 0 -> 15 bytes
 tests/data/oldpickledata/formdefs/1           | Bin 0 -> 302 bytes
 tests/test_storage.py                         |  19 ++++++++++++++++--
 wcs/carddef.py                                |  12 +++++------
 wcs/ctl/management/commands/convert_to_sql.py |   2 +-
 wcs/formdata.py                               |   5 +++--
 wcs/formdef.py                                |  16 +++++++++------
 wcs/publisher.py                              |   4 ++++
 22 files changed, 43 insertions(+), 17 deletions(-)
 create mode 100644 tests/data/oldpickledata/card-bar/.indexes/concerned_roles/concerned_roles-_submitter
 create mode 100644 tests/data/oldpickledata/card-bar/.indexes/status/status-None
 create mode 100644 tests/data/oldpickledata/card-bar/.indexes/user_id/user_id-None
 create mode 100644 tests/data/oldpickledata/card-bar/.indexes/workflow_roles/workflow_roles-None
 create mode 100644 tests/data/oldpickledata/card-bar/.max_id
 create mode 100644 tests/data/oldpickledata/card-bar/1
 create mode 100644 tests/data/oldpickledata/carddefs/.indexes/backoffice_submission_roles/backoffice_submission_roles-None
 create mode 100644 tests/data/oldpickledata/carddefs/1
 create mode 100644 tests/data/oldpickledata/form-foo/.indexes/concerned_roles/concerned_roles-_submitter
 create mode 100644 tests/data/oldpickledata/form-foo/.indexes/status/status-None
 create mode 100644 tests/data/oldpickledata/form-foo/.indexes/user_id/user_id-None
 create mode 100644 tests/data/oldpickledata/form-foo/.indexes/workflow_roles/workflow_roles-None
 create mode 100644 tests/data/oldpickledata/form-foo/.max_id
 create mode 100644 tests/data/oldpickledata/form-foo/1
 create mode 100644 tests/data/oldpickledata/formdefs/.indexes/backoffice_submission_roles/backoffice_submission_roles-None
 create mode 100644 tests/data/oldpickledata/formdefs/1

diff --git a/tests/data/oldpickledata/card-bar/.indexes/concerned_roles/concerned_roles-_submitter b/tests/data/oldpickledata/card-bar/.indexes/concerned_roles/concerned_roles-_submitter
new file mode 100644
index 0000000000000000000000000000000000000000..a7a08cd97a4d4db54f3d0cf5e44bfcace25d886f
GIT binary patch
diff --git a/tests/data/oldpickledata/card-bar/.indexes/status/status-None b/tests/data/oldpickledata/card-bar/.indexes/status/status-None
new file mode 100644
index 0000000000000000000000000000000000000000..a7a08cd97a4d4db54f3d0cf5e44bfcace25d886f
GIT binary patch
diff --git a/tests/data/oldpickledata/card-bar/.indexes/user_id/user_id-None b/tests/data/oldpickledata/card-bar/.indexes/user_id/user_id-None
new file mode 100644
index 0000000000000000000000000000000000000000..a7a08cd97a4d4db54f3d0cf5e44bfcace25d886f
GIT binary patch
diff --git a/tests/data/oldpickledata/card-bar/.indexes/workflow_roles/workflow_roles-None b/tests/data/oldpickledata/card-bar/.indexes/workflow_roles/workflow_roles-None
new file mode 100644
index 0000000000000000000000000000000000000000..a7a08cd97a4d4db54f3d0cf5e44bfcace25d886f
GIT binary patch
diff --git a/tests/data/oldpickledata/card-bar/.max_id b/tests/data/oldpickledata/card-bar/.max_id
new file mode 100644
index 00000000..56a6051c
--- /dev/null
+++ b/tests/data/oldpickledata/card-bar/.max_id
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/tests/data/oldpickledata/card-bar/1 b/tests/data/oldpickledata/card-bar/1
new file mode 100644
index 0000000000000000000000000000000000000000..eafb0df64336dd7e7d8e0c87028ad3555db0aba7
GIT binary patch
diff --git a/tests/data/oldpickledata/carddefs/.indexes/backoffice_submission_roles/backoffice_submission_roles-None b/tests/data/oldpickledata/carddefs/.indexes/backoffice_submission_roles/backoffice_submission_roles-None
new file mode 100644
index 0000000000000000000000000000000000000000..a7a08cd97a4d4db54f3d0cf5e44bfcace25d886f
GIT binary patch
diff --git a/tests/data/oldpickledata/carddefs/1 b/tests/data/oldpickledata/carddefs/1
new file mode 100644
index 0000000000000000000000000000000000000000..4dfac670022b30438e9fcf38a958b4e9be2c2a49
GIT binary patch
diff --git a/tests/data/oldpickledata/form-foo/.indexes/concerned_roles/concerned_roles-_submitter b/tests/data/oldpickledata/form-foo/.indexes/concerned_roles/concerned_roles-_submitter
new file mode 100644
index 0000000000000000000000000000000000000000..a7a08cd97a4d4db54f3d0cf5e44bfcace25d886f
GIT binary patch
diff --git a/tests/data/oldpickledata/form-foo/.indexes/status/status-None b/tests/data/oldpickledata/form-foo/.indexes/status/status-None
new file mode 100644
index 0000000000000000000000000000000000000000..a7a08cd97a4d4db54f3d0cf5e44bfcace25d886f
GIT binary patch
diff --git a/tests/data/oldpickledata/form-foo/.indexes/user_id/user_id-None b/tests/data/oldpickledata/form-foo/.indexes/user_id/user_id-None
new file mode 100644
index 0000000000000000000000000000000000000000..a7a08cd97a4d4db54f3d0cf5e44bfcace25d886f
GIT binary patch
diff --git a/tests/data/oldpickledata/form-foo/.indexes/workflow_roles/workflow_roles-None b/tests/data/oldpickledata/form-foo/.indexes/workflow_roles/workflow_roles-None
new file mode 100644
index 0000000000000000000000000000000000000000..a7a08cd97a4d4db54f3d0cf5e44bfcace25d886f
GIT binary patch
diff --git a/tests/data/oldpickledata/form-foo/.max_id b/tests/data/oldpickledata/form-foo/.max_id
new file mode 100644
index 00000000..56a6051c
--- /dev/null
+++ b/tests/data/oldpickledata/form-foo/.max_id
@@ -0,0 +1 @@
+1
\ No newline at end of file
diff --git a/tests/data/oldpickledata/form-foo/1 b/tests/data/oldpickledata/form-foo/1
new file mode 100644
index 0000000000000000000000000000000000000000..a2c21ce3f0b0c77c1c51f932eb079f4266a9dcc8
GIT binary patch
diff --git a/tests/data/oldpickledata/formdefs/.indexes/backoffice_submission_roles/backoffice_submission_roles-None b/tests/data/oldpickledata/formdefs/.indexes/backoffice_submission_roles/backoffice_submission_roles-None
new file mode 100644
index 0000000000000000000000000000000000000000..a7a08cd97a4d4db54f3d0cf5e44bfcace25d886f
GIT binary patch
diff --git a/tests/data/oldpickledata/formdefs/1 b/tests/data/oldpickledata/formdefs/1
new file mode 100644
index 0000000000000000000000000000000000000000..df816a5e005709c169b7a6291ec7b4c4fd6b601b
GIT binary patch
diff --git a/tests/test_storage.py b/tests/test_storage.py
index 4a9776a8..5ebbafb7 100644
--- a/tests/test_storage.py
+++ b/tests/test_storage.py
@@ -1,6 +1,5 @@
 import datetime
 import os
-import sys
 import shutil
 import time
 import random
@@ -8,7 +7,8 @@ import random
 import pytest
 
 from quixote import cleanup
-from wcs import publisher
+from wcs.carddef import CardDef
+from wcs.formdef import FormDef
 from wcs.qommon.storage import StorableObject, cache_umask
 import wcs.qommon.storage as st
 
@@ -452,3 +452,18 @@ def test_umask():
     cache_umask()
     test.store()
     assert (os.stat(test.get_object_filename()).st_mode % 0o1000) == 0o664
+
+
+def test_load_old_pickle():
+    # check picklized old data (name without 'WCS:' prefix)
+    # formdata
+    shutil.copytree(os.path.join(os.path.dirname(__file__), 'data', 'oldpickledata', 'formdefs'), os.path.join(pub.app_dir, 'formdefs'))
+    shutil.copytree(os.path.join(os.path.dirname(__file__), 'data', 'oldpickledata', 'form-foo'), os.path.join(pub.app_dir, 'form-foo'))
+    formdef = FormDef.select()[0]
+    formdef.data_class().select()
+
+    # carddata
+    shutil.copytree(os.path.join(os.path.dirname(__file__), 'data', 'oldpickledata', 'carddefs'), os.path.join(pub.app_dir, 'carddefs'))
+    shutil.copytree(os.path.join(os.path.dirname(__file__), 'data', 'oldpickledata', 'card-bar'), os.path.join(pub.app_dir, 'card-bar'))
+    carddef = CardDef.select()[0]
+    carddef.data_class().select()
diff --git a/wcs/carddef.py b/wcs/carddef.py
index f9e7df1a..3d7023ef 100644
--- a/wcs/carddef.py
+++ b/wcs/carddef.py
@@ -40,8 +40,8 @@ class CardDef(FormDef):
     def data_class(self, mode=None):
         if not 'carddef' in sys.modules:
             sys.modules['carddef'] = sys.modules[__name__]
-        if hasattr(sys.modules['carddef'], self.url_name.title()):
-            data_class = getattr(sys.modules['carddef'], self.url_name.title())
+        if hasattr(sys.modules['carddef'], self.data_class_name):
+            data_class = getattr(sys.modules['carddef'], self.data_class_name)
             # only use existing data class if it has a reference to this actual
             # carddef
             if data_class._formdef is self:
@@ -49,17 +49,17 @@ class CardDef(FormDef):
         if (get_publisher().is_using_postgresql() and not mode == 'files') or mode == 'sql':
             from . import sql
             table_name = sql.get_formdef_table_name(self)
-            cls = types.ClassType(self.url_name.title(), (sql.SqlCardData,),
+            cls = types.ClassType(self.data_class_name, (sql.SqlCardData,),
                         {'_formdef': self,
                          '_table_name': table_name})
             actions = sql.do_formdef_tables(self)
         else:
-            cls = types.ClassType(self.url_name.title(), (CardData,),
+            cls = types.ClassType(self.data_class_name, (CardData,),
                         {'_names': 'card-%s' % self.internal_identifier,
                          '_formdef': self})
             actions = []
-        setattr(sys.modules['carddef'], self.url_name.title(), cls)
-        setattr(sys.modules['wcs.carddef'], self.url_name.title(), cls)
+        setattr(sys.modules['carddef'], self.data_class_name, cls)
+        setattr(sys.modules['wcs.carddef'], self.data_class_name, cls)
 
         if actions:
             for action in actions:
diff --git a/wcs/ctl/management/commands/convert_to_sql.py b/wcs/ctl/management/commands/convert_to_sql.py
index c04bbd3d..c211ee29 100644
--- a/wcs/ctl/management/commands/convert_to_sql.py
+++ b/wcs/ctl/management/commands/convert_to_sql.py
@@ -124,7 +124,7 @@ class Command(BaseCommand):
             # run and the eventual changes properly saved.
             for id in data_class.keys():
                 formdata = data_class.get(id)
-            delattr(sys.modules['formdef'], formdef.url_name.title())
+            delattr(sys.modules['formdef'], formdef.data_class_name)
 
             # once this is done, reload and store everything in postgresql
             sql_data_class = formdef.data_class(mode='sql')
diff --git a/wcs/formdata.py b/wcs/formdata.py
index 361ae3cc..73238613 100644
--- a/wcs/formdata.py
+++ b/wcs/formdata.py
@@ -289,8 +289,9 @@ class FormData(StorableObject):
         # particular object, as it is required by pickle (or it will raise
         # "Can't pickle %r: it's not the same object as %s.%s" if the class
         # object has been changed in the course of the request).
-        setattr(sys.modules[self._formdef.pickle_module_name], self._formdef.url_name.title(), self.__class__)
-        setattr(sys.modules['wcs.%s' % self._formdef.pickle_module_name], self._formdef.url_name.title(), self.__class__)
+        print('store', self._formdef, self._formdef.pickle_module_name, self._formdef.data_class_name, self.__class__)
+        setattr(sys.modules[self._formdef.pickle_module_name], self._formdef.data_class_name, self.__class__)
+        setattr(sys.modules['wcs.%s' % self._formdef.pickle_module_name], self._formdef.data_class_name, self.__class__)
         has_id = (self.id is not None)
         if has_id:
             self.set_auto_fields()
diff --git a/wcs/formdef.py b/wcs/formdef.py
index 7e8a5799..07d0eb4c 100644
--- a/wcs/formdef.py
+++ b/wcs/formdef.py
@@ -260,11 +260,15 @@ class FormDef(StorableObject):
             conn.commit()
             cur.close()
 
+    @property
+    def data_class_name(self):
+        return 'WCS:%s' % self.url_name.title()
+
     def data_class(self, mode=None):
         if not 'formdef' in sys.modules:
             sys.modules['formdef'] = sys.modules[__name__]
-        if hasattr(sys.modules['formdef'], self.url_name.title()):
-            data_class = getattr(sys.modules['formdef'], self.url_name.title())
+        if hasattr(sys.modules['formdef'], self.data_class_name):
+            data_class = getattr(sys.modules['formdef'], self.data_class_name)
             # only use existing data class if it has a reference to this actual
             # formdef
             if data_class._formdef is self:
@@ -272,17 +276,17 @@ class FormDef(StorableObject):
         if (get_publisher().is_using_postgresql() and not mode == 'files') or mode == 'sql':
             from . import sql
             table_name = sql.get_formdef_table_name(self)
-            cls = types.ClassType(self.url_name.title(), (sql.SqlFormData,),
+            cls = types.ClassType(self.data_class_name, (sql.SqlFormData,),
                         {'_formdef': self,
                          '_table_name': table_name})
             actions = sql.do_formdef_tables(self)
         else:
-            cls = types.ClassType(self.url_name.title(), (FormData,),
+            cls = types.ClassType(self.data_class_name, (FormData,),
                         {'_names': 'form-%s' % self.internal_identifier,
                          '_formdef': self})
             actions = []
-        setattr(sys.modules['formdef'], self.url_name.title(), cls)
-        setattr(sys.modules['wcs.formdef'], self.url_name.title(), cls)
+        setattr(sys.modules['formdef'], self.data_class_name, cls)
+        setattr(sys.modules['wcs.formdef'], self.data_class_name, cls)
 
         if actions:
             for action in actions:
diff --git a/wcs/publisher.py b/wcs/publisher.py
index 5e6e017a..b1889cb5 100644
--- a/wcs/publisher.py
+++ b/wcs/publisher.py
@@ -65,6 +65,10 @@ class UnpicklerClass(pickle.Unpickler):
             module = 'wcs.%s' % module
         __import__(module)
         mod = sys.modules[module]
+        if module == 'wcs.formdef' and name != 'FormDef' and not name.startswith('WCS:'):
+            name = 'WCS:%s' % name
+        elif module == 'wcs.carddef' and name != 'CardDef' and not name.startswith('WCS:'):
+            name = 'WCS:%s' % name
         klass = getattr(mod, name)
         return klass
 
-- 
2.28.0

