Commit 45d6a112 authored by Rafael Monnerat's avatar Rafael Monnerat 👻

Update from upstream/master

parents ca6d28ec dfd1873b
line_list = []
for line in context.contentValues(
portal_type=context.getPortalAccountingMovementTypeList()):
has_amount = True
if side == 'source':
account = line.getSourceValue(portal_type='Account')
if test_compta_demat_compatibility:
has_amount = bool(
line.getSourceTotalAssetPrice()
if line.hasSourceTotalAssetPrice() else line.getQuantity())
else:
assert side == 'destination'
account = line.getDestinationValue(portal_type='Account')
if test_compta_demat_compatibility:
has_amount = bool(
line.getDestinationTotalAssetPrice()
if line.hasDestinationTotalAssetPrice() else line.getQuantity())
if account is not None and has_amount:
line_list.append(line)
return line_list
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>side, test_compta_demat_compatibility</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>AccountingTransaction_getFECXMLAccountingTransactionLineList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<ecriture xmlns:tal="http://xml.zope.org/namespaces/tal"> <ecriture
xmlns:tal="http://xml.zope.org/namespaces/tal"
tal:define="line_list python:context.AccountingTransaction_getFECXMLAccountingTransactionLineList('destination', options['test_compta_demat_compatibility'])"
tal:condition="line_list">
<EcritureNum tal:content="context/getDestinationReference">Specific Reference</EcritureNum> <EcritureNum tal:content="context/getDestinationReference">Specific Reference</EcritureNum>
<EcritureDate tal:content="python: context.getStopDate().strftime('%Y-%m-%d')">Specific Date</EcritureDate> <EcritureDate tal:content="python: context.getStopDate().strftime('%Y-%m-%d')">Specific Date</EcritureDate>
<EcritureLib tal:content="context/getTitle">Title</EcritureLib> <EcritureLib tal:content="context/getTitle">Title</EcritureLib>
...@@ -7,9 +10,8 @@ ...@@ -7,9 +10,8 @@
<tal:block tal:replace="nothing"><EcritureLet></EcritureLet> <tal:block tal:replace="nothing"><EcritureLet></EcritureLet>
<DateLet></DateLet></tal:block> <DateLet></DateLet></tal:block>
<ValidDate tal:content="python: context.AccountingTransaction_getDeliverDate().strftime('%Y-%m-%d')">Modification Date</ValidDate> <ValidDate tal:content="python: context.AccountingTransaction_getDeliverDate().strftime('%Y-%m-%d')">Modification Date</ValidDate>
<tal:block tal:repeat="line python:context.contentValues(portal_type=context.getPortalAccountingMovementTypeList())"><ligne <tal:block tal:repeat="line line_list"><ligne
tal:define="account python:line.getDestinationValue(portal_type='Account')" tal:define="account python:line.getDestinationValue(portal_type='Account')">
tal:condition="python: account is not None and ((line.getDestinationTotalAssetPrice() if line.hasDestinationTotalAssetPrice() else line.getQuantity()) or not options['test_compta_demat_compatibility'])">
<CompteNum tal:content="account/Account_getGapId">Reference Compte (Account_getGapId)</CompteNum> <CompteNum tal:content="account/Account_getGapId">Reference Compte (Account_getGapId)</CompteNum>
<CompteLib tal:content="line/Movement_getDestinationCompteLib">Translated Title Compte</CompteLib> <CompteLib tal:content="line/Movement_getDestinationCompteLib">Translated Title Compte</CompteLib>
<tal:block tal:condition="python: account.getAccountType() in ('asset/receivable', 'liability/payable')" <tal:block tal:condition="python: account.getAccountType() in ('asset/receivable', 'liability/payable')"
......
<ecriture xmlns:tal="http://xml.zope.org/namespaces/tal"> <ecriture
xmlns:tal="http://xml.zope.org/namespaces/tal"
tal:define="line_list python:context.AccountingTransaction_getFECXMLAccountingTransactionLineList('source', options['test_compta_demat_compatibility'])"
tal:condition="line_list">
<EcritureNum tal:content="context/getSourceReference">Specific Reference</EcritureNum> <EcritureNum tal:content="context/getSourceReference">Specific Reference</EcritureNum>
<EcritureDate tal:content="python: context.getStartDate().strftime('%Y-%m-%d')">Specific Date</EcritureDate> <EcritureDate tal:content="python: context.getStartDate().strftime('%Y-%m-%d')">Specific Date</EcritureDate>
<EcritureLib tal:content="context/getTitle">Title</EcritureLib> <EcritureLib tal:content="context/getTitle">Title</EcritureLib>
...@@ -7,9 +10,8 @@ ...@@ -7,9 +10,8 @@
<tal:block tal:replace="nothing"><EcritureLet></EcritureLet> <tal:block tal:replace="nothing"><EcritureLet></EcritureLet>
<DateLet></DateLet></tal:block> <DateLet></DateLet></tal:block>
<ValidDate tal:content="python: context.AccountingTransaction_getDeliverDate().strftime('%Y-%m-%d')">Modification Date</ValidDate> <ValidDate tal:content="python: context.AccountingTransaction_getDeliverDate().strftime('%Y-%m-%d')">Modification Date</ValidDate>
<tal:block tal:repeat="line python:context.contentValues(portal_type=context.getPortalAccountingMovementTypeList())"><ligne <tal:block tal:repeat="line line_list"><ligne
tal:define="account python:line.getSourceValue(portal_type='Account')" tal:define="account python:line.getSourceValue(portal_type='Account')">
tal:condition="python: account is not None and ((line.getSourceTotalAssetPrice() if line.hasSourceTotalAssetPrice() else line.getQuantity()) or not options['test_compta_demat_compatibility'])">
<CompteNum tal:content="account/Account_getGapId">Reference Compte (Account_getGapId)</CompteNum> <CompteNum tal:content="account/Account_getGapId">Reference Compte (Account_getGapId)</CompteNum>
<CompteLib tal:content="line/Movement_getSourceCompteLib">Translated Title Compte</CompteLib> <CompteLib tal:content="line/Movement_getSourceCompteLib">Translated Title Compte</CompteLib>
<tal:block tal:condition="python: account.getAccountType() in ('asset/receivable', 'liability/payable')" <tal:block tal:condition="python: account.getAccountType() in ('asset/receivable', 'liability/payable')"
......
...@@ -31,7 +31,6 @@ ...@@ -31,7 +31,6 @@
""" """
import six import six
import unittest
import zipfile import zipfile
if six.PY2: if six.PY2:
from email import message_from_string as message_from_bytes from email import message_from_string as message_from_bytes
...@@ -46,6 +45,7 @@ from AccessControl.SecurityManagement import newSecurityManager ...@@ -46,6 +45,7 @@ from AccessControl.SecurityManagement import newSecurityManager
from erp5.component.test.testAccounting import AccountingTestCase from erp5.component.test.testAccounting import AccountingTestCase
class TestAccounting_l10n_fr(AccountingTestCase): class TestAccounting_l10n_fr(AccountingTestCase):
"""Test Accounting L10N FR """Test Accounting L10N FR
""" """
...@@ -405,7 +405,29 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -405,7 +405,29 @@ class TestAccounting_l10n_fr(AccountingTestCase):
def test_ValidDate(self): def test_ValidDate(self):
account_module = self.portal.account_module account_module = self.portal.account_module
invoice = self._makeOne( invoice_source = self._makeOne(
portal_type='Purchase Invoice Transaction',
title='Premiere Ecriture',
simulation_state='delivered',
reference='1',
source_section_value=self.organisation_module.supplier,
stop_date=DateTime(2014, 2, 2),
lines=(dict(source_value=account_module.payable,
source_debit=132.00),
dict(source_value=account_module.refundable_vat,
source_credit=22.00),
dict(source_value=account_module.goods_purchase,
source_credit=110.00)))
assert invoice_source.workflow_history['accounting_workflow'][-1]['action'] == 'deliver'
invoice_source.workflow_history['accounting_workflow'][-1]['time'] = DateTime(2001, 2, 3)
tree = etree.fromstring(
invoice_source.AccountingTransaction_viewAsSourceFECXML(
test_compta_demat_compatibility=True))
self.assertEqual(tree.xpath('//ValidDate/text()'), ['2001-02-03'])
invoice_destination = self._makeOne(
portal_type='Purchase Invoice Transaction', portal_type='Purchase Invoice Transaction',
title='Premiere Ecriture', title='Premiere Ecriture',
simulation_state='delivered', simulation_state='delivered',
...@@ -419,15 +441,11 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -419,15 +441,11 @@ class TestAccounting_l10n_fr(AccountingTestCase):
dict(destination_value=account_module.goods_purchase, dict(destination_value=account_module.goods_purchase,
destination_credit=110.00))) destination_credit=110.00)))
assert invoice.workflow_history['accounting_workflow'][-1]['action'] == 'deliver' assert invoice_destination.workflow_history['accounting_workflow'][-1]['action'] == 'deliver'
invoice.workflow_history['accounting_workflow'][-1]['time'] = DateTime(2001, 2, 3) invoice_destination.workflow_history['accounting_workflow'][-1]['time'] = DateTime(2001, 2, 3)
tree = etree.fromstring( tree = etree.fromstring(
invoice.AccountingTransaction_viewAsSourceFECXML( invoice_destination.AccountingTransaction_viewAsDestinationFECXML(
test_compta_demat_compatibility=True))
self.assertEqual(tree.xpath('//ValidDate/text()'), ['2001-02-03'])
tree = etree.fromstring(
invoice.AccountingTransaction_viewAsDestinationFECXML(
test_compta_demat_compatibility=True)) test_compta_demat_compatibility=True))
self.assertEqual(tree.xpath('//ValidDate/text()'), ['2001-02-03']) self.assertEqual(tree.xpath('//ValidDate/text()'), ['2001-02-03'])
...@@ -551,9 +569,92 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -551,9 +569,92 @@ class TestAccounting_l10n_fr(AccountingTestCase):
'//ecriture/PieceRef[text()="source"]/../ligne/Credit/text()'), '//ecriture/PieceRef[text()="source"]/../ligne/Credit/text()'),
['0.00', '40.00', '200.00']) ['0.00', '40.00', '200.00'])
def test_SkipEmptyTransactions(self):
# Don't include transactions without lines, because they are
# reported as invalid by Test Compta Demat
account_module = self.portal.account_module
self._makeOne(
portal_type='Purchase Invoice Transaction',
title='destination 0',
simulation_state='delivered',
reference='destination_0_lines',
source_section_value=self.organisation_module.supplier,
stop_date=DateTime(2014, 2, 2),
lines=(
dict(
destination_value=account_module.payable, destination_debit=0.00),
dict(
destination_value=account_module.payable,
destination_debit=10000.00,
destination_asset_debit=0.00),
dict(
destination_value=account_module.refundable_vat,
destination_credit=0.00),
dict(
destination_value=account_module.refundable_vat,
destination_credit=10000.00,
destination_asset_credit=0.00)))
self._makeOne(
portal_type='Purchase Invoice Transaction',
title='destination no',
simulation_state='delivered',
reference='destination_no_lines',
source_section_value=self.organisation_module.supplier,
stop_date=DateTime(2014, 2, 2),
lines=())
self._makeOne(
portal_type='Sale Invoice Transaction',
title='source 0',
simulation_state='delivered',
reference='source_0_lines',
destination_section_value=self.organisation_module.client_2,
start_date=DateTime(2014, 3, 1),
lines=(
dict(source_value=account_module.receivable, source_debit=0.00),
dict(source_value=account_module.collected_vat, source_credit=0.00)))
self._makeOne(
portal_type='Sale Invoice Transaction',
title='source no',
simulation_state='delivered',
reference='source_no_lines',
destination_section_value=self.organisation_module.client_2,
start_date=DateTime(2014, 3, 1),
lines=())
self.tic()
self.portal.accounting_module.AccountingTransactionModule_viewFrenchAccountingTransactionFile(
section_category='group/demo_group',
section_category_strict=False,
at_date=DateTime(2014, 12, 31),
simulation_state=['delivered'])
self.tic()
tree = etree.fromstring(self.getFECFromMailMessage())
self.validateFECXML(tree)
self.assertEqual(tree.xpath('//ecriture'), [])
def test_PieceRefDefaultValue(self): def test_PieceRefDefaultValue(self):
account_module = self.portal.account_module account_module = self.portal.account_module
invoice = self._makeOne( invoice_source = self._makeOne(
portal_type='Purchase Invoice Transaction',
title='Premiere Ecriture',
simulation_state='delivered',
source_section_value=self.organisation_module.supplier,
stop_date=DateTime(2014, 2, 2),
lines=(
dict(
source_value=account_module.payable, source_debit=132.00),
dict(
source_value=account_module.refundable_vat,
source_credit=22.00),
dict(
source_value=account_module.goods_purchase,
source_credit=110.00)))
invoice_source.setSourceReference('source_reference')
invoice_destination = self._makeOne(
portal_type='Purchase Invoice Transaction', portal_type='Purchase Invoice Transaction',
title='Premiere Ecriture', title='Premiere Ecriture',
simulation_state='delivered', simulation_state='delivered',
...@@ -568,16 +669,14 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -568,16 +669,14 @@ class TestAccounting_l10n_fr(AccountingTestCase):
dict( dict(
destination_value=account_module.goods_purchase, destination_value=account_module.goods_purchase,
destination_credit=110.00))) destination_credit=110.00)))
invoice_destination.setDestinationReference('destination_reference')
invoice.setSourceReference('source_reference')
invoice.setDestinationReference('destination_reference')
tree = etree.fromstring( tree = etree.fromstring(
invoice.AccountingTransaction_viewAsSourceFECXML( invoice_source.AccountingTransaction_viewAsSourceFECXML(
test_compta_demat_compatibility=True)) test_compta_demat_compatibility=True))
self.assertEqual(tree.xpath('//EcritureNum/text()'), ['source_reference']) self.assertEqual(tree.xpath('//EcritureNum/text()'), ['source_reference'])
self.assertEqual(tree.xpath('//PieceRef/text()'), ['source_reference']) self.assertEqual(tree.xpath('//PieceRef/text()'), ['source_reference'])
tree = etree.fromstring( tree = etree.fromstring(
invoice.AccountingTransaction_viewAsDestinationFECXML( invoice_destination.AccountingTransaction_viewAsDestinationFECXML(
test_compta_demat_compatibility=True)) test_compta_demat_compatibility=True))
self.assertEqual( self.assertEqual(
tree.xpath('//EcritureNum/text()'), ['destination_reference']) tree.xpath('//EcritureNum/text()'), ['destination_reference'])
...@@ -585,12 +684,12 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -585,12 +684,12 @@ class TestAccounting_l10n_fr(AccountingTestCase):
tree.xpath('//PieceRef/text()'), ['destination_reference']) tree.xpath('//PieceRef/text()'), ['destination_reference'])
tree = etree.fromstring( tree = etree.fromstring(
invoice.AccountingTransaction_viewAsSourceFECXML( invoice_source.AccountingTransaction_viewAsSourceFECXML(
test_compta_demat_compatibility=False)) test_compta_demat_compatibility=False))
self.assertEqual(tree.xpath('//EcritureNum/text()'), ['source_reference']) self.assertEqual(tree.xpath('//EcritureNum/text()'), ['source_reference'])
self.assertEqual([n.text for n in tree.xpath('//PieceRef')], [None]) self.assertEqual([n.text for n in tree.xpath('//PieceRef')], [None])
tree = etree.fromstring( tree = etree.fromstring(
invoice.AccountingTransaction_viewAsDestinationFECXML( invoice_destination.AccountingTransaction_viewAsDestinationFECXML(
test_compta_demat_compatibility=False)) test_compta_demat_compatibility=False))
self.assertEqual( self.assertEqual(
tree.xpath('//EcritureNum/text()'), ['destination_reference']) tree.xpath('//EcritureNum/text()'), ['destination_reference'])
...@@ -661,9 +760,3 @@ class TestAccounting_l10n_fr(AccountingTestCase): ...@@ -661,9 +760,3 @@ class TestAccounting_l10n_fr(AccountingTestCase):
tree.xpath( tree.xpath(
'//ecriture/PieceRef[text()="source"]/../ligne/Credit/text()'), '//ecriture/PieceRef[text()="source"]/../ligne/Credit/text()'),
['0.00', '345.00']) ['0.00', '345.00'])
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestAccounting_l10n_fr))
return suite
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Alarm" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>active_sense_method_id</string> </key>
<value> <string>Alarm_checkSiteDailyModification</string> </value>
</item>
<item>
<key> <string>alarm_notification_mode</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>automatic_solve</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>enabled</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>check_site_daily_modification</string> </value>
</item>
<item>
<key> <string>periodicity_hour</string> </key>
<value>
<tuple>
<int>0</int>
</tuple>
</value>
</item>
<item>
<key> <string>periodicity_minute</string> </key>
<value>
<tuple>
<int>1</int>
</tuple>
</value>
</item>
<item>
<key> <string>periodicity_month</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_month_day</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>periodicity_start_date</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="DateTime" module="DateTime.DateTime"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<tuple>
<float>1603152000.0</float>
<string>GMT</string>
</tuple>
</state>
</object>
</value>
</item>
<item>
<key> <string>periodicity_week</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Alarm</string> </value>
</item>
<item>
<key> <string>report_method_id</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Check Site Daily Modification</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
active_process = context.newActiveProcess().getRelativeUrl()
context.activate(tag=tag).Base_checkSiteDailyModification(active_process=active_process)
context.activate(after_tag=tag).getId()
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>tag, **kw</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Alarm_checkSiteDailyModification</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from DateTime import DateTime
from Products.CMFActivity.ActiveResult import ActiveResult
from Products.ZSQLCatalog.SQLCatalog import Query
portal = context.getPortalObject()
if not check_date:
check_date = DateTime().earliestTime() - 1
active_process = context.restrictedTraverse(active_process)
for workflow_object in portal.portal_catalog(
portal_type=(
'Workflow',
'Workflow Script',
'Workflow State',
'Workflow Transition',
'Workflow Variable',
'Worklist',
'Interaction Workflow'
),
modification_date=Query(modification_date=check_date, range="min"),
select_list = ['relative_url']
):
active_process.postResult(ActiveResult(
severity=100,
detail='%s is modified' % workflow_object.relative_url))
for sub_path, sub_obj in portal.portal_skins.ZopeFind(portal.portal_skins, search_sub=1):
modified_date = DateTime(container.last_modified(sub_obj))
if modified_date >= check_date:
active_process.postResult(ActiveResult(
severity=100,
detail='%s is modified' % sub_path))
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>active_process, check_date = None</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Base_checkSiteDailyModification</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
from Products.ERP5Type.Document import newTempBase
from DateTime import DateTime
from zExceptions import Unauthorized
if REQUEST is not None:
raise Unauthorized
portal = context.getPortalObject()
# Use only the first entry. This prevents change the rss content
# too often whenever multiple activities are failing over time.
message_list = portal.portal_activities.getMessageTempObjectList(processing_node=-2,
count=1)
if not len(message_list):
return []
message = portal.Base_translateString('You have one or more activity failures.')
# Make compatible with renderjs_runner
web_site = context.getWebSiteValue()
if web_site is None:
web_site_url = portal.absolute_url()
else:
web_site_url = web_site.absolute_url() + "/#"
return [
newTempBase(portal, "rss_entry",
uid=message_list[0].uid,
date=DateTime().earliestTime(),
link="%s/portal_activities" % web_site_url,
title=message)]
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>REQUEST=None, **kw</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_getPendingErrorList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ERP5 Form" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_objects</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>action_title</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>edit_order</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>enctype</string> </key>
<value> <string>application/x-www-form-urlencoded</string> </value>
</item>
<item>
<key> <string>group_list</string> </key>
<value>
<list>
<string>bottom</string>
<string>hidden</string>
</list>
</value>
</item>
<item>
<key> <string>groups</string> </key>
<value>
<dictionary>
<item>
<key> <string>bottom</string> </key>
<value>
<list>
<string>listbox</string>
</list>
</value>
</item>
<item>
<key> <string>hidden</string> </key>
<value>
<list/>
</value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>ERP5Site_viewPendingErrorListAsRSS</string> </value>
</item>
<item>
<key> <string>method</string> </key>
<value> <string>POST</string> </value>
</item>
<item>
<key> <string>name</string> </key>
<value> <string>ERP5Site_viewPendingErrorListAsRSS</string> </value>
</item>
<item>
<key> <string>pt</string> </key>
<value> <string>rss_view</string> </value>
</item>
<item>
<key> <string>row_length</string> </key>
<value> <int>4</int> </value>
</item>
<item>
<key> <string>stored_encoding</string> </key>
<value> <string>UTF-8</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Pending Errors</string> </value>
</item>
<item>
<key> <string>unicode_mode</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>update_action</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>update_action_title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>all_columns</string>
<string>columns</string>
<string>count_method</string>
<string>editable_columns</string>
<string>hide_rows_on_no_search_criterion</string>
<string>lines</string>
<string>list_method</string>
<string>portal_types</string>
<string>search_columns</string>
<string>selection_name</string>
<string>sort</string>
<string>sort_columns</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>listbox</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>all_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>columns</string> </key>
<value>
<list>
<tuple>
<string>title</string>
<string>title</string>
</tuple>
<tuple>
<string>link</string>
<string>link</string>
</tuple>
<tuple>
<string>uid</string>
<string>guid</string>
</tuple>
<tuple>
<string>date</string>
<string>pubDate</string>
</tuple>
</list>
</value>
</item>
<item>
<key> <string>count_method</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>editable_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_list_mode_listbox</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>hide_rows_on_no_search_criterion</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>lines</string> </key>
<value> <int>30</int> </value>
</item>
<item>
<key> <string>list_method</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>portal_types</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>search_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>selection_name</string> </key>
<value> <string>pending_failure_selection</string> </value>
</item>
<item>
<key> <string>sort</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>sort_columns</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Pending Errors</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Method" module="Products.Formulator.MethodField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>method_name</string> </key>
<value> <string>ERP5Site_getPendingErrorList</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -30,6 +30,7 @@ ...@@ -30,6 +30,7 @@
import unittest import unittest
import time import time
from Products.ERP5.tests.testInventoryAPI import InventoryAPITestCase from Products.ERP5.tests.testInventoryAPI import InventoryAPITestCase
from DateTime import DateTime
class TestERP5Administration(InventoryAPITestCase): class TestERP5Administration(InventoryAPITestCase):
"""Test for erp5_administration business template. """Test for erp5_administration business template.
...@@ -231,6 +232,51 @@ component_error() ...@@ -231,6 +232,51 @@ component_error()
location_and_message_list) location_and_message_list)
def test_check_site_modification(self):
# remove second, obj's modification in erp5 don't have seconds
check_date = DateTime(DateTime().strftime('%Y-%m-%d %H:%M'))
active_process = self.portal.portal_activities.newActiveProcess()
self.portal.Base_checkSiteDailyModification(
active_process=active_process.getRelativeUrl(),
check_date = check_date
)
result_list = [x.detail for x in active_process.getResultList()]
message_list = [
'erp5_administration/Base_checkSiteDailyModification is modified',
'erp5_administration/BusinessTemplate_viewCheckPythonCodeDialog is modified',
'portal_workflow/edit_workflow is modified',
'portal_workflow/edit_workflow/state_current is modified',
'portal_workflow/preference_interaction_workflow is modified'
]
for message in message_list:
self.assertNotIn(message, result_list)
self.portal.portal_skins.erp5_administration.Base_checkSiteDailyModification.ZPythonScript_setTitle('%s' % check_date)
self.portal.portal_skins.erp5_administration.Base_checkSiteDailyModification.ZPythonScript_setTitle('')
self.portal.portal_skins.erp5_administration.BusinessTemplate_viewCheckPythonCodeDialog.manage_addProduct['Formulator'].manage_addField('my_title', 'Title', 'StringField')
self.portal.portal_skins.erp5_administration.BusinessTemplate_viewCheckPythonCodeDialog.manage_delObjects('my_title')
new_comment = 'Test %s' % check_date
self.portal.portal_workflow.preference_interaction_workflow.edit(
comment = new_comment
)
self.portal.portal_workflow.edit_workflow.edit(
comment = new_comment
)
self.portal.portal_workflow.edit_workflow.state_current.edit(
comment = new_comment
)
self.tic()
self.portal.Base_checkSiteDailyModification(
active_process=active_process.getRelativeUrl(),
check_date = check_date
)
result_list = [x.detail for x in active_process.getResultList()]
for message in message_list:
self.assertIn(message, result_list)
def test_suite(): def test_suite():
suite = unittest.TestSuite() suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestERP5Administration)) suite.addTest(unittest.makeSuite(TestERP5Administration))
......
...@@ -4,5 +4,6 @@ portal_alarms/check_conversion_tool_availability ...@@ -4,5 +4,6 @@ portal_alarms/check_conversion_tool_availability
portal_alarms/check_folder_handler portal_alarms/check_folder_handler
portal_alarms/check_item_tracking portal_alarms/check_item_tracking
portal_alarms/check_localizer portal_alarms/check_localizer
portal_alarms/check_site_daily_modification
portal_alarms/check_skin_cache portal_alarms/check_skin_cache
portal_alarms/check_stock portal_alarms/check_stock
\ No newline at end of file
...@@ -5,7 +5,6 @@ ...@@ -5,7 +5,6 @@
# #
############################################################################## ##############################################################################
import random
import transaction import transaction
from Products.ERP5Type.tests.SecurityTestCase import SecurityTestCase from Products.ERP5Type.tests.SecurityTestCase import SecurityTestCase
from Products.ERP5Type.tests.utils import DummyMailHost from Products.ERP5Type.tests.utils import DummyMailHost
...@@ -67,11 +66,6 @@ class TestOfficeJSSDKConfigurator(SecurityTestCase): ...@@ -67,11 +66,6 @@ class TestOfficeJSSDKConfigurator(SecurityTestCase):
# Execute the business configuration if not installed # Execute the business configuration if not installed
business_configuration = self.getBusinessConfiguration() business_configuration = self.getBusinessConfiguration()
if (business_configuration.getSimulationState() != 'installed'): if (business_configuration.getSimulationState() != 'installed'):
self.portal.portal_caches.erp5_site_global_id = '%s' % random.random()
self.portal.portal_caches._p_changed = 1
self.commit()
self.portal.portal_caches.updateCache()
self.bootstrapSite() self.bootstrapSite()
self.commit() self.commit()
......
<catalog_method> <catalog_method>
<item key="sql_uncatalog_object" type="int"> <item key="sql_deferred_uncatalog_object" type="int">
<value>1</value> <value>1</value>
</item> </item>
</catalog_method> </catalog_method>
DELETE FROM content_translation WHERE <dtml-sqltest uid op=eq type=int> DELETE FROM content_translation WHERE <dtml-sqltest uid op=eq type=int multiple>
\ No newline at end of file \ No newline at end of file
<catalog_method> <catalog_method>
<item key="sql_catalog_object_list" type="int"> <item key="sql_deferred_catalog_object_list" type="int">
<value>1</value> <value>1</value>
</item> </item>
</catalog_method> </catalog_method>
...@@ -134,8 +134,11 @@ class TestCopySupport(ERP5TypeTestCase): ...@@ -134,8 +134,11 @@ class TestCopySupport(ERP5TypeTestCase):
self.tic() self.tic()
finally: finally:
ActivityTool.invokeGroup = ActivityTool_invokeGroup ActivityTool.invokeGroup = ActivityTool_invokeGroup
self.assertEqual(invokeGroup_list, catalog_relative_url = self.portal.portal_catalog.getSQLCatalog().getRelativeUrl()
['portal_catalog/uncatalogObjectList', uid_list, 'SQLQueue', False]) self.assertEqual(invokeGroup_list, [
'portal_catalog/uncatalogObjectList', uid_list, 'SQLQueue', False,
catalog_relative_url + '/SQLCatalog_deferUncatalogObjectActivity', uid_list, 'SQLQueue', False,
])
self.assertEqual(len(search_catalog(uid=uid_list)), 0) self.assertEqual(len(search_catalog(uid=uid_list)), 0)
......
...@@ -33,7 +33,7 @@ import zodbpickle.fastpickle as pickle ...@@ -33,7 +33,7 @@ import zodbpickle.fastpickle as pickle
import re import re
from io import BytesIO from io import BytesIO
from six import StringIO from six import StringIO
from Products.ERP5Type.XMLExportImport import importXML, ppml from Products.ERP5Type.XMLExportImport import importXML, OrderedPickler, ppml
import six import six
import lxml.etree import lxml.etree
...@@ -194,6 +194,7 @@ class TestXMLPickle(XMLPickleTestCase): ...@@ -194,6 +194,7 @@ class TestXMLPickle(XMLPickleTestCase):
self.check_and_load({'a': 1, 'b': 2}) self.check_and_load({'a': 1, 'b': 2})
self.check_and_load({'hé': 'ho'}) self.check_and_load({'hé': 'ho'})
self.check_and_load(dict.fromkeys(range(3000))) self.check_and_load(dict.fromkeys(range(3000)))
self.check_and_load({1: 'one', 'two': 2})
def test_tuple(self): def test_tuple(self):
self.check_and_load((1, )) self.check_and_load((1, ))
...@@ -346,3 +347,24 @@ class TestXMLPickleStringHeuristics(XMLPickleTestCase): ...@@ -346,3 +347,24 @@ class TestXMLPickleStringHeuristics(XMLPickleTestCase):
self.assertEqual( self.assertEqual(
persistent_ids, persistent_ids,
[b'\x00\x00\x00\x00\x00\x00\x00\x01']) [b'\x00\x00\x00\x00\x00\x00\x00\x01'])
class TestOrderedPickler(unittest.TestCase):
def test_ordered_pickler(self):
def check(obj, check_items_order=True):
f = BytesIO()
pickler = OrderedPickler(f)
pickler.dump(obj)
f.seek(0)
reconstructed = pickle.load(f)
self.assertEqual(reconstructed, obj)
self.assertIs(type(reconstructed), type(obj))
if check_items_order:
self.assertEqual(list(reconstructed.items()), list(obj.items()))
check({"one": 1, "two": 2})
check({1: "one", "two": 2})
check({b"one": 1, b"two": 2})
check({})
check(1, check_items_order=False)
check("one", check_items_order=False)
...@@ -35,7 +35,6 @@ MAIN FILE: generate book in different output formats ...@@ -35,7 +35,6 @@ MAIN FILE: generate book in different output formats
import re import re
import six import six
from Products.PythonScripts.standard import html_quote
from Products.ERP5Type.Utils import str2bytes, bytes2str, unicode2str from Products.ERP5Type.Utils import str2bytes, bytes2str, unicode2str
from base64 import b64encode from base64 import b64encode
...@@ -75,15 +74,15 @@ if not book_content: ...@@ -75,15 +74,15 @@ if not book_content:
return return
book_aggregate_list = [] book_aggregate_list = []
book_revision = book.getRevision() book_revision = book.getRevision()
book_modification_date = book.getModificationDate() book_modification_date = book.getEffectiveDate() or book.getModificationDate()
book_language = book.getLanguage() book_language = book.getLanguage()
# XXX sigh for passing "" around # XXX sigh for passing "" around
book_reference = html_quote(override_document_reference) if override_document_reference else book.getReference() book_reference = override_document_reference if override_document_reference else book.getReference()
book_short_title = html_quote(override_document_short_title) if override_document_short_title else book.getShortTitle() book_short_title = override_document_short_title if override_document_short_title else book.getShortTitle()
book_version = html_quote(override_document_version) if override_document_version else book.getVersion() or "001" book_version = override_document_version if override_document_version else book.getVersion() or "001"
book_description = html_quote(override_document_description) if override_document_description else book.getDescription() book_description = override_document_description if override_document_description else book.getDescription()
book_title = html_quote(override_document_title) if override_document_title else book.getTitle() book_title = override_document_title if override_document_title else book.getTitle()
if six.PY2 and isinstance(book_content, six.text_type): if six.PY2 and isinstance(book_content, six.text_type):
book_content = unicode2str(book_content) book_content = unicode2str(book_content)
...@@ -99,7 +98,7 @@ if override_batch_mode: ...@@ -99,7 +98,7 @@ if override_batch_mode:
book_revision = "1" book_revision = "1"
book_short_date = book_modification_date.strftime('%Y-%m-%d') book_short_date = book_modification_date.strftime('%Y-%m-%d')
if book_language: if book_language and 'AcceptLanguage' in book.REQUEST:
book.REQUEST['AcceptLanguage'].set(book_language, 10) book.REQUEST['AcceptLanguage'].set(book_language, 10)
else: else:
book_language = blank book_language = blank
......
...@@ -497,3 +497,13 @@ class TestCorporateIdentityMethod(ERP5TypeTestCase): ...@@ -497,3 +497,13 @@ class TestCorporateIdentityMethod(ERP5TypeTestCase):
) )
self.assertEqual(output, None) self.assertEqual(output, None)
def test_escapeOverridden(self):
book_export = self.portal.web_page_module.template_test_book_input_003_en_html.WebPage_viewAsBook(
format="html",
override_document_description='<script>alert("description");</script>',
override_document_short_title='<script>alert("short title");</script>',
override_document_title='<script>alert("title");</script>',
override_document_version='<script>alert("001");</script>',
override_document_reference='<script>alert("reference");</script>',
)
self.assertNotIn("<script>alert", book_export)
...@@ -38,6 +38,7 @@ getPreferredCategoryChildItemListMethodId. ...@@ -38,6 +38,7 @@ getPreferredCategoryChildItemListMethodId.
# - all resource child must be properly indented # - all resource child must be properly indented
# It is much simpler if only "empty_category=False" case is handled. # It is much simpler if only "empty_category=False" case is handled.
from Products.ERP5Type.Cache import CachingMethod from Products.ERP5Type.Cache import CachingMethod
from Products.ERP5Type.Utils import bytes2str
from AccessControl import getSecurityManager from AccessControl import getSecurityManager
from six.moves import range from six.moves import range
portal = context.getPortalObject() portal = context.getPortalObject()
...@@ -58,7 +59,7 @@ if indent_category == indent_resource == compact == None: ...@@ -58,7 +59,7 @@ if indent_category == indent_resource == compact == None:
accessor_id = 'getCompactTranslatedTitle' if compact else 'getTranslatedTitle' accessor_id = 'getCompactTranslatedTitle' if compact else 'getTranslatedTitle'
def getResourceItemList(): def getResourceItemList():
INDENT = portal_preferences.getPreferredWhitespaceNumberForChildItemIndentation() * '\xc2\xa0' # UTF-8 Non-breaking space INDENT = portal_preferences.getPreferredWhitespaceNumberForChildItemIndentation() * bytes2str(b'\xc2\xa0') # UTF-8 Non-breaking space
RESOURCE_INDENT = INDENT if indent_resource else '' RESOURCE_INDENT = INDENT if indent_resource else ''
getResourceTitle = lambda resource, category, depth: RESOURCE_INDENT * depth + getattr(resource, accessor_id)() getResourceTitle = lambda resource, category, depth: RESOURCE_INDENT * depth + getattr(resource, accessor_id)()
if indent_category: if indent_category:
......
# This script is called to defer fulltext indexing. # This script is called to defer fulltext indexing.
METHOD_ID = script.id + 'Activity' METHOD_ID = script.id + 'Activity'
GROUP_METHOD_ID = context.getPath() + '/' + METHOD_ID GROUP_METHOD_ID = 'portal_catalog/deferredCatalogObjectList'
activateObject = context.getPortalObject().portal_activities.activateObject activateObject = context.getPortalObject().portal_activities.activateObject
try: try:
priority = context.getActivityRuntimeEnvironment().getPriority() priority = context.getActivityRuntimeEnvironment().getPriority()
...@@ -26,4 +26,4 @@ for document in getPath: ...@@ -26,4 +26,4 @@ for document in getPath:
serialization_tag='full_text_' + document, serialization_tag='full_text_' + document,
), ),
METHOD_ID, METHOD_ID,
)() )(check_uid=0, deferred=1)
from Products.ERP5Type.Utils import UpperCase # BBB only used when upgrading that still spawn activities with this method id.
from ZODB.POSException import ConflictError
from zExceptions import Unauthorized
import six
method = context.z_catalog_fulltext_list
property_list = method.arguments_src.split()
parameter_dict = {x: [] for x in property_list}
for group_object in object_list: for group_object in object_list:
tmp_dict = {} group_object.object.reindexObject()
try:
obj = group_object.object
for property in property_list:
getter = getattr(obj, property, None)
if callable(getter):
value = getter()
else:
value = getattr(obj, 'get%s' % UpperCase(property))()
tmp_dict[property] = value
except ConflictError:
raise
except Unauthorized: # should happen in tricky testERP5Catalog tests only
# Fake activity success: if indexation cannot View document, ignore it.
group_object.result = None group_object.result = None
except Exception:
group_object.raised()
else:
for property, value in six.iteritems(tmp_dict):
parameter_dict[property].append(value)
group_object.result = None
if parameter_dict:
return method(**parameter_dict)
...@@ -52,14 +52,6 @@ ...@@ -52,14 +52,6 @@
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>object_list</string> </value> <value> <string>object_list</string> </value>
</item> </item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
<value> <value>
......
<catalog_method>
<item key="sql_uncatalog_object" type="int">
<value>1</value>
</item>
</catalog_method>
# This script is called to defer fulltext unindexing.
METHOD_ID = script.id + 'Activity'
GROUP_METHOD_ID = context.getRelativeUrl() + '/' + METHOD_ID
try:
priority = context.getActivityRuntimeEnvironment().getPriority()
except KeyError:
# called outside of an activity, could be an immediate reindexation
# XXX: duplicates default priority for sake of simplicity and speed.
# Strictly, this could also look-up default activate parameters, but on
# which document ? Traversing is expensive. So keep things fast by default.
priority = 1
# Optimise cache usage by reducing the likelyhood of a processing node
# including activities spawned by others into its activity group.
# Use unindexObject as dummy method id for compatibility with
# after_method_id=('unindexObject', ...)
context.activate(
activity='SQLQueue',
priority=priority,
node='same',
group_method_id=GROUP_METHOD_ID,
).unindexObject(uid=uid)
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Python Script" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>uid</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SQLCatalog_deferUncatalogObject</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Python Script</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
uid_list = []
for grouped_message in grouped_message_list:
assert not grouped_message.args
assert len(grouped_message.kw) == 1
uid_list.append(grouped_message.kw['uid'])
for method_id in context.getSqlDeferredUncatalogObjectList():
method = getattr(context, method_id)
method(uid=uid_list)
for grouped_message in grouped_message_list:
grouped_message.result = None
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Python Script" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="_reconstructor" module="copy_reg"/>
</klass>
<tuple>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
<global name="object" module="__builtin__"/>
<none/>
</tuple>
<state>
<dictionary>
<item>
<key> <string>_asgns</string> </key>
<value>
<dictionary>
<item>
<key> <string>name_container</string> </key>
<value> <string>container</string> </value>
</item>
<item>
<key> <string>name_context</string> </key>
<value> <string>context</string> </value>
</item>
<item>
<key> <string>name_m_self</string> </key>
<value> <string>script</string> </value>
</item>
<item>
<key> <string>name_subpath</string> </key>
<value> <string>traverse_subpath</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</state>
</object>
</value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string>grouped_message_list</string> </value>
</item>
<item>
<key> <string>_proxy_roles</string> </key>
<value>
<tuple>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>SQLCatalog_deferUncatalogObjectActivity</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Python Script</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<catalog_method> <catalog_method>
<item key="sql_uncatalog_object" type="int">
<value>1</value>
</item>
</catalog_method> </catalog_method>
DELETE FROM catalog_full_text WHERE <dtml-sqltest uid op=eq type=int> DELETE FROM catalog_full_text WHERE <dtml-sqltest uid op=eq type=int multiple>
\ No newline at end of file \ No newline at end of file
<catalog_method> <catalog_method>
<item key="sql_uncatalog_object" type="int"> <item key="sql_deferred_uncatalog_object" type="int">
<value>1</value> <value>1</value>
</item> </item>
</catalog_method> </catalog_method>
DELETE FROM full_text WHERE <dtml-sqltest uid op=eq type=int> DELETE FROM full_text WHERE <dtml-sqltest uid op=eq type=int multiple>
\ No newline at end of file \ No newline at end of file
<catalog_method> <catalog_method>
<item key="sql_deferred_catalog_object_list" type="int">
<value>1</value>
</item>
</catalog_method> </catalog_method>
erp5_mysql_innodb/SQLCatalog_deferFullTextIndex erp5_mysql_innodb/SQLCatalog_deferFullTextIndex
erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity erp5_mysql_innodb/SQLCatalog_deferFullTextIndexActivity
erp5_mysql_innodb/SQLCatalog_deferUncatalogObject
erp5_mysql_innodb/SQLCatalog_deferUncatalogObjectActivity
erp5_mysql_innodb/SQLCatalog_makeFullTextQuery erp5_mysql_innodb/SQLCatalog_makeFullTextQuery
erp5_mysql_innodb/z0_drop_catalog_fulltext erp5_mysql_innodb/z0_drop_catalog_fulltext
erp5_mysql_innodb/z0_drop_content_translation erp5_mysql_innodb/z0_drop_content_translation
......
...@@ -29,6 +29,8 @@ def filterActions(actions): ...@@ -29,6 +29,8 @@ def filterActions(actions):
filtered_actions[action_category_name].extend(action_list) filtered_actions[action_category_name].extend(action_list)
else: else:
filtered_actions[action_category_name] = action_list filtered_actions[action_category_name] = action_list
if filter_action_script_id:
filtered_actions = getattr(context, filter_action_script_id)(filtered_actions)
return {action_category_name: sorted(action_list, key=lambda x: x.get('priority', 1.0)) return {action_category_name: sorted(action_list, key=lambda x: x.get('priority', 1.0))
for action_category_name, action_list in filtered_actions.items()} for action_category_name, action_list in filtered_actions.items()}
......
...@@ -50,7 +50,7 @@ ...@@ -50,7 +50,7 @@
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>actions</string> </value> <value> <string>actions, filter_action_script_id=None</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
...@@ -1472,8 +1472,12 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None, ...@@ -1472,8 +1472,12 @@ def calculateHateoas(is_portal=None, is_site_root=None, traversed_document=None,
} }
# Find current action URL and extract embedded view # Find current action URL and extract embedded view
filter_action_script_id = ''
if hasattr(site_root, 'getLayoutProperty'):
filter_action_script_id = site_root.getLayoutProperty('configuration_filter_action_script_id', default='')
erp5_action_dict = portal.Base_filterDuplicateActions( erp5_action_dict = portal.Base_filterDuplicateActions(
portal.portal_actions.listFilteredActionsFor(traversed_document)) portal.portal_actions.listFilteredActionsFor(traversed_document),
filter_action_script_id)
for erp5_action_key in erp5_action_dict.keys(): for erp5_action_key in erp5_action_dict.keys():
for view_action in erp5_action_dict[erp5_action_key]: for view_action in erp5_action_dict[erp5_action_key]:
# Try to embed the form in the result # Try to embed the form in the result
......
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
<list> <list>
<string>my_configuration_login</string> <string>my_configuration_login</string>
<string>my_configuration_logout</string> <string>my_configuration_logout</string>
<string>my_configuration_filter_action_script_id</string>
</list> </list>
</value> </value>
</item> </item>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_configuration_filter_action_script_id</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_view_mode_reference</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>target</string> </key>
<value> <string>Click to edit the target</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Filter Action Script Id</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -709,6 +709,61 @@ class TestERP5Document_getHateoas_mode_traverse(ERP5HALJSONStyleSkinsMixin): ...@@ -709,6 +709,61 @@ class TestERP5Document_getHateoas_mode_traverse(ERP5HALJSONStyleSkinsMixin):
document.getRelativeUrl())) document.getRelativeUrl()))
self.assertEqual(result_dict['_embedded']['_view']['_actions']['put']['method'], 'POST') self.assertEqual(result_dict['_embedded']['_view']['_actions']['put']['method'], 'POST')
@simulate('Base_getRequestUrl', '*args, **kwargs',
'return "http://example.org/bar"')
@simulate('Base_getRequestHeader', '*args, **kwargs',
'return "application/hal+json"')
@simulate('Base_filterActionId', 'actions', """
filtered_actions = {}
for action_category_name, action_list in actions.items():
filtered_actions[action_category_name] = [action for action in action_list if 'foo' in action['id']]
return filtered_actions
""")
@changeSkin('Hal')
def test_getHateoasDocument_filtered_view(self):
self.portal.web_site_module.hateoas.edit(configuration_filter_action_script_id='Base_filterActionId')
document = self._makeDocument()
document.Foo_view.listbox.ListBox_setPropertyList(
field_title='Foo Lines',
field_list_method='objectValues',
field_portal_types='Foo Line | Foo Line',
field_stat_method='portal_catalog',
field_stat_columns='quantity | Foo_statQuantity',
field_editable=1,
field_columns='id|ID\ntitle|Title\nquantity|Quantity\nstart_date|Date\ncatalog.uid|Uid',
field_editable_columns='id|ID\ntitle|Title\nquantity|quantity\nstart_date|Date',
field_search_columns='id|ID\ntitle|Title\nquantity|Quantity\nstart_date|Date',
field_domain_root_list='foo_category|FooCat\nfoo_domain|FooDomain\nnot_existing_domain|NotExisting',)
parent = document.getParentValue()
fake_request = do_fake_request("GET")
result = self.portal.web_site_module.hateoas.ERP5Document_getHateoas(REQUEST=fake_request, mode="traverse", relative_url=document.getRelativeUrl(), view="view")
self.assertEqual(fake_request.RESPONSE.status, 200)
self.assertEqual(fake_request.RESPONSE.getHeader('Content-Type'),
"application/hal+json"
)
result_dict = json.loads(result)
self.assertEqual(result_dict['_links']['self'], {"href": "http://example.org/bar"})
self.assertEqual(result_dict['_links']['parent'],
{"href": "urn:jio:get:%s" % parent.getRelativeUrl(), "name": parent.getTitle()})
self.assertEqual(result_dict['_links']['view']['href'],
"%s/web_site_module/hateoas/ERP5Document_getHateoas?mode=traverse&relative_url=%s&view=view_formbox_fooline" % (
self.portal.absolute_url(),
quote_plus(document.getRelativeUrl())))
self.assertEqual(result_dict['_links']['view']['title'], "FormBox FooLine")
self.assertEqual(result_dict['_links']['view']['name'], "view_formbox_fooline")
self.assertNotIn('_embedded', result_dict)
for category, value in result_dict['_links'].items():
if 'action' in category:
if isinstance(value, dict):
self.assertIn('foo', value['name'])
else:
for link in value:
self.assertIn('foo', link['name'])
@simulate('Base_getRequestUrl', '*args, **kwargs', @simulate('Base_getRequestUrl', '*args, **kwargs',
'return "http://example.org/bar"') 'return "http://example.org/bar"')
@simulate('Base_getRequestHeader', '*args, **kwargs', @simulate('Base_getRequestHeader', '*args, **kwargs',
......
...@@ -46,13 +46,13 @@ class MailevaSOAPConnector(XMLObject): ...@@ -46,13 +46,13 @@ class MailevaSOAPConnector(XMLObject):
security.declareObjectProtected(Permissions.AccessContentsInformation) security.declareObjectProtected(Permissions.AccessContentsInformation)
# Default Properties # Default Properties
property_sheets = ( PropertySheet.Base property_sheets = (PropertySheet.Base
, PropertySheet.XMLObject , PropertySheet.XMLObject
, PropertySheet.CategoryCore , PropertySheet.CategoryCore
) )
def processResponse(self, response, maileva_exchange, failed=False): def processResponse(self, response, maileva_exchange, failed=False):
maileva_exchange.edit( maileva_exchange.edit(
response = response response=response
) )
maileva_exchange.confirm() maileva_exchange.confirm()
# change state, no need to wait alarm check # change state, no need to wait alarm check
...@@ -61,28 +61,29 @@ class MailevaSOAPConnector(XMLObject): ...@@ -61,28 +61,29 @@ class MailevaSOAPConnector(XMLObject):
maileva_exchange.getFollowUpValue().fail() maileva_exchange.getFollowUpValue().fail()
def submitRequest(self, maileva_exchange): def submitRequest(self, maileva_exchange):
authenticated = HttpAuthenticated(username=self.getUserId(), password=self.getPassword()) authenticated = HttpAuthenticated(username=self.getUserId(),
password=self.getPassword())
runtime_environment = self.getActivityRuntimeEnvironment() runtime_environment = self.getActivityRuntimeEnvironment()
if runtime_environment: if runtime_environment:
runtime_environment.edit( runtime_environment.edit(
conflict_retry=False, conflict_retry=False,
max_retry=0) max_retry=0)
try: try:
response = suds.client.Client(url = self.getProperty('submit_url_string'), transport=authenticated).service.submit(__inject={'msg': maileva_exchange.getRequest()}) response = suds.client.Client(
url=self.getSubmitLinkUrlString(),
transport=authenticated
).service.submit(__inject={'msg': maileva_exchange.getRequest()})
maileva_exchange.activate().MailevaExchange_processResponse(response) maileva_exchange.activate().MailevaExchange_processResponse(response)
except socket.error as e: except socket.error as e:
if e.errno == socket.errno.ECONNREFUSED: if e.errno == socket.errno.ECONNREFUSED:
if runtime_environment: if runtime_environment:
runtime_environment.edit(max_retry=None) runtime_environment.edit(max_retry=None)
except Exception as e: except Exception as e:
maileva_exchange.activate().MailevaExchange_processResponse(str(e), failed = True) maileva_exchange.activate().MailevaExchange_processResponse(str(e), failed=True)
def checkPendingNotifications(self): def checkPendingNotifications(self):
authenticated = HttpAuthenticated(username=self.getUserId(), password=self.getPassword()) authenticated = HttpAuthenticated(username=self.getUserId(), password=self.getPassword())
client = suds.client.Client(url = self.getProperty("tracking_url_string"), transport=authenticated) client = suds.client.Client(url=self.getTrackingLinkUrlString(), transport=authenticated)
notification_dict = {} notification_dict = {}
for notification in client.service.checkPendingNotifications("GENERAL"): for notification in client.service.checkPendingNotifications("GENERAL"):
notification_dict[notification.reqTrackId] = { notification_dict[notification.reqTrackId] = {
...@@ -95,7 +96,8 @@ class MailevaSOAPConnector(XMLObject): ...@@ -95,7 +96,8 @@ class MailevaSOAPConnector(XMLObject):
def getPendingNotificationDetails(self, request_id, debug=False): def getPendingNotificationDetails(self, request_id, debug=False):
authenticated = HttpAuthenticated(username=self.getUserId(), password=self.getPassword()) authenticated = HttpAuthenticated(username=self.getUserId(), password=self.getPassword())
result = suds.client.Client(url = self.getProperty("tracking_url_string"), transport=authenticated).service.getPendingNotificationDetails(request_id) result = suds.client.Client(url=self.getTrackingLinkUrlString(),
transport=authenticated).service.getPendingNotificationDetails(request_id)
return { return {
"status": str(result.status), "status": str(result.status),
"notification_status": str(result.notificationStatus), "notification_status": str(result.notificationStatus),
......
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
</portal_type> </portal_type>
<portal_type id="Maileva SOAP Connector"> <portal_type id="Maileva SOAP Connector">
<item>Login</item> <item>Login</item>
<item>MailevaSOAPConnector</item>
<item>Reference</item> <item>Reference</item>
<item>Url</item> <item>Url</item>
</portal_type> </portal_type>
......
...@@ -38,6 +38,12 @@ ...@@ -38,6 +38,12 @@
<key> <string>portal_type</string> </key> <key> <string>portal_type</string> </key>
<value> <string>Base Type</string> </value> <value> <string>Base Type</string> </value>
</item> </item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item> <item>
<key> <string>type_class</string> </key> <key> <string>type_class</string> </key>
<value> <string>MailevaSOAPConnector</string> </value> <value> <string>MailevaSOAPConnector</string> </value>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Property Sheet" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_count</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_mt_index</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>_tree</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAQ=</string> </persistent>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>MailevaSOAPConnector</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Property Sheet</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="Length" module="BTrees.Length"/>
</pickle>
<pickle> <int>0</int> </pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
<record id="4" aka="AAAAAAAAAAQ=">
<pickle>
<global name="OOBTree" module="BTrees.OOBTree"/>
</pickle>
<pickle>
<none/>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Content Existence Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>constraint_portal_type</string> </key>
<value> <string>python: (\'Link\',)</string> </value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>link_existence_constraint</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Content Existence Constraint</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="String Attribute Match Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>message_property_not_set</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>constraint_property</string> </key>
<value>
<tuple>
<string>password</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>password_constraint</string> </value>
</item>
<item>
<key> <string>message_attribute_not_match</string> </key>
<value> <string>password has to be set.</string> </value>
</item>
<item>
<key> <string>message_no_such_property</string> </key>
<value> <string>password has to be set.</string> </value>
</item>
<item>
<key> <string>message_property_not_set</string> </key>
<value> <string>Certificate has to be set.</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>String Attribute Match Constraint</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Acquired Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>acquisition_object_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>alt_accessor_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/content</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_acquired_property_id</string> </key>
<value>
<tuple>
<string>url_string</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_portal_type</string> </key>
<value> <string>python: (\'Link\',)</string> </value>
</item>
<item>
<key> <string>content_translation_acquired_property_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Include link URL</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>submit_link_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Acquired Property</string> </value>
</item>
<item>
<key> <string>storage_id</string> </key>
<value> <string>submit_link</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="String Attribute Match Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>message_property_not_set</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>constraint_property</string> </key>
<value>
<tuple>
<string>submit_link_url_string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>submit_link_url_string_constraint</string> </value>
</item>
<item>
<key> <string>message_attribute_not_match</string> </key>
<value> <string>Submit URL have to be set</string> </value>
</item>
<item>
<key> <string>message_no_such_property</string> </key>
<value> <string>Submit URL have to be set</string> </value>
</item>
<item>
<key> <string>message_property_not_set</string> </key>
<value> <string>Payzen URL have to be set</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>String Attribute Match Constraint</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Acquired Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>acquisition_object_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>alt_accessor_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/content</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_acquired_property_id</string> </key>
<value>
<tuple>
<string>url_string</string>
</tuple>
</value>
</item>
<item>
<key> <string>content_portal_type</string> </key>
<value> <string>python: (\'Link\',)</string> </value>
</item>
<item>
<key> <string>content_translation_acquired_property_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Link for tracking url</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>tracking_link_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Acquired Property</string> </value>
</item>
<item>
<key> <string>storage_id</string> </key>
<value> <string>tracking_link</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="String Attribute Match Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>message_property_not_set</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>constraint_property</string> </key>
<value>
<tuple>
<string>tracking_link_url_string</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>tracking_link_url_string_constraint</string> </value>
</item>
<item>
<key> <string>message_attribute_not_match</string> </key>
<value> <string>Tracking URL have to be set</string> </value>
</item>
<item>
<key> <string>message_no_such_property</string> </key>
<value> <string>Tracking URL have to be set</string> </value>
</item>
<item>
<key> <string>message_property_not_set</string> </key>
<value> <string>Payzen URL have to be set</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>String Attribute Match Constraint</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="String Attribute Match Constraint" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_identity_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>message_property_not_set</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>_range_criterion</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAM=</string> </persistent>
</value>
</item>
<item>
<key> <string>constraint_property</string> </key>
<value>
<tuple>
<string>user_id</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>user_id_constraint</string> </value>
</item>
<item>
<key> <string>message_attribute_not_match</string> </key>
<value> <string>User ID have to be set</string> </value>
</item>
<item>
<key> <string>message_no_such_property</string> </key>
<value> <string>User ID have to be set</string> </value>
</item>
<item>
<key> <string>message_property_not_set</string> </key>
<value> <string>vads_site_id have to be set</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>String Attribute Match Constraint</string> </value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="3" aka="AAAAAAAAAAM=">
<pickle>
<global name="PersistentMapping" module="Persistence.mapping"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>data</string> </key>
<value>
<dictionary/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
maileva_connector = context.portal_catalog.getResultValue( maileva_connector_list = context.portal_catalog(
portal_type='Maileva SOAP Connector', portal_type='Maileva SOAP Connector',
reference=reference, validation_state='validated',
validation_state='validated') limit=2)
if not maileva_connector:
raise ValueError('Maileav soap connector is not defined') # Ensure there is no duplication.
return maileva_connector if not len(maileva_connector_list):
raise ValueError('Maileva soap connector is not defined')
elif len(maileva_connector_list) != 1:
raise ValueError('More them one Maileva soap connector was found!')
return maileva_connector_list[0]
...@@ -115,8 +115,8 @@ ...@@ -115,8 +115,8 @@
<key> <string>right</string> </key> <key> <string>right</string> </key>
<value> <value>
<list> <list>
<string>my_submit_url_string</string> <string>my_submit_link_url_string</string>
<string>my_tracking_url_string</string> <string>my_tracking_link_url_string</string>
<string>my_translated_validation_state_title</string> <string>my_translated_validation_state_title</string>
</list> </list>
</value> </value>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>my_submit_url_string</string> </value> <value> <string>my_submit_link_url_string</string> </value>
</item> </item>
<item> <item>
<key> <string>message_values</string> </key> <key> <string>message_values</string> </key>
......
...@@ -16,7 +16,7 @@ ...@@ -16,7 +16,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>my_tracking_url_string</string> </value> <value> <string>my_tracking_link_url_string</string> </value>
</item> </item>
<item> <item>
<key> <string>message_values</string> </key> <key> <string>message_values</string> </key>
......
translateString = context.Base_translateString
if context.getSendState() != 'failed': if context.getSendState() != 'failed':
return context.Base_redirect('Document_viewMailevaConnectionStatus', keep_items={'portal_status_message': 'This document is not in failed state'}) return context.Base_redirect('Document_viewMailevaConnectionStatus',
keep_items={'portal_status_message': translateString('This document is not in failed state')})
maileva_exchange = context.getFollowUpRelatedValue(portal_type='Maileva Exchange') maileva_exchange = context.getFollowUpRelatedValue(portal_type='Maileva Exchange')
context.PDF_sendToMaileva( context.PDF_sendToMaileva(
recipient = maileva_exchange.getDestinationValue(), recipient = maileva_exchange.getDestinationValue(),
sender = maileva_exchange.getSourceValue() sender = maileva_exchange.getSourceValue()
) )
return context.Base_redirect('PDF_viewPDFJSPreview', keep_items={'portal_status_message': 'This document is resending to maileva'}) return context.Base_redirect('PDF_viewPDFJSPreview',
keep_items={'portal_status_message': translateString('This document is resending to maileva')})
...@@ -3,5 +3,6 @@ Maileva Exchange | Arrow ...@@ -3,5 +3,6 @@ Maileva Exchange | Arrow
Maileva Exchange | Event Maileva Exchange | Event
Maileva Exchange | HttpExchange Maileva Exchange | HttpExchange
Maileva SOAP Connector | Login Maileva SOAP Connector | Login
Maileva SOAP Connector | MailevaSOAPConnector
Maileva SOAP Connector | Reference Maileva SOAP Connector | Reference
Maileva SOAP Connector | Url Maileva SOAP Connector | Url
\ No newline at end of file
MailevaSOAPConnector
\ No newline at end of file
...@@ -242,8 +242,8 @@ $script.onload = function() { ...@@ -242,8 +242,8 @@ $script.onload = function() {
"pylint", "pylint",
data["annotations"].map(annotation => { data["annotations"].map(annotation => {
return { return {
startLineNumber: annotation.row + 1, startLineNumber: annotation.row,
endLineNumber: annotation.row + 1, endLineNumber: annotation.row,
startColumn: annotation.col, startColumn: annotation.col,
endColumn: Infinity, endColumn: Infinity,
message: annotation.text, message: annotation.text,
......
...@@ -127,7 +127,7 @@ ...@@ -127,7 +127,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>_text</string> </key> <key> <string>_text</string> </key>
<value> <string>python: here.getResourceValue().getVariationBaseCategoryItemList(omit_optional_variation=1, display_id=\'translated_title\')</string> </value> <value> <string>python: here.getResourceValue().getVariationBaseCategoryItemList(display_id=\'translated_title\')</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
# #
############################################################################## ##############################################################################
import random
import unittest import unittest
from Products.ERP5Type.tests.ERP5TypeFunctionalTestCase import \ from Products.ERP5Type.tests.ERP5TypeFunctionalTestCase import \
...@@ -91,11 +90,6 @@ class TestZeleniumStandaloneUserTutorial(ERP5TypeFunctionalTestCase): ...@@ -91,11 +90,6 @@ class TestZeleniumStandaloneUserTutorial(ERP5TypeFunctionalTestCase):
# Execute the business configuration if not installed # Execute the business configuration if not installed
business_configuration = self.getBusinessConfiguration() business_configuration = self.getBusinessConfiguration()
if (business_configuration.getSimulationState() != 'installed'): if (business_configuration.getSimulationState() != 'installed'):
self.portal.portal_caches.erp5_site_global_id = '%s' % random.random()
self.portal.portal_caches._p_changed = 1
self.commit()
self.portal.portal_caches.updateCache()
self.bootstrapSite() self.bootstrapSite()
self.commit() self.commit()
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>select_variable</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/multiple selection</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Methods to be called to catalog the list of objects with a deferred connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>sql_deferred_catalog_object_list_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>select_variable</string> </key>
<value> <string>getCatalogMethodIds</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Standard Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_local_properties</string> </key>
<value>
<tuple>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>mode</string> </value>
</item>
<item>
<key> <string>type</string> </key>
<value> <string>string</string> </value>
</item>
</dictionary>
</tuple>
</value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>elementary_type/multiple selection</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Methods to be called to uncatalog an object with a deferred connection</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>sql_deferred_uncatalog_object_property</string> </value>
</item>
<item>
<key> <string>mode</string> </key>
<value> <string>w</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Standard Property</string> </value>
</item>
<item>
<key> <string>select_variable</string> </key>
<value> <string>getCatalogMethodIds</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -118,7 +118,9 @@ ...@@ -118,7 +118,9 @@
<value> <value>
<list> <list>
<string>my_sql_catalog_object_list_list</string> <string>my_sql_catalog_object_list_list</string>
<string>my_sql_deferred_catalog_object_list_list</string>
<string>my_sql_uncatalog_object_list</string> <string>my_sql_uncatalog_object_list</string>
<string>my_sql_deferred_uncatalog_object_list</string>
<string>my_sql_search_tables_list</string> <string>my_sql_search_tables_list</string>
<string>my_sql_catalog_datetime_search_keys_list</string> <string>my_sql_catalog_datetime_search_keys_list</string>
</list> </list>
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>items</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_sql_deferred_catalog_object_list_list</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>items</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_multi_list_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>items</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Deferred Catalog Objects</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python:[(\'\', \'\')]+here.getCatalogMethodIds()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="ProxyField" module="Products.ERP5Form.ProxyField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>delegated_list</string> </key>
<value>
<list>
<string>items</string>
<string>title</string>
</list>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>my_sql_deferred_uncatalog_object_list</string> </value>
</item>
<item>
<key> <string>message_values</string> </key>
<value>
<dictionary>
<item>
<key> <string>external_validator_failed</string> </key>
<value> <string>The input failed the external validator.</string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>overrides</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>tales</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>items</string> </key>
<value>
<persistent> <string encoding="base64">AAAAAAAAAAI=</string> </persistent>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string></string> </value>
</item>
</dictionary>
</value>
</item>
<item>
<key> <string>values</string> </key>
<value>
<dictionary>
<item>
<key> <string>field_id</string> </key>
<value> <string>my_multi_list_field</string> </value>
</item>
<item>
<key> <string>form_id</string> </key>
<value> <string>Base_viewFieldLibrary</string> </value>
</item>
<item>
<key> <string>items</string> </key>
<value>
<list/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Deferred Uncatalog Object</string> </value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record id="2" aka="AAAAAAAAAAI=">
<pickle>
<global name="TALESMethod" module="Products.Formulator.TALESField"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_text</string> </key>
<value> <string>python:[(\'\', \'\')]+here.getCatalogMethodIds()</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -889,10 +889,15 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): ...@@ -889,10 +889,15 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject):
""" """
return ZCatalog.countResults(self, REQUEST, **kw) return ZCatalog.countResults(self, REQUEST, **kw)
def wrapObjectList(self, object_value_list, catalog_value): def wrapObjectList(self, object_value_list, catalog_value, deferred=False):
""" """
Return a list of wrapped objects for reindexing. Return a list of wrapped objects for reindexing.
""" """
if deferred:
# No need to wrap, but should return a list
if isinstance(object_value_list, set):
object_value_list = list(object_value_list)
return object_value_list
portal = self.getPortalObject() portal = self.getPortalObject()
user_set = set() user_set = set()
...@@ -973,7 +978,7 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): ...@@ -973,7 +978,7 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject):
security.declarePrivate('reindexObject') security.declarePrivate('reindexObject')
reindexObject = reindexCatalogObject reindexObject = reindexCatalogObject
security.declarePrivate('catalogObjectList')
def catalogObjectList(self, object_list, *args, **kw): def catalogObjectList(self, object_list, *args, **kw):
"""Catalog a list of objects""" """Catalog a list of objects"""
m = object_list[0] m = object_list[0]
...@@ -990,6 +995,9 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject): ...@@ -990,6 +995,9 @@ class CatalogTool (UniqueObject, ZCatalog, CMFCoreCatalogTool, ActiveObject):
else: else:
super(CatalogTool, self).catalogObjectList(object_list, *args, **kw) super(CatalogTool, self).catalogObjectList(object_list, *args, **kw)
security.declarePrivate('deferredCatalogObjectList')
deferredCatalogObjectList = catalogObjectList
security.declarePrivate('uncatalogObjectList') security.declarePrivate('uncatalogObjectList')
def uncatalogObjectList(self, message_list): def uncatalogObjectList(self, message_list):
"""Uncatalog a list of objects""" """Uncatalog a list of objects"""
......
...@@ -363,7 +363,7 @@ class OOoTemplate(ZopePageTemplate): ...@@ -363,7 +363,7 @@ class OOoTemplate(ZopePageTemplate):
picture_type = picture.content_type() picture_type = picture.content_type()
else: else:
# "standard" filetype case (Image or File) # "standard" filetype case (Image or File)
picture_data = str(picture_data) picture_data = bytes(picture_data)
if picture_type is None: if picture_type is None:
picture_type = picture.getContentType() picture_type = picture.getContentType()
......
...@@ -28,7 +28,6 @@ ...@@ -28,7 +28,6 @@
############################################################################## ##############################################################################
import os import os
import unittest
from io import BytesIO from io import BytesIO
from zipfile import ZipFile from zipfile import ZipFile
from Products.ERP5Type.tests.utils import FileUpload from Products.ERP5Type.tests.utils import FileUpload
...@@ -216,6 +215,7 @@ return getattr(context, "%s_%s" % (parameter, current_language)) ...@@ -216,6 +215,7 @@ return getattr(context, "%s_%s" % (parameter, current_language))
file_path = os.path.join(os.path.dirname(__file__), 'test_document', file_path = os.path.join(os.path.dirname(__file__), 'test_document',
filename) filename)
upload_file = FileUpload(file_path) upload_file = FileUpload(file_path)
self.addCleanup(upload_file.close)
document = self.portal.portal_contributions.newContent(file=upload_file) document = self.portal.portal_contributions.newContent(file=upload_file)
addOOoTemplate = self.getPortal().manage_addProduct['ERP5OOo'].addOOoTemplate addOOoTemplate = self.getPortal().manage_addProduct['ERP5OOo'].addOOoTemplate
addOOoTemplate(id='Base_viewIncludeImageAsOdt', title='') addOOoTemplate(id='Base_viewIncludeImageAsOdt', title='')
...@@ -239,17 +239,14 @@ return getattr(context, "%s_%s" % (parameter, current_language)) ...@@ -239,17 +239,14 @@ return getattr(context, "%s_%s" % (parameter, current_language))
cs = BytesIO() cs = BytesIO()
cs.write(body) cs.write(body)
zip_document = ZipFile(cs) zip_document = ZipFile(cs)
picture_list = filter(lambda x: "Pictures" in x.filename, picture_list = [x for x in zip_document.infolist() if "Pictures" in x.filename]
zip_document.infolist()) self.assertTrue(picture_list)
self.assertNotEqual([], picture_list)
manifest = bytes2str(zip_document.read('META-INF/manifest.xml')) manifest = bytes2str(zip_document.read('META-INF/manifest.xml'))
content = bytes2str(zip_document.read('content.xml')) content = bytes2str(zip_document.read('content.xml'))
for picture in picture_list: for picture in picture_list:
self.assertIn(picture.filename, manifest) self.assertIn(picture.filename, manifest)
self.assertIn(picture.filename, content) self.assertIn(picture.filename, content)
with open(file_path, 'rb') as f:
expected_data = f.read()
self.assertTrue([p for p in picture_list if zip_document.read(p) == expected_data])
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestOooDynamicStyle))
return suite
...@@ -315,6 +315,7 @@ class Test(ERP5TypeTestCase): ...@@ -315,6 +315,7 @@ class Test(ERP5TypeTestCase):
except ImportError: except ImportError:
import traceback import traceback
traceback.print_exc(file=global_stream) traceback.print_exc(file=global_stream)
traceback.print_exc() # also print on stderr
global_stream.seek(0) global_stream.seek(0)
return global_stream.read() return global_stream.read()
finally: finally:
......
...@@ -300,9 +300,6 @@ if memcache is not None: ...@@ -300,9 +300,6 @@ if memcache is not None:
if memcached_plugin is None: if memcached_plugin is None:
raise ValueError('Memcached Plugin does not exists: %r' % ( raise ValueError('Memcached Plugin does not exists: %r' % (
plugin_path, )) plugin_path, ))
global_prefix = self.erp5_site_global_id
if global_prefix:
key_prefix = global_prefix + '_' + key_prefix
return SharedDict(memcached_plugin.getConnection(), prefix=key_prefix) return SharedDict(memcached_plugin.getConnection(), prefix=key_prefix)
InitializeClass(MemcachedTool) InitializeClass(MemcachedTool)
......
...@@ -74,9 +74,10 @@ class OrderedPickler(Pickler): ...@@ -74,9 +74,10 @@ class OrderedPickler(Pickler):
dispatch = Pickler.dispatch.copy() dispatch = Pickler.dispatch.copy()
def save_dict(self, obj): def save_dict(self, obj):
return Pickler.save_dict( items = sorted(
self, obj.items(),
OrderedDict(sorted(obj.items()))) key=lambda item:str(item[0]))
return Pickler.save_dict(self, OrderedDict(items))
dispatch[dict] = save_dict dispatch[dict] = save_dict
......
...@@ -62,7 +62,12 @@ class CompatibilityDisableChecker(checkers.BaseChecker): ...@@ -62,7 +62,12 @@ class CompatibilityDisableChecker(checkers.BaseChecker):
"possibly-used-before-assignment", "possibly-used-before-assignment",
"possibly-used-before-assignment", "possibly-used-before-assignment",
"" ""
) ),
"E9987": (
"repeated-keyword",
"repeated-keyword",
""
),
} }
......
...@@ -291,12 +291,18 @@ def runLiveTest(test_list, verbosity=1, stream=None, request_server_url=None, ** ...@@ -291,12 +291,18 @@ def runLiveTest(test_list, verbosity=1, stream=None, request_server_url=None, **
output = stream output = stream
if stream is None: if stream is None:
output = StringIO() output = StringIO()
def print_and_write(data): class StderrIOWrapper:
def __init__(self, wrapped):
self._wrapped_io = wrapped
def write(self, data):
sys.stderr.write(data) sys.stderr.write(data)
sys.stderr.flush() return self._wrapped_io.write(data)
return output.write(data) def __getattr__(self, attr):
print_and_write("**Running Live Test:\n") return getattr(self._wrapped_io, attr)
ZopeTestCase._print = print_and_write
output = StderrIOWrapper(output)
output.write("**Running Live Test:\n")
ZopeTestCase._print = output.write
with warnings.catch_warnings(): with warnings.catch_warnings():
warnings.simplefilter(kw['warnings']) warnings.simplefilter(kw['warnings'])
...@@ -306,6 +312,6 @@ def runLiveTest(test_list, verbosity=1, stream=None, request_server_url=None, ** ...@@ -306,6 +312,6 @@ def runLiveTest(test_list, verbosity=1, stream=None, request_server_url=None, **
from AccessControl.SecurityManagement import getSecurityManager, setSecurityManager from AccessControl.SecurityManagement import getSecurityManager, setSecurityManager
sm = getSecurityManager() sm = getSecurityManager()
try: try:
result = TestRunner(stream=output, verbosity=verbosity).run(suite) TestRunner(stream=output, verbosity=verbosity).run(suite)
finally: finally:
setSecurityManager(sm) setSecurityManager(sm)
...@@ -7,7 +7,6 @@ ...@@ -7,7 +7,6 @@
__version__ = '0.3.0' __version__ = '0.3.0'
import base64
import errno import errno
import os import os
import random import random
...@@ -17,6 +16,7 @@ import string ...@@ -17,6 +16,7 @@ import string
import sys import sys
import time import time
import traceback import traceback
import warnings
from six.moves import configparser from six.moves import configparser
from contextlib import contextmanager from contextlib import contextmanager
from io import BytesIO from io import BytesIO
...@@ -273,6 +273,10 @@ class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase, functional.F ...@@ -273,6 +273,10 @@ class ERP5TypeTestCaseMixin(ProcessingNodeTestCase, PortalTestCase, functional.F
def newPassword(self): def newPassword(self):
""" Generate a password """ """ Generate a password """
forced_password = os.environ.get('insecure_erp5_test_password')
if forced_password:
warnings.warn("Using password set from environment variable")
return forced_password
return ''.join(random.SystemRandom().sample(string.ascii_letters + string.digits, 20)) return ''.join(random.SystemRandom().sample(string.ascii_letters + string.digits, 20))
def login(self, user_name=None, quiet=0): def login(self, user_name=None, quiet=0):
...@@ -1317,10 +1321,6 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin): ...@@ -1317,10 +1321,6 @@ class ERP5TypeCommandLineTestCase(ERP5TypeTestCaseMixin):
reindex=reindex, reindex=reindex,
create_activities=create_activities, create_activities=create_activities,
**kw) **kw)
sql = kw.get('erp5_sql_connection_string')
if sql:
app[portal_name]._setProperty('erp5_site_global_id',
base64.standard_b64encode(str2bytes(sql)))
if not quiet: if not quiet:
ZopeTestCase._print('done (%.3fs)\n' % (time.time() - _start)) ZopeTestCase._print('done (%.3fs)\n' % (time.time() - _start))
# Release locks # Release locks
...@@ -1637,7 +1637,7 @@ optimize() ...@@ -1637,7 +1637,7 @@ optimize()
@onsetup @onsetup
def fortify(): def fortify():
'''Add some extra checks that we don't have at runtime, not to slow down the '''Add some extra checks that we don't have at runtime, not to slow down the
system. system and adjust the system for unit test environment.
''' '''
# check that we don't store persistent objects in cache # check that we don't store persistent objects in cache
from Products.ERP5Type.CachePlugins.BaseCache import CacheEntry from Products.ERP5Type.CachePlugins.BaseCache import CacheEntry
...@@ -1662,5 +1662,15 @@ def fortify(): ...@@ -1662,5 +1662,15 @@ def fortify():
activity_kw, *args, **kw) activity_kw, *args, **kw)
Message.__init__ = __init__ Message.__init__ = __init__
# Inject a prefix to keys used by memcached, so that when we are running
# multiple runUnitTest process using the same memcached instance they don't
# have conflicting keys.
import Products.ERP5Type.Tool.MemcachedTool
original_encodeKey = Products.ERP5Type.Tool.MemcachedTool.encodeKey
prefix = str2bytes(''.join(random.sample(string.ascii_letters + string.digits, 6)))
def encodeKey(key):
return prefix + original_encodeKey(key)
Products.ERP5Type.Tool.MemcachedTool.encodeKey = encodeKey
fortify() fortify()
...@@ -11,6 +11,8 @@ class SetupSiteError(Exception): ...@@ -11,6 +11,8 @@ class SetupSiteError(Exception):
def patch(): def patch():
import six import six
import contextlib
import sys
import traceback import traceback
from unittest import TestCase, TextTestResult, TextTestRunner from unittest import TestCase, TextTestResult, TextTestRunner
...@@ -21,6 +23,20 @@ def patch(): ...@@ -21,6 +23,20 @@ def patch():
TestCase.assertRaisesRegex = getattr(TestCase, 'assertRaisesRegexp') TestCase.assertRaisesRegex = getattr(TestCase, 'assertRaisesRegexp')
TestCase.assertRegex = getattr(TestCase, 'assertRegexpMatches') TestCase.assertRegex = getattr(TestCase, 'assertRegexpMatches')
TestCase.assertCountEqual = TestCase.assertItemsEqual TestCase.assertCountEqual = TestCase.assertItemsEqual
@contextlib.contextmanager
def subTest(self, msg='', **params):
yield
TestCase.subTest = subTest
if sys.version_info < (3, 11):
def enterContext(self, cm):
cls = type(cm)
enter = cls.__enter__
exit = cls.__exit__
result = enter(cm)
self.addCleanup(exit, cm, None, None, None)
return result
TestCase.enterContext = enterContext
TextTestResult_addError = six.get_unbound_function(TextTestResult.addError) TextTestResult_addError = six.get_unbound_function(TextTestResult.addError)
def addError(self, test, err): def addError(self, test, err):
......
...@@ -150,6 +150,7 @@ Options: ...@@ -150,6 +150,7 @@ Options:
timer service. timer service.
This option only makes sense with --activity_node= This option only makes sense with --activity_node=
or when not specifying a test to run. or when not specifying a test to run.
--insecure_password=PWD Use `PWD` instead of generating random passwords for users.
--zserver=ADDRESS[,...] Make ZServer listen on given IPv4 address. --zserver=ADDRESS[,...] Make ZServer listen on given IPv4 address.
Addresses can be given in the following syntaxs: Addresses can be given in the following syntaxs:
- HOST:PORT - HOST:PORT
...@@ -798,7 +799,8 @@ def main(argument_list=None): ...@@ -798,7 +799,8 @@ def main(argument_list=None):
"sys_path=", "sys_path=",
"instance_home=", "instance_home=",
"log_directory=", "log_directory=",
"with_wendelin_core" "with_wendelin_core",
"insecure_password=",
]) ])
except getopt.GetoptError as msg: except getopt.GetoptError as msg:
usage(sys.stderr, msg) usage(sys.stderr, msg)
...@@ -919,6 +921,8 @@ def main(argument_list=None): ...@@ -919,6 +921,8 @@ def main(argument_list=None):
_log_directory = os.path.abspath(arg) _log_directory = os.path.abspath(arg)
elif opt == "--with_wendelin_core": elif opt == "--with_wendelin_core":
os.environ["with_wendelin_core"] = "1" os.environ["with_wendelin_core"] = "1"
elif opt == "--insecure_password":
os.environ["insecure_erp5_test_password"] = arg
setupWarnings() setupWarnings()
......
...@@ -3255,17 +3255,9 @@ class Test(ERP5TypeTestCase): ...@@ -3255,17 +3255,9 @@ class Test(ERP5TypeTestCase):
self.assertNotEqual(os, None) self.assertNotEqual(os, None)
''' '''
def testRunLiveTest(self): def _runLiveTest(self, test_name):
"""Runs a live test from portal_components
""" """
Create a new ZODB Test Component and try to run it as a live tests and
check the expected output
"""
# First try with a test which run successfully
source_code = self._getValidSourceCode()
component = self._newComponent('testRunLiveTest', source_code)
component.validate()
self.tic()
from Products.ERP5Type.tests.runUnitTest import ERP5TypeTestLoader from Products.ERP5Type.tests.runUnitTest import ERP5TypeTestLoader
ERP5TypeTestLoader_loadTestsFromNames = ERP5TypeTestLoader.loadTestsFromNames ERP5TypeTestLoader_loadTestsFromNames = ERP5TypeTestLoader.loadTestsFromNames
def loadTestsFromNames(self, *args, **kwargs): def loadTestsFromNames(self, *args, **kwargs):
...@@ -3287,27 +3279,44 @@ class Test(ERP5TypeTestCase): ...@@ -3287,27 +3279,44 @@ class Test(ERP5TypeTestCase):
return ret return ret
self.assertEqual(component.getValidationState(), 'validated')
self.assertModuleImportable('testRunLiveTest')
self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
# set a request key, that should not be set from the test request
self.portal.REQUEST.set('foo', 'something from main request')
def runLiveTest(test_name):
# ERP5TypeLiveTestCase.runLiveTest patches ERP5TypeTestCase bases, thus it # ERP5TypeLiveTestCase.runLiveTest patches ERP5TypeTestCase bases, thus it
# needs to be restored after calling runLiveTest # needs to be restored after calling runLiveTest
base_tuple = ERP5TypeTestCase.__bases__ base_tuple = ERP5TypeTestCase.__bases__
ERP5TypeTestLoader.loadTestsFromNames = loadTestsFromNames ERP5TypeTestLoader.loadTestsFromNames = loadTestsFromNames
from six.moves import cStringIO as StringIO
stderr = StringIO()
_real_stderr = sys.stderr
sys.stderr = stderr
try: try:
self._component_tool.runLiveTest(test_name) self._component_tool.runLiveTest(test_name)
finally: finally:
ERP5TypeTestCase.__bases__ = base_tuple ERP5TypeTestCase.__bases__ = base_tuple
ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames
return self._component_tool.readTestOutput() sys.stderr = _real_stderr
test_output = self._component_tool.readTestOutput()
self.assertEqual(stderr.getvalue(), test_output)
return test_output
def testRunLiveTest(self):
"""
Create a new ZODB Test Component and try to run it as a live tests and
check the expected output
"""
# First try with a test which run successfully
source_code = self._getValidSourceCode()
component = self._newComponent('testRunLiveTest', source_code)
component.validate()
self.tic()
output = runLiveTest('testRunLiveTest') self.assertEqual(component.getValidationState(), 'validated')
self.assertModuleImportable('testRunLiveTest')
self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True)
# set a request key, that should not be set from the test request
self.portal.REQUEST.set('foo', 'something from main request')
output = self._runLiveTest('testRunLiveTest')
expected_msg_re = re.compile('Ran 1 test.*OK', re.DOTALL) expected_msg_re = re.compile('Ran 1 test.*OK', re.DOTALL)
self.assertRegex(output, expected_msg_re) self.assertRegex(output, expected_msg_re)
...@@ -3325,7 +3334,7 @@ class Test(ERP5TypeTestCase): ...@@ -3325,7 +3334,7 @@ class Test(ERP5TypeTestCase):
self._component_tool.reset(force=True, self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True) reset_portal_type_at_transaction_boundary=True)
output = runLiveTest('testRunLiveTest') output = self._runLiveTest('testRunLiveTest')
expected_msg_re = re.compile(r'Ran 2 tests.*FAILED \(failures=1\)', re.DOTALL) expected_msg_re = re.compile(r'Ran 2 tests.*FAILED \(failures=1\)', re.DOTALL)
self.assertRegex(output, expected_msg_re) self.assertRegex(output, expected_msg_re)
...@@ -3350,7 +3359,7 @@ class Test(ERP5TypeTestCase): ...@@ -3350,7 +3359,7 @@ class Test(ERP5TypeTestCase):
self._component_tool.reset(force=True, self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True) reset_portal_type_at_transaction_boundary=True)
output = runLiveTest('testRunLiveTest') output = self._runLiveTest('testRunLiveTest')
expected_msg_re = re.compile('Ran 3 test.*OK', re.DOTALL) expected_msg_re = re.compile('Ran 3 test.*OK', re.DOTALL)
self.assertRegex(output, expected_msg_re) self.assertRegex(output, expected_msg_re)
...@@ -3364,44 +3373,11 @@ break_at_import() ...@@ -3364,44 +3373,11 @@ break_at_import()
component.validate() component.validate()
self.tic() self.tic()
from Products.ERP5Type.tests.runUnitTest import ERP5TypeTestLoader
ERP5TypeTestLoader_loadTestsFromNames = ERP5TypeTestLoader.loadTestsFromNames
def loadTestsFromNames(self, *args, **kwargs):
"""
Monkey patched to simulate a reset right after importing the ZODB Test
Component whose Unit Tests are going to be executed
"""
ret = ERP5TypeTestLoader_loadTestsFromNames(self, *args, **kwargs)
from Products.ERP5.ERP5Site import getSite
getSite().portal_components.reset(force=True)
# Simulate a new REQUEST while the old one has been GC'ed
import erp5.component
erp5.component.ref_manager.clear()
import gc
gc.collect()
return ret
self.assertEqual(component.getValidationState(), 'validated') self.assertEqual(component.getValidationState(), 'validated')
self._component_tool.reset(force=True, self._component_tool.reset(force=True,
reset_portal_type_at_transaction_boundary=True) reset_portal_type_at_transaction_boundary=True)
def runLiveTest(test_name): output = self._runLiveTest('testRunLiveTestImportError')
# ERP5TypeLiveTestCase.runLiveTest patches ERP5TypeTestCase bases, thus it
# needs to be restored after calling runLiveTest
base_tuple = ERP5TypeTestCase.__bases__
ERP5TypeTestLoader.loadTestsFromNames = loadTestsFromNames
try:
self._component_tool.runLiveTest(test_name)
finally:
ERP5TypeTestCase.__bases__ = base_tuple
ERP5TypeTestLoader.loadTestsFromNames = ERP5TypeTestLoader_loadTestsFromNames
return self._component_tool.readTestOutput()
output = runLiveTest('testRunLiveTestImportError')
relative_url = 'portal_components/test.erp5.testRunLiveTestImportError' relative_url = 'portal_components/test.erp5.testRunLiveTestImportError'
if six.PY2: if six.PY2:
module_file = '<' + relative_url + '>' module_file = '<' + relative_url + '>'
...@@ -3417,7 +3393,7 @@ break_at_import() ...@@ -3417,7 +3393,7 @@ break_at_import()
%(error_message)s %(error_message)s
''' % dict(module_file=module_file, error_message=error_message), output) ''' % dict(module_file=module_file, error_message=error_message), output)
output = runLiveTest('testDoesNotExist_import_error_because_module_does_not_exist') output = self._runLiveTest('testDoesNotExist_import_error_because_module_does_not_exist')
if six.PY2: if six.PY2:
expected_output = "ImportError: No module named testDoesNotExist_import_error_because_module_does_not_exist" expected_output = "ImportError: No module named testDoesNotExist_import_error_because_module_does_not_exist"
else: else:
......
...@@ -12,7 +12,7 @@ from six.moves.urllib.parse import urljoin ...@@ -12,7 +12,7 @@ from six.moves.urllib.parse import urljoin
from lxml import etree from lxml import etree
from lxml.etree import Element, SubElement from lxml.etree import Element, SubElement
from lxml.builder import ElementMaker from lxml.builder import ElementMaker
from Products.ERP5Type.Utils import unicode2str, str2unicode from Products.ERP5Type.Utils import bytes2str, unicode2str, str2unicode
import re import re
import sys import sys
import six import six
...@@ -1145,7 +1145,7 @@ class MultiItemsWidget(ItemsWidget): ...@@ -1145,7 +1145,7 @@ class MultiItemsWidget(ItemsWidget):
d[item_value] = item_text d[item_value] = item_text
result = [] result = []
for e in value: for e in value:
result.append(d[e].replace('\xc2\xa0', '')) result.append(d[e].replace(bytes2str(b'\xc2\xa0'), ''))
return result return result
def render_odg(self, field, value, as_string, ooo_builder, REQUEST, def render_odg(self, field, value, as_string, ooo_builder, REQUEST,
......
...@@ -29,7 +29,6 @@ from OFS.Folder import Folder ...@@ -29,7 +29,6 @@ from OFS.Folder import Folder
from AccessControl import ClassSecurityInfo from AccessControl import ClassSecurityInfo
from AccessControl.Permissions import ( from AccessControl.Permissions import (
access_contents_information, access_contents_information,
import_export_objects,
manage_zcatalog_entries, manage_zcatalog_entries,
) )
from AccessControl.SimpleObjectPolicies import ContainerAssertions from AccessControl.SimpleObjectPolicies import ContainerAssertions
...@@ -54,10 +53,6 @@ import pprint ...@@ -54,10 +53,6 @@ import pprint
import re import re
import warnings import warnings
from contextlib import contextmanager from contextlib import contextmanager
from xml.dom.minidom import parse
from xml.sax.saxutils import escape, quoteattr
import os
from hashlib import md5
from .interfaces.query_catalog import ISearchKeyCatalog from .interfaces.query_catalog import ISearchKeyCatalog
from zope.interface.verify import verifyClass from zope.interface.verify import verifyClass
...@@ -402,11 +397,21 @@ class Catalog(Folder, ...@@ -402,11 +397,21 @@ class Catalog(Folder,
'type' : 'multiple selection', 'type' : 'multiple selection',
'select_variable' : 'getCatalogMethodIds', 'select_variable' : 'getCatalogMethodIds',
'mode' : 'w' }, 'mode' : 'w' },
{ 'id' : 'sql_deferred_catalog_object_list',
'description' : 'Methods to be called to catalog the list of objects with a deferred connection',
'type' : 'multiple selection',
'select_variable' : 'getCatalogMethodIds',
'mode' : 'w' },
{ 'id' : 'sql_uncatalog_object', { 'id' : 'sql_uncatalog_object',
'description' : 'Methods to be called to uncatalog an object', 'description' : 'Methods to be called to uncatalog an object',
'type' : 'multiple selection', 'type' : 'multiple selection',
'select_variable' : 'getCatalogMethodIds', 'select_variable' : 'getCatalogMethodIds',
'mode' : 'w' }, 'mode' : 'w' },
{ 'id' : 'sql_deferred_uncatalog_object',
'description' : 'Methods to be called to uncatalog an object with a deferred connection',
'type' : 'multiple selection',
'select_variable' : 'getCatalogMethodIds',
'mode' : 'w' },
{ 'id' : 'sql_catalog_translation_list', { 'id' : 'sql_catalog_translation_list',
'description' : 'Methods to be called to catalog the list of translation objects', 'description' : 'Methods to be called to catalog the list of translation objects',
'type' : 'selection', 'type' : 'selection',
...@@ -587,7 +592,9 @@ class Catalog(Folder, ...@@ -587,7 +592,9 @@ class Catalog(Folder,
sql_catalog_delete_uid = '' sql_catalog_delete_uid = ''
sql_catalog_clear_reserved = '' sql_catalog_clear_reserved = ''
sql_catalog_object_list = () sql_catalog_object_list = ()
sql_deferred_catalog_object_list = ()
sql_uncatalog_object = () sql_uncatalog_object = ()
sql_deferred_uncatalog_object = ()
sql_clear_catalog = () sql_clear_catalog = ()
sql_catalog_translation_list = '' sql_catalog_translation_list = ''
sql_delete_translation_list = '' sql_delete_translation_list = ''
...@@ -1217,11 +1224,10 @@ class Catalog(Folder, ...@@ -1217,11 +1224,10 @@ class Catalog(Folder,
elapse = time.time() elapse = time.time()
c_elapse = time.clock() c_elapse = time.clock()
words = 0
obj = REQUEST.PARENTS[1] obj = REQUEST.PARENTS[1]
path = '/'.join(obj.getPhysicalPath()) path = '/'.join(obj.getPhysicalPath())
results = self.aq_parent.ZopeFindAndApply(obj, self.aq_parent.ZopeFindAndApply(obj,
obj_metatypes=obj_metatypes, obj_metatypes=obj_metatypes,
obj_ids=obj_ids, obj_ids=obj_ids,
obj_searchterm=obj_searchterm, obj_searchterm=obj_searchterm,
...@@ -1252,7 +1258,7 @@ class Catalog(Folder, ...@@ -1252,7 +1258,7 @@ class Catalog(Folder,
security.declarePrivate('catalogObjectList') security.declarePrivate('catalogObjectList')
def catalogObjectList(self, object_list, method_id_list=None, def catalogObjectList(self, object_list, method_id_list=None,
disable_cache=0, check_uid=1, idxs=None): disable_cache=0, check_uid=1, idxs=None, deferred=0):
"""Add objects to the Catalog by calling all SQL methods and """Add objects to the Catalog by calling all SQL methods and
providing needed arguments. providing needed arguments.
...@@ -1276,13 +1282,17 @@ class Catalog(Folder, ...@@ -1276,13 +1282,17 @@ class Catalog(Folder,
method_id_list=method_id_list, method_id_list=method_id_list,
disable_cache=disable_cache, disable_cache=disable_cache,
check_uid=check_uid, check_uid=check_uid,
idxs=idxs) idxs=idxs,
deferred=deferred)
def getSqlCatalogObjectListList(self): def getSqlCatalogObjectListList(self):
return self.sql_catalog_object_list return self.sql_catalog_object_list
def getSqlDeferredCatalogObjectListList(self):
return self.sql_deferred_catalog_object_list
def _catalogObjectList(self, object_list, method_id_list=None, def _catalogObjectList(self, object_list, method_id_list=None,
disable_cache=0, check_uid=1, idxs=None): disable_cache=0, check_uid=1, idxs=None, deferred=0):
"""This is the real method to catalog objects.""" """This is the real method to catalog objects."""
if idxs not in (None, []): if idxs not in (None, []):
LOG('ZSLQCatalog.SQLCatalog:catalogObjectList', WARNING, LOG('ZSLQCatalog.SQLCatalog:catalogObjectList', WARNING,
...@@ -1349,6 +1359,9 @@ class Catalog(Folder, ...@@ -1349,6 +1359,9 @@ class Catalog(Folder,
LOG('SQLCatalog._catalogObjectList', ERROR, error_message) LOG('SQLCatalog._catalogObjectList', ERROR, error_message)
if method_id_list is None: if method_id_list is None:
if deferred:
method_id_list = self.getSqlDeferredCatalogObjectListList()
else:
method_id_list = self.getSqlCatalogObjectListList() method_id_list = self.getSqlCatalogObjectListList()
econtext = getEngine().getContext() econtext = getEngine().getContext()
if disable_cache: if disable_cache:
...@@ -1496,6 +1509,9 @@ class Catalog(Folder, ...@@ -1496,6 +1509,9 @@ class Catalog(Folder,
def getSqlUncatalogObjectList(self): def getSqlUncatalogObjectList(self):
return self.sql_uncatalog_object return self.sql_uncatalog_object
def getSqlDeferredUncatalogObjectList(self):
return self.sql_deferred_uncatalog_object
security.declarePrivate('uncatalogObject') security.declarePrivate('uncatalogObject')
def uncatalogObject(self, path=None, uid=None): def uncatalogObject(self, path=None, uid=None):
""" """
...@@ -1874,9 +1890,7 @@ class Catalog(Folder, ...@@ -1874,9 +1890,7 @@ class Catalog(Folder,
""" """
search_key, related_key_definition = self.getColumnSearchKey(key, search_key, related_key_definition = self.getColumnSearchKey(key,
search_key_name=search_key_name) search_key_name=search_key_name)
if search_key is None: if search_key is not None:
result = None
else:
if related_key_definition is not None: if related_key_definition is not None:
search_key = search_key.getSearchKey(sql_catalog=self, search_key = search_key.getSearchKey(sql_catalog=self,
related_key_definition=related_key_definition, related_key_definition=related_key_definition,
...@@ -2450,30 +2464,12 @@ class Catalog(Folder, ...@@ -2450,30 +2464,12 @@ class Catalog(Folder,
if method.meta_type in ('Z SQL Method', 'ERP5 SQL Method') and ('deferred' in method.connection_id) == deferred: if method.meta_type in ('Z SQL Method', 'ERP5 SQL Method') and ('deferred' in method.connection_id) == deferred:
return method.connection_id return method.connection_id
def getSqlCatalogObjectList(self):
try:
return self.sql_catalog_object
except AttributeError:
return ()
def getSqlUncatalogObjectList(self):
try:
return self.sql_uncatalog_object
except AttributeError:
return ()
def getSqlUpdateObjectList(self): def getSqlUpdateObjectList(self):
try: try:
return self.sql_update_object return self.sql_update_object
except AttributeError: except AttributeError:
return () return ()
def getSqlCatalogObjectListList(self):
try:
return self.sql_catalog_object_list
except AttributeError:
return ()
security.declarePrivate('getFilterableMethodList') security.declarePrivate('getFilterableMethodList')
def getFilterableMethodList(self): def getFilterableMethodList(self):
""" """
...@@ -2482,10 +2478,11 @@ class Catalog(Folder, ...@@ -2482,10 +2478,11 @@ class Catalog(Folder,
method_id_set = set() method_id_set = set()
if withCMF: if withCMF:
method_id_set.update( method_id_set.update(
self.getSqlCatalogObjectList() + self.getSqlCatalogObjectListList() +
self.getSqlDeferredCatalogObjectListList() +
self.getSqlUncatalogObjectList() + self.getSqlUncatalogObjectList() +
self.getSqlUpdateObjectList() + self.getSqlDeferredUncatalogObjectList() +
self.getSqlCatalogObjectListList() self.getSqlUpdateObjectList()
) )
return [ return [
method method
......
...@@ -671,7 +671,7 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -671,7 +671,7 @@ class ZCatalog(Folder, Persistent, Implicit):
return [] return []
security.declarePrivate('wrapObjectList') security.declarePrivate('wrapObjectList')
def wrapObjectList(self, object_value_list, catalog_value): def wrapObjectList(self, object_value_list, catalog_value, deferred=False):
""" """
Return a list of wrapped objects for reindexing. Return a list of wrapped objects for reindexing.
...@@ -690,6 +690,7 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -690,6 +690,7 @@ class ZCatalog(Folder, Persistent, Implicit):
"""Catalog a list of objects. """Catalog a list of objects.
""" """
catalog = self.getSQLCatalog(sql_catalog_id) catalog = self.getSQLCatalog(sql_catalog_id)
deferred = kw.get('deferred', False)
hot_reindexing = (self.hot_reindexing_state is not None) and \ hot_reindexing = (self.hot_reindexing_state is not None) and \
(catalog is not None) and \ (catalog is not None) and \
(self.source_sql_catalog_id == catalog.id) (self.source_sql_catalog_id == catalog.id)
...@@ -791,6 +792,7 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -791,6 +792,7 @@ class ZCatalog(Folder, Persistent, Implicit):
self.wrapObjectList( self.wrapObjectList(
object_value_list=d['obj'], object_value_list=d['obj'],
catalog_value=destination_catalog, catalog_value=destination_catalog,
deferred=deferred,
), ),
**kw **kw
) )
...@@ -801,6 +803,7 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -801,6 +803,7 @@ class ZCatalog(Folder, Persistent, Implicit):
self.wrapObjectList( self.wrapObjectList(
object_value_list=d['obj'], object_value_list=d['obj'],
catalog_value=archive_catalog, catalog_value=archive_catalog,
deferred=deferred,
), ),
**kw **kw
) )
...@@ -815,6 +818,7 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -815,6 +818,7 @@ class ZCatalog(Folder, Persistent, Implicit):
self.wrapObjectList( self.wrapObjectList(
object_value_list=current_catalog_object_list, object_value_list=current_catalog_object_list,
catalog_value=catalog, catalog_value=catalog,
deferred=deferred,
), ),
**kw **kw
) )
...@@ -828,6 +832,7 @@ class ZCatalog(Folder, Persistent, Implicit): ...@@ -828,6 +832,7 @@ class ZCatalog(Folder, Persistent, Implicit):
self.wrapObjectList( self.wrapObjectList(
object_value_list=object_set, object_value_list=object_set,
catalog_value=destination_catalog, catalog_value=destination_catalog,
deferred=deferred,
), ),
**kw **kw
) )
......
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