misc: prefix CardData & FormData class name to avoid conflict (#46588)

This commit is contained in:
Lauréline Guérin 2020-09-17 14:48:37 +02:00
parent eb16118351
commit 8a0985332c
No known key found for this signature in database
GPG Key ID: 1FAB9B9B4F93D473
10 changed files with 40 additions and 17 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -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()

View File

@ -41,8 +41,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:
@ -50,17 +50,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:

View File

@ -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')

View File

@ -289,8 +289,8 @@ 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__)
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()

View File

@ -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:

View File

@ -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