Commit 557c20bd authored by Ayush Tiwari's avatar Ayush Tiwari

Products.ERP5Catalog: EPR5-ify catalog.

Move from SQLCatalog to ERP5Catalog as the default Catalog inside ERP5.
The major difference is use of Products.ERP5Type.Core.Folder as Catalog
base class.

Significant addition/changes in
-------------------------------

  ERP5Catalog class:
    Inherit from Catalog class from Products.ZSQLCatalog.SQLCatalog instead of copy-pasting the whole code again.
    Monkey patch some property setters and getters to maintain consistency
    Override getCatalogMethodIds cause it uses global variable in SQLCatalog.Catalog
    Add FilterDict and Filter class to have consistency with `filter_dict` attribute of SQLCatalog

  BusinessTemplate:
    Update BusinessTemplate installation with updated filter_dict
    Also, use dynamic migration while installing the catalog method objects for
    bt5. This way we have SQL Methods migrated just after installation.

  Tests:
    Update tests according to changes in portal_catalog

  SQLCatalog, testZSQLCatalog:
    Cleanup for unusable functions
parent c2809b85
...@@ -153,12 +153,12 @@ SEPARATELY_EXPORTED_PROPERTY_DICT = { ...@@ -153,12 +153,12 @@ SEPARATELY_EXPORTED_PROPERTY_DICT = {
def _getCatalog(acquisition_context): def _getCatalog(acquisition_context):
""" """
Return the id of the SQLCatalog which correspond to the current BT. Return the id of the Catalog which correspond to the current BT.
""" """
catalog_method_id_list = acquisition_context.getTemplateCatalogMethodIdList() catalog_method_id_list = acquisition_context.getTemplateCatalogMethodIdList()
if len(catalog_method_id_list) == 0: if len(catalog_method_id_list) == 0:
try: try:
return acquisition_context.getPortalObject().portal_catalog.objectIds('SQLCatalog')[0] return acquisition_context.getPortalObject().portal_catalog.objectIds()[0]
except IndexError: except IndexError:
return None return None
catalog_method_id = catalog_method_id_list[0] catalog_method_id = catalog_method_id_list[0]
...@@ -1459,7 +1459,7 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -1459,7 +1459,7 @@ class ObjectTemplateItem(BaseTemplateItem):
# an object which cannot (e.g. External Method). # an object which cannot (e.g. External Method).
LOG('BusinessTemplate', WARNING, LOG('BusinessTemplate', WARNING,
'could not restore %r in %r' % (subobject_id, obj)) 'could not restore %r in %r' % (subobject_id, obj))
if obj.meta_type in ('Z SQL Method',): if obj.meta_type in ('Z SQL Method', 'ERP5 SQL Method'):
fixZSQLMethod(portal, obj) fixZSQLMethod(portal, obj)
# portal transforms specific initialization # portal transforms specific initialization
elif obj.meta_type in ('Transform', 'TransformsChain'): elif obj.meta_type in ('Transform', 'TransformsChain'):
...@@ -1951,7 +1951,7 @@ class SkinTemplateItem(ObjectTemplateItem): ...@@ -1951,7 +1951,7 @@ class SkinTemplateItem(ObjectTemplateItem):
if not force and update_dict.get(relative_url) == 'nothing': if not force and update_dict.get(relative_url) == 'nothing':
continue continue
folder = self.unrestrictedResolveValue(p, relative_url) folder = self.unrestrictedResolveValue(p, relative_url)
for obj in folder.objectValues(spec=('Z SQL Method',)): for obj in folder.objectValues(spec=('Z SQL Method', 'ERP5 SQL Method')):
fixZSQLMethod(p, obj) fixZSQLMethod(p, obj)
if folder.aq_parent.meta_type == 'CMF Skins Tool': if folder.aq_parent.meta_type == 'CMF Skins Tool':
registerSkinFolder(skin_tool, folder) registerSkinFolder(skin_tool, folder)
...@@ -2891,14 +2891,26 @@ class CatalogMethodTemplateItem(ObjectTemplateItem): ...@@ -2891,14 +2891,26 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
"""Extracts properties for a given method in the catalog. """Extracts properties for a given method in the catalog.
Returns a mapping of property name -> boolean """ Returns a mapping of property name -> boolean """
method_properties = PersistentMapping() method_properties = PersistentMapping()
for prop in catalog._properties:
if catalog.meta_type == 'ERP5 Catalog':
property_list = list(catalog.propertyMap())
else:
property_list = list(catalog._properties)
for prop in property_list:
if prop.get('select_variable') == 'getCatalogMethodIds': if prop.get('select_variable') == 'getCatalogMethodIds':
# In case the properties are defined via property sheet 'Catalog', the
# object would have two IDs if it is of type 'selection' or
# 'multiple_selection': 'id' and 'base_id', usage of base_id is preferred
# while building objects as it maintains consistency between the old
# catalog and new erp5 catalog
prop_id = prop.get('base_id', prop['id'])
if prop['type'] == 'selection' and \ if prop['type'] == 'selection' and \
getattr(catalog, prop['id']) == method_id: getattr(catalog, prop_id) == method_id:
method_properties[prop['id']] = 1 method_properties[prop_id] = 1
elif prop['type'] == 'multiple selection' and \ elif prop['type'] == 'multiple selection' and \
method_id in getattr(catalog, prop['id']): method_id in getattr(catalog, prop_id):
method_properties[prop['id']] = 1 method_properties[prop_id] = 1
return method_properties return method_properties
def build(self, context, **kw): def build(self, context, **kw):
...@@ -2915,9 +2927,11 @@ class CatalogMethodTemplateItem(ObjectTemplateItem): ...@@ -2915,9 +2927,11 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
for obj in self._objects.values(): for obj in self._objects.values():
method_id = obj.id method_id = obj.id
# Check if the method exists in catalog before getting filter dict
if method_id in catalog.objectIds():
self._method_properties[method_id] = self._extractMethodProperties( self._method_properties[method_id] = self._extractMethodProperties(
catalog, method_id) catalog, method_id)
filter = catalog.filter_dict.get(method_id, {}) filter = catalog._getFilterDict().get(method_id, {})
self._is_filtered_archive[method_id] = filter.get('filtered', 0) self._is_filtered_archive[method_id] = filter.get('filtered', 0)
for method in catalog_method_filter_list: for method in catalog_method_filter_list:
property = method[8:-8] property = method[8:-8]
...@@ -2983,6 +2997,32 @@ class CatalogMethodTemplateItem(ObjectTemplateItem): ...@@ -2983,6 +2997,32 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
force = kw.get('force') force = kw.get('force')
values = [] values = []
# When the default catalog is of 'ERP5 Catalog' meta_type, its better to ..
# convert all the CatalogMethodTemplateItems in the current BT to the
# allowed types for ERP5 Catalog, i.e, to ERP5 SQLMethod and ERP5 Python Script
# and update the self._objects dict accordingly
if catalog.meta_type == 'ERP5 Catalog':
import erp5
from Products.ERP5.Extensions.CheckPortalTypes import changeObjectClass
# We need the dynamic portal_type classes for changing object classes
sql_class = getattr(erp5.portal_type, 'SQL Method')
script_class = getattr(erp5.portal_type, 'Python Script')
portal = self.getPortalObject()
# Will be modifying dict, so better to use .items()
# XXX: In python3 it should be .copy.items().
for path, obj in self._objects.items():
method = self.unrestrictedResolveValue(portal, path)
method_id = path.split('/')[-1]
if method.meta_type == 'Z SQL Method':
method = changeObjectClass(catalog, method_id, sql_class)
if method.meta_type == 'Script (Python)':
method = changeObjectClass(catalog, method_id, script_class)
method._compile()
new_obj = method.aq_base
self._objects[path] = new_obj
if force: # get all objects if force: # get all objects
values = self._objects.values() values = self._objects.values()
else: # get only selected object else: # get only selected object
...@@ -3009,6 +3049,7 @@ class CatalogMethodTemplateItem(ObjectTemplateItem): ...@@ -3009,6 +3049,7 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
new_value.sort() new_value.sort()
setattr(catalog, key, tuple(new_value)) setattr(catalog, key, tuple(new_value))
method = catalog._getOb(method_id)
# Restore filter # Restore filter
if self._is_filtered_archive.get(method_id, 0): if self._is_filtered_archive.get(method_id, 0):
expression = self._filter_expression_archive[method_id] expression = self._filter_expression_archive[method_id]
...@@ -3017,16 +3058,14 @@ class CatalogMethodTemplateItem(ObjectTemplateItem): ...@@ -3017,16 +3058,14 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
expr_instance = Expression(expression) expr_instance = Expression(expression)
else: else:
expr_instance = None expr_instance = None
catalog.filter_dict[method_id] = PersistentMapping() method.setFiltered(1)
catalog.filter_dict[method_id]['filtered'] = 1 method.setExpression(expression)
catalog.filter_dict[method_id]['expression'] = expression method.setExpressionInstance(expr_instance)
catalog.filter_dict[method_id]['expression_instance'] = expr_instance method.setExpressionCacheKey(
catalog.filter_dict[method_id]['expression_cache_key'] = \ self._filter_expression_cache_key_archive.get(method_id, ()))
self._filter_expression_cache_key_archive.get(method_id, ()) method.setTypeList(self._filter_type_archive.get(method_id, ()))
catalog.filter_dict[method_id]['type'] = \ else:
self._filter_type_archive.get(method_id, ()) method.setFiltered(0)
elif method_id in catalog.filter_dict.keys():
catalog.filter_dict[method_id]['filtered'] = 0
# backward compatibility # backward compatibility
if hasattr(self, '_is_catalog_list_method_archive'): if hasattr(self, '_is_catalog_list_method_archive'):
...@@ -3082,18 +3121,34 @@ class CatalogMethodTemplateItem(ObjectTemplateItem): ...@@ -3082,18 +3121,34 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
values.append(value) values.append(value)
for obj in values: for obj in values:
method_id = obj.id method_id = obj.id
if catalog.meta_type == 'ERP5 Catalog':
property_list = list(catalog.propertyMap())
else:
property_list = list(catalog._properties)
# remove method references in portal_catalog # remove method references in portal_catalog
for catalog_prop in catalog._properties: for catalog_prop in property_list:
if catalog_prop.get('select_variable') == 'getCatalogMethodIds'\ if catalog_prop.get('select_variable') == 'getCatalogMethodIds'\
and catalog_prop['type'] == 'multiple selection': and catalog_prop['type'] == 'multiple selection':
old_value = getattr(catalog, catalog_prop['id'], ()) # In case the properties are defined via property sheet 'Catalog', the
# object would have two IDs if it is of type 'selection' or
# 'multiple_selection': 'id' and 'base_id', usage of base_id is preferred
# while building objects as it maintains consistency between the old
# catalog and new erp5 catalog
catalog_prop_id = catalog_prop.get('base_id', catalog_prop['id'])
old_value = getattr(catalog, catalog_prop_id, ())
if method_id in old_value: if method_id in old_value:
new_value = list(old_value) new_value = list(old_value)
new_value.remove(method_id) new_value.remove(method_id)
setattr(catalog, catalog_prop['id'], new_value) # Better to set the attribute value as tuple as it would be consistent
# with both SQL Catalog and ERP5 Catalog.
setattr(catalog, catalog_prop_id, tuple(new_value))
if method_id in catalog.filter_dict: filter_dict = catalog._getFilterDict()
del catalog.filter_dict[method_id] try:
del filter_dict[method_id]
except KeyError:
pass
# uninstall objects # uninstall objects
ObjectTemplateItem.uninstall(self, context, **kw) ObjectTemplateItem.uninstall(self, context, **kw)
......
...@@ -191,8 +191,10 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): ...@@ -191,8 +191,10 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor):
sql_uncatalog_object.remove(method_id) sql_uncatalog_object.remove(method_id)
sql_uncatalog_object.sort() sql_uncatalog_object.sort()
catalog.sql_uncatalog_object = tuple(sql_uncatalog_object) catalog.sql_uncatalog_object = tuple(sql_uncatalog_object)
if method_id in catalog.filter_dict: try:
del catalog.filter_dict[method_id] del catalog._getFilterDict()[method_id]
except KeyError:
pass
for obj_id in ('another_file', 'test_document', 'dummy_type_provider'): for obj_id in ('another_file', 'test_document', 'dummy_type_provider'):
if obj_id in self.portal.objectIds(): if obj_id in self.portal.objectIds():
self.portal.manage_delObjects([obj_id]) self.portal.manage_delObjects([obj_id])
...@@ -1585,9 +1587,9 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): ...@@ -1585,9 +1587,9 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor):
catalog = pc.getSQLCatalog() catalog = pc.getSQLCatalog()
self.assertTrue(catalog is not None) self.assertTrue(catalog is not None)
method_id = "z_fake_method" method_id = "z_fake_method"
addSQLMethod = catalog.manage_addProduct['ZSQLMethods'].manage_addZSQLMethod addSQLMethod = catalog.newContent
addSQLMethod(id=method_id, title='', connection_id='erp5_sql_connection', addSQLMethod(portal_type='SQL Method', id=method_id, title='',
arguments='', template='') connection_id='erp5_sql_connection', arguments_src='', src='')
zsql_method = catalog._getOb(method_id, None) zsql_method = catalog._getOb(method_id, None)
self.assertTrue(zsql_method is not None) self.assertTrue(zsql_method is not None)
sequence.edit(zsql_method_id = method_id) sequence.edit(zsql_method_id = method_id)
...@@ -1599,21 +1601,20 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): ...@@ -1599,21 +1601,20 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor):
# set filter for this method # set filter for this method
expression = 'python: context.isPredicate()' expression = 'python: context.isPredicate()'
expr_instance = Expression(expression) expr_instance = Expression(expression)
catalog.filter_dict[method_id] = PersistentMapping() zsql_method.setFiltered(1)
catalog.filter_dict[method_id]['filtered'] = 1 zsql_method.setExpression(expression)
catalog.filter_dict[method_id]['expression'] = expression zsql_method.setExpressionInstance(expr_instance)
catalog.filter_dict[method_id]['expression_instance'] = expr_instance zsql_method.setExpressionCacheKey('portal_type')
catalog.filter_dict[method_id]['expression_cache_key'] = 'portal_type', zsql_method.setTypeList([])
catalog.filter_dict[method_id]['type'] = []
def stepCreateUpdateCatalogMethod(self, sequence=None, **kw): def stepCreateUpdateCatalogMethod(self, sequence=None, **kw):
pc = self.getCatalogTool() pc = self.getCatalogTool()
catalog = pc.getSQLCatalog() catalog = pc.getSQLCatalog()
self.assertTrue(catalog is not None) self.assertTrue(catalog is not None)
method_id = "z_fake_method" method_id = "z_fake_method"
addSQLMethod = catalog.manage_addProduct['ZSQLMethods'].manage_addZSQLMethod addSQLMethod = catalog.newContent
addSQLMethod(id=method_id, title='', connection_id='erp5_sql_connection', addSQLMethod(portal_type='SQL Method', id=method_id, title='',
arguments='', template='') connection_id='erp5_sql_connection', arguments_src='', src='')
zsql_method = catalog._getOb(method_id, None) zsql_method = catalog._getOb(method_id, None)
self.assertTrue(zsql_method is not None) self.assertTrue(zsql_method is not None)
sequence.edit(zsql_method_id = method_id) sequence.edit(zsql_method_id = method_id)
...@@ -1625,20 +1626,19 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): ...@@ -1625,20 +1626,19 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor):
# set filter for this method # set filter for this method
expression = 'python: context.isDelivery()' expression = 'python: context.isDelivery()'
expr_instance = Expression(expression) expr_instance = Expression(expression)
catalog.filter_dict[method_id] = PersistentMapping() zsql_method.setFiltered(1)
catalog.filter_dict[method_id]['filtered'] = 1 zsql_method.setExpression(expression)
catalog.filter_dict[method_id]['expression'] = expression zsql_method.setExpressionInstance(expr_instance)
catalog.filter_dict[method_id]['expression_instance'] = expr_instance zsql_method.setExpressionCacheKey('portal_type')
catalog.filter_dict[method_id]['expression_cache_key'] = 'portal_type', zsql_method.setTypeList([])
catalog.filter_dict[method_id]['type'] = []
def stepCreateNewCatalogMethod(self, sequence=None, **kw): def stepCreateNewCatalogMethod(self, sequence=None, **kw):
pc = self.getCatalogTool() pc = self.getCatalogTool()
catalog = pc.getSQLCatalog() catalog = pc.getSQLCatalog()
method_id = "z_another_fake_method" method_id = "z_another_fake_method"
addSQLMethod =catalog.manage_addProduct['ZSQLMethods'].manage_addZSQLMethod addSQLMethod =catalog.newContent
addSQLMethod(id=method_id, title='', connection_id='erp5_sql_connection', addSQLMethod(portal_type='SQL Method', id=method_id, title='',
arguments='', template='') connection_id='erp5_sql_connection', arguments_src='', src='')
zsql_method = catalog._getOb(method_id, None) zsql_method = catalog._getOb(method_id, None)
self.assertTrue(zsql_method is not None) self.assertTrue(zsql_method is not None)
sequence.edit(another_zsql_method_id = method_id) sequence.edit(another_zsql_method_id = method_id)
...@@ -1717,11 +1717,12 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): ...@@ -1717,11 +1717,12 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor):
# check catalog properties # check catalog properties
self.assertIn(method_id, catalog.sql_uncatalog_object) self.assertIn(method_id, catalog.sql_uncatalog_object)
# check filter # check filter
filter_dict = catalog.filter_dict[method_id] filter_dict = catalog._getFilterDict()
self.assertEqual(filter_dict['filtered'], 1) filter = filter_dict[method_id]
self.assertEqual(filter_dict['expression'], 'python: context.isPredicate()') self.assertItemsEqual(filter['expression_cache_key'], ['portal_type'])
self.assertEqual(filter_dict['expression_cache_key'], ('portal_type',)) self.assertEqual(filter['type'], [])
self.assertEqual(filter_dict['type'], ()) self.assertEqual(filter['filtered'], 1)
self.assertEqual(filter['expression'], 'python: context.isPredicate()')
def stepCheckUpdatedCatalogMethodExists(self, sequence=None, **kw): def stepCheckUpdatedCatalogMethodExists(self, sequence=None, **kw):
pc = self.getCatalogTool() pc = self.getCatalogTool()
...@@ -1733,11 +1734,12 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): ...@@ -1733,11 +1734,12 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor):
# check catalog properties # check catalog properties
self.assertIn(method_id, catalog.sql_uncatalog_object) self.assertIn(method_id, catalog.sql_uncatalog_object)
# check filter # check filter
filter_dict = catalog.filter_dict[method_id] filter_dict = catalog._getFilterDict()
self.assertEqual(filter_dict['filtered'], 1) filter = filter_dict[method_id]
self.assertEqual(filter_dict['expression'], 'python: context.isDelivery()') self.assertItemsEqual(filter['expression_cache_key'], ['portal_type'])
self.assertEqual(filter_dict['expression_cache_key'], ('portal_type',)) self.assertEqual(filter['type'], [])
self.assertEqual(filter_dict['type'], ()) self.assertEqual(filter['filtered'], 1)
self.assertEqual(filter['expression'], 'python: context.isDelivery()')
def stepCheckCatalogMethodRemoved(self, sequence=None, **kw): def stepCheckCatalogMethodRemoved(self, sequence=None, **kw):
""" """
...@@ -1752,7 +1754,8 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): ...@@ -1752,7 +1754,8 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor):
# check catalog properties # check catalog properties
self.assertNotIn(method_id, catalog.sql_uncatalog_object) self.assertNotIn(method_id, catalog.sql_uncatalog_object)
# check filter # check filter
self.assertNotIn(method_id, catalog.filter_dict.keys()) with self.assertRaises(KeyError):
catalog._getFilterDict()[method_id]
def stepRemoveCatalogMethod(self, sequence=None, **kw): def stepRemoveCatalogMethod(self, sequence=None, **kw):
""" """
...@@ -1772,8 +1775,8 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): ...@@ -1772,8 +1775,8 @@ class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor):
catalog.sql_uncatalog_object = tuple(sql_uncatalog_object) catalog.sql_uncatalog_object = tuple(sql_uncatalog_object)
self.assertNotIn(method_id, catalog.sql_uncatalog_object) self.assertNotIn(method_id, catalog.sql_uncatalog_object)
# remove filter # remove filter
del catalog.filter_dict[method_id] with self.assertRaises(KeyError):
self.assertNotIn(method_id, catalog.filter_dict.keys()) catalog._getFilterDict()[method_id]
# Related key, Result key and table, and others # Related key, Result key and table, and others
def stepCreateKeysAndTable(self, sequence=list, **kw): def stepCreateKeysAndTable(self, sequence=list, **kw):
......
This diff is collapsed.
...@@ -38,8 +38,9 @@ document_classes = updateGlobals( this_module, globals(), permissions_module = P ...@@ -38,8 +38,9 @@ document_classes = updateGlobals( this_module, globals(), permissions_module = P
# Define object classes and tools # Define object classes and tools
from Tool import ArchiveTool from Tool import ArchiveTool
from Document import ERP5Catalog
import CatalogTool import CatalogTool
object_classes = () object_classes = (ERP5Catalog.ERP5Catalog,)
  • Is this object_classes really needed ? my understanding is that object_classes is only for classes added in the ZMI

    Screenshot_2017-11-24_at_19.01.14

    I have not investigated in details, but this seem to cause this error:

    ...
      File "/srv/slapgrid/slappart0/srv/runner/software/6da59345a2fbf81362daa2cbacb4700e/parts/erp5/product/ERP5Catalog/__init__.py", line 57, in initialize
        content_classes = content_classes)
      File "/srv/slapgrid/slappart0/srv/runner/software/6da59345a2fbf81362daa2cbacb4700e/parts/erp5/product/ERP5Type/Utils.py", line 1217, in initializeProduct
        constructors = c.constructors,
    AttributeError: type object 'ERP5Catalog' has no attribute 'constructors'

    errors when "restoring" an instance with runUnitTest (ie. using runUnitTest --load after runUnitTest --save )

  • Thanks for pointing it out. I check it again. And remove it if not needed. But I hope this error doesn't interfere with migration or installation.

  • Thanks. I think it can cause problem in tests, in projects specific tests we usually run with --load to speed things up.

Please register or sign in to reply
portal_tools = (CatalogTool.CatalogTool, portal_tools = (CatalogTool.CatalogTool,
ArchiveTool.ArchiveTool) ArchiveTool.ArchiveTool)
content_classes = () content_classes = ()
......
...@@ -73,12 +73,12 @@ CREATE TABLE alternate_roles_and_users ( ...@@ -73,12 +73,12 @@ CREATE TABLE alternate_roles_and_users (
'alternate_roles_and_users'] 'alternate_roles_and_users']
# Configure sql method to insert this table # Configure sql method to insert this table
sql_catalog.manage_addProduct['ZSQLMethods'].manage_addZSQLMethod( sql_catalog.newContent(portal_type='SQL Method',
id='z_catalog_alternate_roles_and_users_list', id='z_catalog_alternate_roles_and_users_list',
title='', title='',
connection_id='erp5_sql_connection', connection_id='erp5_sql_connection',
arguments="\n".join(['uid', 'alternate_security_uid']), arguments_src="\n".join(['uid', 'alternate_security_uid']),
template="""REPLACE INTO alternate_roles_and_users VALUES src="""REPLACE INTO alternate_roles_and_users VALUES
<dtml-in prefix="loop" expr="_.range(_.len(uid))"> <dtml-in prefix="loop" expr="_.range(_.len(uid))">
( <dtml-sqlvar expr="uid[loop_item]" type="int">, ( <dtml-sqlvar expr="uid[loop_item]" type="int">,
<dtml-sqlvar expr="alternate_security_uid[loop_item]" type="int" optional> <dtml-sqlvar expr="alternate_security_uid[loop_item]" type="int" optional>
......
...@@ -67,7 +67,7 @@ def manage_page_footer(self): ...@@ -67,7 +67,7 @@ def manage_page_footer(self):
+ ['printed', 'same_type', 'string', 'sequence', 'random', 'DateTime', + ['printed', 'same_type', 'string', 'sequence', 'random', 'DateTime',
'whrandom', 'reorder', 'sets', 'test', 'math']) 'whrandom', 'reorder', 'sets', 'test', 'math'])
live_check_python_script = 1 # XXX make it a preference ? live_check_python_script = 1 # XXX make it a preference ?
elif document.meta_type in ('Z SQL Method', ): elif document.meta_type in ('Z SQL Method', 'ERP5 SQL Method'):
mode = 'sql' mode = 'sql'
textarea_selector = 'textarea[name="template:text"]' textarea_selector = 'textarea[name="template:text"]'
elif document.meta_type in ('Page Template', 'ERP5 OOo Template', ): elif document.meta_type in ('Page Template', 'ERP5 OOo Template', ):
......
...@@ -3306,9 +3306,10 @@ class TestAccessControl(ERP5TypeTestCase): ...@@ -3306,9 +3306,10 @@ class TestAccessControl(ERP5TypeTestCase):
def afterSetUp(self): def afterSetUp(self):
self.login() self.login()
self.getCatalogTool().getSQLCatalog().filter_dict['z_catalog_object_list'] \ method = self.getCatalogTool().getSQLCatalog()._getOb('z_catalog_object_list')
= dict(filtered=1, type=[], expression=self.expression, method.setFiltered(1)
expression_instance=Expression(self.expression)) method.setExpression(self.expression)
method.setExpressionInstance(Expression(self.expression))
createZODBPythonScript(self.getSkinsTool().custom, createZODBPythonScript(self.getSkinsTool().custom,
'Base_immediateReindexObject', 'Base_immediateReindexObject',
......
...@@ -744,8 +744,7 @@ class Catalog(Folder, ...@@ -744,8 +744,7 @@ class Catalog(Folder,
for item in item_list: for item in item_list:
f.write(' <item type="str">%s</item>\n' % escape(str(item))) f.write(' <item type="str">%s</item>\n' % escape(str(item)))
f.write(' </property>\n') f.write(' </property>\n')
# XXX Although filters are not properties, output filters here. # Filters are now propeties in ERP5 SQL Method(s)
# XXX Ideally, filters should be properties in Z SQL Methods, shouldn't they?
filter_dict = self._getFilterDict() filter_dict = self._getFilterDict()
if filter_dict: if filter_dict:
for filter_id, filter_def in sorted(filter_dict.iteritems()): for filter_id, filter_def in sorted(filter_dict.iteritems()):
...@@ -2663,179 +2662,6 @@ class Catalog(Folder, ...@@ -2663,179 +2662,6 @@ class Catalog(Folder,
method = self._getOb(self.getSqlReadRecordedObjectList()) method = self._getOb(self.getSqlReadRecordedObjectList())
return method(catalog=catalog) return method(catalog=catalog)
# Filtering
security.declareProtected(manage_zcatalog_entries, 'manage_editFilter')
def manage_editFilter(self, REQUEST=None, RESPONSE=None, URL1=None):
"""
This methods allows to set a filter on each zsql method called,
so we can test if we should or not call a zsql method, so we can
increase a lot the speed.
"""
if withCMF:
method_id_list = [zsql_method.id for zsql_method in self.getFilterableMethodList()]
# Remove unused filters.
for id in self.filter_dict.keys():
if id not in method_id_list:
del self.filter_dict[id]
for id in method_id_list:
# We will first look if the filter is activated
if id not in self.filter_dict:
self.filter_dict[id] = PersistentMapping()
if REQUEST.has_key('%s_box' % id):
self.filter_dict[id]['filtered'] = 1
else:
self.filter_dict[id]['filtered'] = 0
expression = REQUEST.get('%s_expression' % id, '').strip()
self.filter_dict[id]['expression'] = expression
if expression:
self.filter_dict[id]['expression_instance'] = Expression(expression)
else:
self.filter_dict[id]['expression_instance'] = None
if REQUEST.has_key('%s_type' % id):
list_type = REQUEST['%s_type' % id]
if isinstance(list_type, str):
list_type = [list_type]
self.filter_dict[id]['type'] = list_type
else:
self.filter_dict[id]['type'] = []
self.filter_dict[id]['expression_cache_key'] = \
tuple(sorted(REQUEST.get('%s_expression_cache_key' % id, '').split()))
if RESPONSE and URL1:
RESPONSE.redirect(URL1 + '/manage_catalogFilter?manage_tabs_message=Filter%20Changed')
security.declarePrivate('isMethodFiltered')
def isMethodFiltered(self, method_name):
"""
Returns 1 if the method is already filtered,
else it returns 0
"""
if withCMF:
# Reset Filtet dict
if getattr(aq_base(self), 'filter_dict', None) is None:
self.filter_dict = PersistentMapping()
return 0
try:
return self.filter_dict[method_name]['filtered']
except KeyError:
return 0
return 0
security.declarePrivate('getExpression')
def getExpression(self, method_name):
""" Get the filter expression text for this method.
"""
if withCMF:
if getattr(aq_base(self), 'filter_dict', None) is None:
self.filter_dict = PersistentMapping()
return ""
try:
return self.filter_dict[method_name]['expression']
except KeyError:
return ""
return ""
security.declarePrivate('getExpressionCacheKey')
def getExpressionCacheKey(self, method_name):
""" Get the key string which is used to cache results
for the given expression.
"""
if withCMF:
if getattr(aq_base(self), 'filter_dict', None) is None:
self.filter_dict = PersistentMapping()
return ""
try:
return ' '.join(self.filter_dict[method_name]['expression_cache_key'])
except KeyError:
return ""
return ""
security.declarePrivate('getExpressionInstance')
def getExpressionInstance(self, method_name):
""" Get the filter expression instance for this method.
"""
if withCMF:
if getattr(aq_base(self), 'filter_dict', None) is None:
self.filter_dict = PersistentMapping()
return None
try:
return self.filter_dict[method_name]['expression_instance']
except KeyError:
return None
return None
security.declarePrivate('setFilterExpression')
def setFilterExpression(self, method_name, expression):
""" Set the Expression for a certain method name. This allow set
expressions by scripts.
"""
if withCMF:
if getattr(aq_base(self), 'filter_dict', None) is None:
self.filter_dict = PersistentMapping()
return None
self.filter_dict[method_name]['expression'] = expression
if expression:
self.filter_dict[method_name]['expression_instance'] = Expression(expression)
else:
self.filter_dict[method_name]['expression_instance'] = None
security.declarePrivate('isPortalTypeSelected')
def isPortalTypeSelected(self, method_name, portal_type):
""" Returns true if the portal type is selected for this method.
XXX deprecated
"""
if withCMF:
if getattr(aq_base(self), 'filter_dict', None) is None:
self.filter_dict = PersistentMapping()
return 0
try:
return portal_type in (self.filter_dict[method_name]['type'])
except KeyError:
return 0
return 0
security.declarePrivate('getFilteredPortalTypeList')
def getFilteredPortalTypeList(self, method_name):
""" Returns the list of portal types which define
the filter.
XXX deprecated
"""
if withCMF:
if getattr(aq_base(self), 'filter_dict', None) is None:
self.filter_dict = PersistentMapping()
return []
try:
return self.filter_dict[method_name]['type']
except KeyError:
return []
return []
security.declarePrivate('getFilterDict')
def getFilterDict(self):
"""
Utility Method.
Filter Dict is a dictionary and used at Python Scripts,
This method returns a filter dict as a dictionary.
"""
if withCMF:
if getattr(aq_base(self), 'filter_dict', None) is None:
self.filter_dict = PersistentMapping()
return None
filter_dict = {}
for key in self.filter_dict:
# Filter is also a Persistence dict.
filter_dict[key] = {}
for sub_key in self.filter_dict[key]:
filter_dict[key][sub_key] = self.filter_dict[key][sub_key]
return filter_dict
return None
security.declarePublic('getConnectionId') security.declarePublic('getConnectionId')
def getConnectionId(self, deferred=False): def getConnectionId(self, deferred=False):
""" """
...@@ -2844,7 +2670,7 @@ class Catalog(Folder, ...@@ -2844,7 +2670,7 @@ class Catalog(Folder,
If 'deferred' is True, then returns the deferred connection If 'deferred' is True, then returns the deferred connection
""" """
for method in self.objectValues(): for method in self.objectValues():
if method.meta_type == 'Z SQL Method': if method.meta_type in ('Z SQL Method', 'ERP5 SQL Method',):
if ('deferred' in method.connection_id) == deferred: if ('deferred' in method.connection_id) == deferred:
return method.connection_id return method.connection_id
......
...@@ -366,7 +366,7 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -366,7 +366,7 @@ class ZCatalog(Folder, Persistent, Implicit):
security.declarePrivate('changeSQLConnectionIds') security.declarePrivate('changeSQLConnectionIds')
def changeSQLConnectionIds(self, folder, sql_connection_id_dict): def changeSQLConnectionIds(self, folder, sql_connection_id_dict):
if sql_connection_id_dict is not None: if sql_connection_id_dict is not None:
if folder.meta_type == 'Z SQL Method': if folder.meta_type in ('Z SQL Method', 'ERP5 SQL Method',):
connection_id = folder.connection_id connection_id = folder.connection_id
if connection_id in sql_connection_id_dict: if connection_id in sql_connection_id_dict:
folder.connection_id = sql_connection_id_dict[connection_id] folder.connection_id = sql_connection_id_dict[connection_id]
......
...@@ -55,64 +55,6 @@ class TestSQLCatalog(unittest.TestCase): ...@@ -55,64 +55,6 @@ class TestSQLCatalog(unittest.TestCase):
self.assertTrue(self._catalog.z_dummy_method in self.assertTrue(self._catalog.z_dummy_method in
self._catalog.getFilterableMethodList()) self._catalog.getFilterableMethodList())
def test_manage_editFilter(self):
request = dict(z_dummy_method_box=1, z_dummy_method_expression='python: 1')
self._catalog.manage_editFilter(REQUEST=request)
self.assertTrue(self._catalog.filter_dict.has_key('z_dummy_method'))
def test_isMethodFiltered(self):
request = dict(z_dummy_method_box=1, z_dummy_method_expression='python: 1')
self._catalog.manage_editFilter(REQUEST=request)
self.assertTrue(self._catalog.isMethodFiltered('z_dummy_method'))
self.assertFalse(self._catalog.isMethodFiltered('not_exist'))
def test_getFilterExpression(self):
request = dict(z_dummy_method_box=1, z_dummy_method_expression='python: 1')
self._catalog.manage_editFilter(REQUEST=request)
self.assertEqual('python: 1', self._catalog.getExpression('z_dummy_method'))
self.assertEqual('', self._catalog.getExpression('not_exists'))
def test_setFilterExpression(self):
request = dict(z_dummy_method_box=1, z_dummy_method_expression='python: 1')
self._catalog.manage_editFilter(REQUEST=request)
expression = self._catalog.getExpressionInstance('z_dummy_method')
self._catalog.setFilterExpression('z_dummy_method', 'python: 2')
self.assertEqual('python: 2', self._catalog.getExpression('z_dummy_method'))
self.assertNotEquals(expression,
self._catalog.getExpressionInstance('z_dummy_method'))
self._catalog.setFilterExpression('z_dummy_method', 'python: 1')
self.assertEqual('python: 1', self._catalog.getExpression('z_dummy_method'))
self.assertRaises(KeyError, self._catalog.setFilterExpression,
'not_exists', "python:1")
self.assertEqual('', self._catalog.getExpression('not_exists'))
def test_getFilterDict(self):
request = dict(z_dummy_method_box=1, z_dummy_method_expression='python: 1')
self._catalog.manage_editFilter(REQUEST=request)
filter_dict = self._catalog.getFilterDict()
self.assertEqual(self._catalog.filter_dict.keys(), filter_dict.keys())
self.assertTrue(isinstance(filter_dict, type({})))
self.assertTrue(isinstance(filter_dict['z_dummy_method'], type({})))
self.assertEqual(self._catalog.getExpression('z_dummy_method'),
filter_dict['z_dummy_method']['expression'])
def test_getFilterExpressionInstance(self):
request = dict(z_dummy_method_box=1, z_dummy_method_expression='python: 1')
self._catalog.manage_editFilter(REQUEST=request)
self.assertTrue(isinstance(
self._catalog.getExpressionInstance('z_dummy_method'), Expression))
self.assertEqual(None, self._catalog.getExpressionInstance('not_exists'))
def test_isPortalTypeSelected(self):
request = dict(z_dummy_method_box=1, z_dummy_method_type=['Selected'])
self._catalog.manage_editFilter(REQUEST=request)
self.assertTrue(
self._catalog.isPortalTypeSelected('z_dummy_method', 'Selected'))
self.assertFalse(
self._catalog.isPortalTypeSelected('z_dummy_method', 'Not Selected'))
self.assertFalse(
self._catalog.isPortalTypeSelected('not_exists', 'Selected'))
def test_getRecordByUid(self): def test_getRecordByUid(self):
class MyError(RuntimeError): class MyError(RuntimeError):
pass pass
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment