Commit c302bb68 authored by Aurel's avatar Aurel

Merge remote-tracking branch 'origin/master' into syncml

parents be1773d5 011e5336
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Category" 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>acquisition_base_category</string> </key>
<value>
<tuple>
<string>order</string>
<string>parent</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_portal_type</string> </key>
<value> <string>python: list( portal.getPortalAcquisitionMovementTypeList() + portal.getPortalItemTypeList() + portal.getPortalDeliveryTypeList() + portal.getPortalOrderTypeList() + portal.getPortalInvoiceTypeList() + portal.getPortalSupplyTypeList() + portal.getPortalSupplyPathTypeList() + portal.getPortalModelPathTypeList())</string> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>journal</string>
</tuple>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>Journal is used to split deliveries of the same type in different subsets.</string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>journal</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Base Category</string> </value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Journal</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>
1048 1049
\ No newline at end of file \ No newline at end of file
...@@ -19,6 +19,7 @@ gender ...@@ -19,6 +19,7 @@ gender
grade grade
group group
insurance_coverage insurance_coverage
journal
legal_parent legal_parent
marital_status marital_status
market_segment market_segment
......
...@@ -64,12 +64,14 @@ person_mapping = (\n ...@@ -64,12 +64,14 @@ person_mapping = (\n
(\'date_of_birth\', \'birthday\'),\n (\'date_of_birth\', \'birthday\'),\n
(\'nationality\', \'nationality\'),\n (\'nationality\', \'nationality\'),\n
(\'default_email_text\', \'default_email_text\'),\n (\'default_email_text\', \'default_email_text\'),\n
(\'default_telephone_telephone_country\', \'default_telephone_telephone_country\'),\n
(\'default_telephone_text\', \'default_telephone_text\'),\n (\'default_telephone_text\', \'default_telephone_text\'),\n
(\'default_fax_text\', \'default_fax_text\'),\n (\'default_fax_text\', \'default_fax_text\'),\n
(\'default_address_street_address\', \'default_address_street_address\'),\n (\'default_address_street_address\', \'default_address_street_address\'),\n
(\'default_address_zip_code\', \'default_address_zip_code\'),\n (\'default_address_zip_code\', \'default_address_zip_code\'),\n
(\'default_address_city\', \'default_address_city\'),\n (\'default_address_city\', \'default_address_city\'),\n
(\'default_address_region\', \'default_address_region\'),\n (\'default_address_region\', \'default_address_region\'),\n
(\'default_mobile_telephone_telephone_country\', \'default_mobile_telephone_telephone_country\'),\n
(\'default_mobile_telephone_text\', \'default_mobile_telephone_text\'),\n (\'default_mobile_telephone_text\', \'default_mobile_telephone_text\'),\n
(\'activity_list\', \'default_career_activity_list\'),\n (\'activity_list\', \'default_career_activity_list\'),\n
(\'function_list\', \'default_career_function_list\'),\n (\'function_list\', \'default_career_function_list\'),\n
......
...@@ -69,7 +69,9 @@ else:\n ...@@ -69,7 +69,9 @@ else:\n
default_credential_question_question_free_text=default_credential_question_question_free_text,\n default_credential_question_question_free_text=default_credential_question_question_free_text,\n
default_credential_question_answer=default_credential_question_answer,\n default_credential_question_answer=default_credential_question_answer,\n
default_email_text=default_email_text,\n default_email_text=default_email_text,\n
default_telephone_telephone_country=default_telephone_telephone_country,\n
default_telephone_text=default_telephone_text,\n default_telephone_text=default_telephone_text,\n
default_mobile_telephone_telephone_country=default_mobile_telephone_telephone_country,\n
default_mobile_telephone_text=default_mobile_telephone_text,\n default_mobile_telephone_text=default_mobile_telephone_text,\n
default_fax_text=default_fax_text,\n default_fax_text=default_fax_text,\n
default_address_street_address=default_address_street_address,\n default_address_street_address=default_address_street_address,\n
...@@ -104,7 +106,7 @@ return portal.Base_redirect(keep_items = {\'portal_status_message\': portal_stat ...@@ -104,7 +106,7 @@ return portal.Base_redirect(keep_items = {\'portal_status_message\': portal_stat
</item> </item>
<item> <item>
<key> <string>_params</string> </key> <key> <string>_params</string> </key>
<value> <string>default_email_text=None, last_name=None, first_name=None, gender=None, nationality=None, password=None, date_of_birth=None, default_telephone_text=None, default_mobile_telephone_text=None, default_fax_text=None, default_credential_question_question=None, default_credential_question_question_free_text=None, default_credential_question_answer=None, function=None, activity_list=None, skill_list=None, default_address_city=None, default_address_street_address=None, default_address_zip_code=None,default_address_region=None,default_image_file=None, description=None, dialog_id=\'\', **kw</string> </value> <value> <string>default_email_text=None, last_name=None, first_name=None, gender=None, nationality=None, password=None, date_of_birth=None, default_telephone_telephone_country=None, default_telephone_text=None, default_mobile_telephone_telephone_country=None, default_mobile_telephone_text=None, default_fax_text=None, default_credential_question_question=None, default_credential_question_question_free_text=None, default_credential_question_answer=None, function=None, activity_list=None, skill_list=None, default_address_city=None, default_address_street_address=None, default_address_zip_code=None,default_address_region=None,default_image_file=None, description=None, dialog_id=\'\', **kw</string> </value>
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
......
424 425
\ No newline at end of file \ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="PythonScript" module="Products.PythonScripts.PythonScript"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>Script_magic</string> </key>
<value> <int>3</int> </value>
</item>
<item>
<key> <string>_bind_names</string> </key>
<value>
<object>
<klass>
<global name="NameAssignments" module="Shared.DC.Scripts.Bindings"/>
</klass>
<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>_body</string> </key>
<value> <string>"""\n
This script is supposed to be the common denominator for invoice reversing operations.\n
Instead of extending it, call it from project-specific script and edit returned document (or its lines).\n
"""\n
def recursiveCopyLine(to_document, from_document):\n
newContent = to_document.newContent\n
for line in from_document.objectValues(portal_type=\'Invoice Line\'):\n
reverse_line = newContent(\n
description=line.getDescription(),\n
int_index=line.getIntIndex(),\n
portal_type=line.getPortalType(),\n
price=line.getPrice(),\n
quantity=-line.getQuantity(), # Notice the "-" !\n
reference=line.getReference(),\n
category_list=line.getCategoryList(),\n
)\n
recursiveCopyLine(reverse_line, line)\n
newCell = reverse_line.newContent\n
for cell in line.objectValues(portal_type=\'Invoice Cell\'):\n
raise NotImplementedError\n
newCell(\n
# TODO: what properties ?\n
portal_type=cell.getPortalType(),\n
category_list=cell.getCategoryList(),\n
)\n
\n
portal = context.getPortalObject()\n
reverse_invoice = context.getParentValue().newContent(\n
portal_type=context.getPortalType(),\n
created_by_builder=1, # tell init script to not create lines\n
# Copy over all Arrow-ish relations\n
# XXX: it would be cleaner to query property sheet definition and check it applies to context\n
category_list=[x for x in context.getCategoryList() if x.startswith(\'source\') or x.startswith(\'destination\')],\n
)\n
# Separate edit to have stable outcome WRT category_list\n
reverse_invoice.edit(\n
causality_value=context,\n
specialise_list=context.getSpecialiseList(),\n
price_currency_list=context.getPriceCurrencyList(),\n
resource_list=context.getResourceList(),\n
)\n
recursiveCopyLine(reverse_invoice, context)\n
return reverse_invoice\n
</string> </value>
</item>
<item>
<key> <string>_params</string> </key>
<value> <string></string> </value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Invoice_createCreditNoteInvoice</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
390 393
\ No newline at end of file
...@@ -625,90 +625,6 @@ div.document div.content div.text a:hover{\n ...@@ -625,90 +625,6 @@ div.document div.content div.text a:hover{\n
color: #000000;\n color: #000000;\n
}\n }\n
\n \n
/* Web Toolbar */\n
div.web-toolbar{\n
background-color: #000000;\n
}\n
\n
div.web-toolbar h3{\n
color:#FFFFFF;\n
padding-top: 4px;\n
}\n
\n
div.web-toolbar h3 a{\n
color:#FFFFFF;\n
font-weight: bold;\n
}\n
\n
#wrapper_footer div.web-toolbar ul{\n
padding: 0em;\n
margin: 0em;\n
}\n
\n
#wrapper_footer div.web-toolbar li.toolboxSection:hover, \n
#wrapper_footer div.web-toolbar li.toolboxSection h3:hover {\n
background:#A8A799;\n
}\n
\n
div.web-toolbar div.menu{\n
background:#818364;\n
padding: 0em;\n
border-style: none;\n
}\n
\n
div.web-toolbar div.menu ul li{\n
padding:0;\n
margin:0;\n
float:left;\n
width:100%;\n
}\n
\n
div.web-toolbar div.menu li > a span, div.web-toolbar div.menu button, div.web-toolbar div.menu label{\n
color: #FFFFFF;\n
}\n
\n
div.web-toolbar li > a span {\n
padding: 0.5em;\n
}\n
\n
div.web-toolbar div.menu label{\n
font-weight: bold;\n
margin-top:1em;\n
margin-bottom:1em;\n
margin-left:0.5em;\n
width:100%;\n
}\n
div.web-toolbar div.menu input{\n
margin-left:0.5em;\n
}\n
div.web-toolbar div.menu button,\n
div.web-toolbar div.menu a{\n
color: #FFFFFF!important;\n
background-color: transparent;\n
padding-left: 1em;\n
padding-bottom:0.5em;\n
}\n
\n
div.web-toolbar div.menu li:hover{\n
background-color: #000000;\n
}\n
\n
div.web-toolbar li > a, div.web-toolbar button{\n
border-style: none;\n
}\n
div.web-toolbar div.menu div.field{\n
padding-left: 0.5em;\n
padding-right: 0.5em;\n
}\n
\n
div.web-toolbar div.menu div.field input, div.web-toolbar div.menu div.field select, div.web-toolbar div.menu div.field button{\n
max-width: 90%;\n
}\n
\n
#clone_action_button{\n
width: 80%;\n
}\n
\n
/* Save button styling */\n /* Save button styling */\n
div.actions button {\n div.actions button {\n
float: right;\n float: right;\n
......
1880 1881
\ No newline at end of file \ No newline at end of file
...@@ -36,7 +36,7 @@ def mergePDFList(self, pdf_data_list, start_on_recto=False): ...@@ -36,7 +36,7 @@ def mergePDFList(self, pdf_data_list, start_on_recto=False):
merged pdf in recto/verso mode. merged pdf in recto/verso mode.
""" """
from StringIO import StringIO from StringIO import StringIO
from pyPdf import PdfFileWriter, PdfFileReader from PyPDF2 import PdfFileWriter, PdfFileReader
output = PdfFileWriter() output = PdfFileWriter()
......
4 6
\ No newline at end of file \ No newline at end of file
...@@ -118,7 +118,7 @@ ...@@ -118,7 +118,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>_text</string> </key> <key> <string>_text</string> </key>
<value> <string>python:ERP5Site_getWorkflowStateItemList(portal_type=(\'Task\', \'Task Report\') state_var=\'simulation_state\', display_none_category=False)</string> </value> <value> <string>python:ERP5Site_getWorkflowStateItemList(portal_type=(\'Task\', \'Task Report\'), state_var=\'simulation_state\', display_none_category=False)</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
832 833
\ No newline at end of file \ No newline at end of file
...@@ -227,7 +227,6 @@ ...@@ -227,7 +227,6 @@
</span>\n </span>\n
</h3>\n </h3>\n
<div class="menu">\n <div class="menu">\n
<fieldset style="display:block;">\n
<div class="field">\n <div class="field">\n
<label i18n:translate="" i18n:domain="ui">Title</label>\n <label i18n:translate="" i18n:domain="ui">Title</label>\n
<div class="input">\n <div class="input">\n
...@@ -294,8 +293,6 @@ ...@@ -294,8 +293,6 @@
</button>\n </button>\n
</div>\n </div>\n
</div>\n </div>\n
</fieldset>\n
\n
</div>\n </div>\n
</li>\n </li>\n
\n \n
......
...@@ -63,6 +63,7 @@ div.web-toolbar h3 {\n ...@@ -63,6 +63,7 @@ div.web-toolbar h3 {\n
margin: 0em;\n margin: 0em;\n
cursor:pointer;\n cursor:pointer;\n
display:block;\n display:block;\n
box-sizing:border-box;\n
}\n }\n
div.web-toolbar h3:hover {\n div.web-toolbar h3:hover {\n
background:#ccf;\n background:#ccf;\n
...@@ -126,7 +127,10 @@ div.web-toolbar fieldset { /* Should be the same as "fieldset" rul ...@@ -126,7 +127,10 @@ div.web-toolbar fieldset { /* Should be the same as "fieldset" rul
background: none;\n background: none;\n
border: inherit;\n border: inherit;\n
margin: 0;\n margin: 0;\n
padding: 0;\n
border: 0;\n border: 0;\n
position: fixed;\n
bottom: 0;\n
}\n }\n
div.web-toolbar fieldset > div.field { /* Should be similar to "fieldset > div" rule */\n div.web-toolbar fieldset > div.field { /* Should be similar to "fieldset > div" rule */\n
padding: 0;\n padding: 0;\n
...@@ -218,6 +222,89 @@ div.web-toolbar div.menu ul li a:link{\n ...@@ -218,6 +222,89 @@ div.web-toolbar div.menu ul li a:link{\n
color:auto !important;\n color:auto !important;\n
}\n }\n
\n \n
/* Web Toolbar */\n
div.web-toolbar{\n
background-color: #000000;\n
}\n
\n
div.web-toolbar h3{\n
color:#FFFFFF;\n
padding-top: 4px;\n
}\n
\n
div.web-toolbar h3 a{\n
color:#FFFFFF;\n
font-weight: bold;\n
}\n
\n
#wrapper_footer div.web-toolbar ul{\n
padding: 0em;\n
margin: 0em;\n
}\n
\n
#wrapper_footer div.web-toolbar li.toolboxSection:hover, \n
#wrapper_footer div.web-toolbar li.toolboxSection h3:hover {\n
background:#A8A799;\n
}\n
\n
div.web-toolbar div.menu{\n
background:#818364;\n
padding: 0em;\n
border-style: none;\n
}\n
\n
div.web-toolbar div.menu ul li{\n
padding:0;\n
margin:0;\n
float:left;\n
width:100%;\n
}\n
\n
div.web-toolbar div.menu li > a span, div.web-toolbar div.menu button, div.web-toolbar div.menu label{\n
color: #FFFFFF;\n
}\n
\n
div.web-toolbar li > a span {\n
padding: 0.5em;\n
}\n
\n
div.web-toolbar div.menu label{\n
font-weight: bold;\n
margin-top:1em;\n
margin-bottom:1em;\n
margin-left:0.5em;\n
width:100%;\n
}\n
div.web-toolbar div.menu input{\n
margin-left:0.5em;\n
}\n
div.web-toolbar div.menu button,\n
div.web-toolbar div.menu a{\n
color: #FFFFFF!important;\n
background-color: transparent;\n
padding-left: 1em;\n
padding-bottom:0.5em;\n
}\n
\n
div.web-toolbar div.menu li:hover{\n
background-color: #000000;\n
}\n
\n
div.web-toolbar li > a, div.web-toolbar button{\n
border-style: none;\n
}\n
div.web-toolbar div.menu div.field{\n
padding-left: 0.5em;\n
padding-right: 0.5em;\n
}\n
\n
div.web-toolbar div.menu div.field input, div.web-toolbar div.menu div.field select, div.web-toolbar div.menu div.field button{\n
max-width: 90%;\n
}\n
\n
#clone_action_button{\n
width: 80%;\n
}\n
</tal:block> </tal:block>
]]></unicode> </value> ]]></unicode> </value>
......
1108 1109
\ No newline at end of file \ No newline at end of file
...@@ -86,6 +86,7 @@ import posixpath ...@@ -86,6 +86,7 @@ import posixpath
import transaction import transaction
import threading import threading
from ZODB.broken import Broken
CACHE_DATABASE_PATH = None CACHE_DATABASE_PATH = None
try: try:
...@@ -931,6 +932,70 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -931,6 +932,70 @@ class ObjectTemplateItem(BaseTemplateItem):
keys.sort() keys.sort()
return keys return keys
def unindexBrokenObject(self, item_path):
"""
Unindex broken objects.
Corresponding catalog record is not unindexed even after a broken object
is removed, since the broken object does not implement 'CopySupport'.
This situation triggers a FATAL problem on SQLCatalog.catalogObjectList
when upgrading a broken path by ObjectTemplateItem with BusinessTemplate.
We often get this problem when we are upgrading a quite old ERP5 site
to new one, as several old classes may be already removed/replaced
in the file system, thus several objects tend to be broken.
Keyword arguments:
item_path -- the path specified by the ObjectTemplateItem
"""
def flushActivity(obj, invoke=0, **kw):
try:
activity_tool = self.getPortalObject().portal_activities
except AttributeError:
return # Do nothing if no portal_activities
# flush all activities related to this object
activity_tool.flush(obj, invoke=invoke, **kw)
class fakeobject:
def __init__(self, path):
self._physical_path = tuple(path.split('/'))
def getPhysicalPath(self):
return self._physical_path
def recursiveUnindex(catalog, item_path, root_document_path):
# search the object + sub-objects
result = catalog(relative_url=(item_path,
item_path.replace('_', r'\_') + '/%'))
for x in result:
uid = x.uid
path = x.path
unindex(root_document_path, path, uid)
def unindex(root_document_path, path, uid):
LOG('Products.ERP5.Document.BusinessTemplate', WARNING,
'Unindex Broken object at %r.' % (path,))
# Make sure there is not activity for this object
flushActivity(fakeobject(path))
# Set the path as deleted without lock
catalog.beforeUnindexObject(None,path=path,uid=uid)
# Then start activity in order to remove lines in catalog,
# sql wich generate locks
catalog.activate(activity='SQLQueue',
tag='%s' % uid,
group_method_id='portal_catalog/uncatalogObjectList',
serialization_tag=root_document_path
).unindexObject(uid=uid)
portal = self.getPortalObject()
try:
catalog = portal.portal_catalog
except AttributeError:
pass
else:
# given item_path is a relative_url in reality
root_path = "/".join(item_path.split('/')[:2])
root_document_path = '/%s/%s' % (portal.getId(), root_path)
recursiveUnindex(catalog, item_path, root_document_path)
def install(self, context, trashbin, **kw): def install(self, context, trashbin, **kw):
self.beforeInstall() self.beforeInstall()
update_dict = kw.get('object_to_update') update_dict = kw.get('object_to_update')
...@@ -1029,6 +1094,12 @@ class ObjectTemplateItem(BaseTemplateItem): ...@@ -1029,6 +1094,12 @@ class ObjectTemplateItem(BaseTemplateItem):
portal_type_dict['workflow_chain'] = \ portal_type_dict['workflow_chain'] = \
getChainByType(context)[1].get('chain_' + object_id, '') getChainByType(context)[1].get('chain_' + object_id, '')
container.manage_delObjects([object_id]) container.manage_delObjects([object_id])
# unindex here when it is a broken object
if isinstance(old_obj, Broken):
new_obj = self._objects[path]
# check isIndexable with new one, because the old one is broken
if new_obj.isIndexable():
self.unindexBrokenObject(path)
# install object # install object
obj = self._objects[path] obj = self._objects[path]
......
...@@ -33,8 +33,7 @@ from AccessControl import ClassSecurityInfo ...@@ -33,8 +33,7 @@ from AccessControl import ClassSecurityInfo
from Products.ERP5Type import Permissions, PropertySheet, interfaces from Products.ERP5Type import Permissions, PropertySheet, interfaces
from Products.ERP5.Document.Image import Image from Products.ERP5.Document.Image import Image
from Products.ERP5.Document.Document import ConversionError,\ from Products.ERP5.Document.Document import ConversionError
VALID_TEXT_FORMAT_LIST
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
from zLOG import LOG, INFO, PROBLEM from zLOG import LOG, INFO, PROBLEM
import errno import errno
...@@ -82,33 +81,37 @@ class PDFDocument(Image): ...@@ -82,33 +81,37 @@ class PDFDocument(Image):
* Watermark is applied at all pages starting watermark_start_page (this * Watermark is applied at all pages starting watermark_start_page (this
index is 0 based) index is 0 based)
""" """
from pyPdf import PdfFileWriter, PdfFileReader, pdf try:
if not watermark_data: from PyPDF2 import PdfFileWriter, PdfFileReader
raise ValueError("watermark_data cannot not be empty") except ImportError:
if not self.hasData(): pass
raise ValueError("Cannot watermark an empty document") else:
self_reader = PdfFileReader(StringIO(self.getData())) if not watermark_data:
watermark_reader = PdfFileReader(StringIO(watermark_data)) raise ValueError("watermark_data cannot not be empty")
watermark_page_count = watermark_reader.getNumPages() if not self.hasData():
raise ValueError("Cannot watermark an empty document")
self_reader = PdfFileReader(StringIO(self.getData()))
watermark_reader = PdfFileReader(StringIO(watermark_data))
watermark_page_count = watermark_reader.getNumPages()
output = PdfFileWriter() output = PdfFileWriter()
for page_number in range(self_reader.getNumPages()): for page_number in range(self_reader.getNumPages()):
self_page = self_reader.getPage(page_number) self_page = self_reader.getPage(page_number)
watermark_page = None watermark_page = None
if page_number >= watermark_start_page: if page_number >= watermark_start_page:
if repeat_watermark: if repeat_watermark:
watermark_page = watermark_reader.getPage( watermark_page = watermark_reader.getPage(
(page_number - watermark_start_page) % watermark_page_count) (page_number - watermark_start_page) % watermark_page_count)
elif page_number < (watermark_page_count + watermark_start_page): elif page_number < (watermark_page_count + watermark_start_page):
watermark_page = watermark_reader.getPage(page_number - watermark_start_page) watermark_page = watermark_reader.getPage(page_number - watermark_start_page)
if watermark_page is not None: if watermark_page is not None:
self_page.mergePage(watermark_page) self_page.mergePage(watermark_page)
output.addPage(self_page) output.addPage(self_page)
outputStream = StringIO() outputStream = StringIO()
output.write(outputStream) output.write(outputStream)
return outputStream.getvalue() return outputStream.getvalue()
# Conversion API # Conversion API
def _convert(self, format, **kw): def _convert(self, format, **kw):
...@@ -177,8 +180,8 @@ class PDFDocument(Image): ...@@ -177,8 +180,8 @@ class PDFDocument(Image):
else: else:
# Try to use OCR # Try to use OCR
# As high dpi images are required, it may take some times to convert the # As high dpi images are required, it may take some times to convert the
# pdf. # pdf.
# It may be required to use activities to fill the cache and at the end, # It may be required to use activities to fill the cache and at the end,
# to calculate the final result # to calculate the final result
text = '' text = ''
content_information = self.getContentInformation() content_information = self.getContentInformation()
...@@ -302,12 +305,12 @@ class PDFDocument(Image): ...@@ -302,12 +305,12 @@ class PDFDocument(Image):
value = ':'.join(item_list[1:]).strip() value = ':'.join(item_list[1:]).strip()
result[key] = value result[key] = value
# Then we use pyPdf to get extra metadata # Then we use PyPDF2 to get extra metadata
try: try:
from pyPdf import PdfFileReader from PyPDF2 import PdfFileReader
from pyPdf.utils import PdfReadError from PyPDF2.utils import PdfReadError
except ImportError: except ImportError:
# if pyPdf not found, pass # if PyPDF2 not found, pass
pass pass
else: else:
try: try:
...@@ -320,7 +323,7 @@ class PDFDocument(Image): ...@@ -320,7 +323,7 @@ class PDFDocument(Image):
# Ignore values that cannot be pickled ( such as AAPL:Keywords ) # Ignore values that cannot be pickled ( such as AAPL:Keywords )
try: try:
pickle.dumps(info_value) pickle.dumps(info_value)
except pickle.PicklingError, err: except pickle.PicklingError:
LOG("PDFDocument.getContentInformation", INFO, LOG("PDFDocument.getContentInformation", INFO,
"Ignoring non picklable document info on %s: %s (%r)" % ( "Ignoring non picklable document info on %s: %s (%r)" % (
self.getRelativeUrl(), info_key, info_value)) self.getRelativeUrl(), info_key, info_value))
...@@ -328,7 +331,7 @@ class PDFDocument(Image): ...@@ -328,7 +331,7 @@ class PDFDocument(Image):
result.setdefault(info_key, info_value) result.setdefault(info_key, info_value)
except PdfReadError: except PdfReadError:
LOG("PDFDocument.getContentInformation", PROBLEM, LOG("PDFDocument.getContentInformation", PROBLEM,
"pyPdf is Unable to read PDF, probably corrupted PDF here : %s" % \ "PyPDF2 is Unable to read PDF, probably corrupted PDF here : %s" % \
(self.getRelativeUrl(),)) (self.getRelativeUrl(),))
finally: finally:
tmp.close() tmp.close()
......
...@@ -102,8 +102,6 @@ def initialize( context ): ...@@ -102,8 +102,6 @@ def initialize( context ):
# Allow some usefull classes and fonctions in TTW code # Allow some usefull classes and fonctions in TTW code
ModuleSecurityInfo('ZODB.POSException').declarePublic('ConflictError') ModuleSecurityInfo('ZODB.POSException').declarePublic('ConflictError')
ModuleSecurityInfo('zExceptions').declarePublic('BadRequest', 'NotFound',
'Redirect', 'Unauthorized')
ModuleSecurityInfo('Products.CMFCore.WorkflowCore').declarePublic( ModuleSecurityInfo('Products.CMFCore.WorkflowCore').declarePublic(
'WorkflowException') 'WorkflowException')
ModuleSecurityInfo('Products.ERP5.Document.Image').declarePublic( ModuleSecurityInfo('Products.ERP5.Document.Image').declarePublic(
......
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Category" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_append_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_base_category</string> </key>
<value>
<tuple>
<string>order</string>
<string>parent</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_copy_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_mask_value</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>acquisition_object_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>acquisition_portal_type</string> </key>
<value> <string>python: list( portal.getPortalAcquisitionMovementTypeList() + portal.getPortalItemTypeList() + portal.getPortalDeliveryTypeList() + portal.getPortalOrderTypeList() + portal.getPortalInvoiceTypeList() + portal.getPortalOpenOrderTypeList())</string> </value>
</item>
<item>
<key> <string>acquisition_sync_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination_decision_administration</string>
<string>destination_carrier_administration</string>
</tuple>
</value>
</item>
<item>
<key> <string>category_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>criterion_property</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>An entity who handles shipment and do paperwork for shipment.</string> </value>
</item>
<item>
<key> <string>fallback_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>destination_carrier_administration</string> </value>
</item>
<item>
<key> <string>id_generator</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id_group</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>membership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>multimembership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Base Category</string> </value>
</item>
<item>
<key> <string>read_permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>rid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Destination Carrier Administration</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Category" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_append_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_base_category</string> </key>
<value>
<tuple>
<string>order</string>
<string>parent</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_copy_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_mask_value</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>acquisition_object_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>acquisition_portal_type</string> </key>
<value> <string>python: list( portal.getPortalAcquisitionMovementTypeList() + portal.getPortalItemTypeList() + portal.getPortalDeliveryTypeList() + portal.getPortalOrderTypeList() + portal.getPortalInvoiceTypeList() + portal.getPortalOpenOrderTypeList())</string> </value>
</item>
<item>
<key> <string>acquisition_sync_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination_decision_administration</string>
</tuple>
</value>
</item>
<item>
<key> <string>category_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>criterion_property</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>An entity who receives order and do paperwork for order.</string> </value>
</item>
<item>
<key> <string>fallback_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>destination_decision_administration</string> </value>
</item>
<item>
<key> <string>id_generator</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id_group</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>membership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>multimembership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Base Category</string> </value>
</item>
<item>
<key> <string>read_permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>rid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Destination Decision Administration</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Category" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_append_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_base_category</string> </key>
<value>
<tuple>
<string>order</string>
<string>parent</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_copy_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_mask_value</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>acquisition_object_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>acquisition_portal_type</string> </key>
<value> <string>python: list( portal.getPortalAcquisitionMovementTypeList() + portal.getPortalItemTypeList() + portal.getPortalDeliveryTypeList() + portal.getPortalOrderTypeList() + portal.getPortalInvoiceTypeList() + portal.getPortalOpenOrderTypeList())</string> </value>
</item>
<item>
<key> <string>acquisition_sync_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination_decision_administration</string>
<string>destination_carrier_administration</string>
<string>destination_section_administration</string>
</tuple>
</value>
</item>
<item>
<key> <string>category_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>criterion_property</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>An entity who do paperwork for invoice.</string> </value>
</item>
<item>
<key> <string>fallback_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>destination_section_administration</string> </value>
</item>
<item>
<key> <string>id_generator</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id_group</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>membership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>multimembership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Base Category</string> </value>
</item>
<item>
<key> <string>read_permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>rid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Destination Section Administration</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Category" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_append_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_base_category</string> </key>
<value>
<tuple>
<string>order</string>
<string>parent</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_copy_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_mask_value</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>acquisition_object_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>acquisition_portal_type</string> </key>
<value> <string>python: list( portal.getPortalAcquisitionMovementTypeList() + portal.getPortalItemTypeList() + portal.getPortalDeliveryTypeList() + portal.getPortalOrderTypeList() + portal.getPortalInvoiceTypeList() + portal.getPortalOpenOrderTypeList())</string> </value>
</item>
<item>
<key> <string>acquisition_sync_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination_decision_administration</string>
<string>destination_carrier_administration</string>
<string>source_carrier_administration</string>
</tuple>
</value>
</item>
<item>
<key> <string>category_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>criterion_property</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>An entity who handles shipment and do paperwork for shipment.</string> </value>
</item>
<item>
<key> <string>fallback_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>source_carrier_administration</string> </value>
</item>
<item>
<key> <string>id_generator</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id_group</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>membership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>multimembership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Base Category</string> </value>
</item>
<item>
<key> <string>read_permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>rid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Source Carrier Administration</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Category" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_append_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_base_category</string> </key>
<value>
<tuple>
<string>order</string>
<string>parent</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_copy_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_mask_value</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>acquisition_object_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>acquisition_portal_type</string> </key>
<value> <string>python: list( portal.getPortalAcquisitionMovementTypeList() + portal.getPortalItemTypeList() + portal.getPortalDeliveryTypeList() + portal.getPortalOrderTypeList() + portal.getPortalInvoiceTypeList() + portal.getPortalOpenOrderTypeList())</string> </value>
</item>
<item>
<key> <string>acquisition_sync_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination_decision_administration</string>
<string>source_decision_administration</string>
<string>source_decision_administration</string>
</tuple>
</value>
</item>
<item>
<key> <string>category_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>criterion_property</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>An entity who receives order and do paperwork for order.</string> </value>
</item>
<item>
<key> <string>fallback_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>source_decision_administration</string> </value>
</item>
<item>
<key> <string>id_generator</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id_group</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>membership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>multimembership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Base Category</string> </value>
</item>
<item>
<key> <string>read_permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>rid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Source Decision Administration</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Base Category" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>_Add_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Add_portal_folders_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Copy_or_Move_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Delete_objects_Permission</string> </key>
<value>
<tuple>
<string>Assignor</string>
<string>Manager</string>
</tuple>
</value>
</item>
<item>
<key> <string>_Modify_portal_content_Permission</string> </key>
<value>
<tuple>
<string>Assignee</string>
<string>Assignor</string>
<string>Manager</string>
<string>Owner</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_append_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_base_category</string> </key>
<value>
<tuple>
<string>order</string>
<string>parent</string>
</tuple>
</value>
</item>
<item>
<key> <string>acquisition_copy_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>acquisition_mask_value</string> </key>
<value> <int>1</int> </value>
</item>
<item>
<key> <string>acquisition_object_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>acquisition_portal_type</string> </key>
<value> <string>python: list( portal.getPortalAcquisitionMovementTypeList() + portal.getPortalItemTypeList() + portal.getPortalDeliveryTypeList() + portal.getPortalOrderTypeList() + portal.getPortalInvoiceTypeList() + portal.getPortalOpenOrderTypeList())</string> </value>
</item>
<item>
<key> <string>acquisition_sync_value</string> </key>
<value> <int>0</int> </value>
</item>
<item>
<key> <string>categories</string> </key>
<value>
<tuple>
<string>destination_decision_administration</string>
<string>destination_carrier_administration</string>
<string>destination_section_administration</string>
<string>source_section_administration</string>
</tuple>
</value>
</item>
<item>
<key> <string>category_type</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>criterion_property</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>description</string> </key>
<value> <string>An entity who do paperwork for invoice.</string> </value>
</item>
<item>
<key> <string>fallback_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>source_section_administration</string> </value>
</item>
<item>
<key> <string>id_generator</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>id_group</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>membership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>membership_criterion_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>multimembership_criterion_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Base Category</string> </value>
</item>
<item>
<key> <string>read_permission</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>rid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>short_title</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>sid</string> </key>
<value>
<none/>
</value>
</item>
<item>
<key> <string>test_method_id</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Source Section Administration</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value>
<none/>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
...@@ -52,6 +52,7 @@ ...@@ -52,6 +52,7 @@
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>from Products.PythonScripts.standard import Object\n <value> <string>from Products.PythonScripts.standard import Object\n
from ZODB.POSException import ConflictError\n from ZODB.POSException import ConflictError\n
from zExceptions import Unauthorized\n
Base_translateString = context.Base_translateString\n Base_translateString = context.Base_translateString\n
\n \n
serial = context.REQUEST[\'serial\']\n serial = context.REQUEST[\'serial\']\n
...@@ -59,9 +60,9 @@ next_serial = context.REQUEST[\'next_serial\']\n ...@@ -59,9 +60,9 @@ next_serial = context.REQUEST[\'next_serial\']\n
\n \n
try:\n try:\n
context.HistoricalRevisions[serial]\n context.HistoricalRevisions[serial]\n
except ConflictError:\n except (ConflictError, Unauthorized):\n
raise\n raise\n
except: # POSKeyError\n except Exception: # POSKeyError\n
return [Object(property_name=Base_translateString(\'Historical revisions are\'\n return [Object(property_name=Base_translateString(\'Historical revisions are\'\n
\' not available, maybe the database has been packed\'))]\n \' not available, maybe the database has been packed\'))]\n
\n \n
......
2013-10-17 tatuya
* Add {source,destination}_{decision,carrier,section}_administration categories.
2013-09-08 arnaud.fontaine 2013-09-08 arnaud.fontaine
* ZODB Components: Revert 'Allow to execute runUnitTest for bt5 Test Components' to fix tests bootstrap. * ZODB Components: Revert 'Allow to execute runUnitTest for bt5 Test Components' to fix tests bootstrap.
......
41128 41130
\ No newline at end of file \ No newline at end of file
...@@ -8,7 +8,9 @@ delivery ...@@ -8,7 +8,9 @@ delivery
destination destination
destination_account destination_account
destination_administration destination_administration
destination_carrier_administration
destination_decision destination_decision
destination_decision_administration
destination_function destination_function
destination_funding destination_funding
destination_payment destination_payment
...@@ -16,6 +18,7 @@ destination_payment_region ...@@ -16,6 +18,7 @@ destination_payment_region
destination_payment_request destination_payment_request
destination_project destination_project
destination_section destination_section
destination_section_administration
destination_trade destination_trade
elementary_type elementary_type
local_role_group local_role_group
...@@ -30,7 +33,9 @@ size ...@@ -30,7 +33,9 @@ size
source source
source_account source_account
source_administration source_administration
source_carrier_administration
source_decision source_decision
source_decision_administration
source_function source_function
source_funding source_funding
source_payment source_payment
...@@ -38,5 +43,6 @@ source_payment_region ...@@ -38,5 +43,6 @@ source_payment_region
source_payment_request source_payment_request
source_project source_project
source_section source_section
source_section_administration
source_trade source_trade
specialise specialise
\ No newline at end of file
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>destination_carrier_administration_category</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>destination_decision_administration_category</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>destination_section_administration_category</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>source_carrier_administration_category</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>source_decision_administration_category</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>source_section_administration_category</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
<?xml version="1.0"?>
<ZopeData>
<record id="1" aka="AAAAAAAAAAE=">
<pickle>
<global name="Category Property" module="erp5.portal_type"/>
</pickle>
<pickle>
<dictionary>
<item>
<key> <string>id</string> </key>
<value> <string>journal_category</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
2013-10-17 tatuya
* Arrow: Add {source,destination}_{decision,carrier,section}_administration categories
2013-09-08 arnaud.fontaine 2013-09-08 arnaud.fontaine
* ZODB Components: Revert 'Allow to execute runUnitTest for bt5 Test Components' to fix tests bootstrap. * ZODB Components: Revert 'Allow to execute runUnitTest for bt5 Test Components' to fix tests bootstrap.
......
65 67
\ No newline at end of file \ No newline at end of file
...@@ -192,8 +192,11 @@ def getModuleActionInformationDict(**kw):\n ...@@ -192,8 +192,11 @@ def getModuleActionInformationDict(**kw):\n
getModuleActionInformationDict = CachingMethod(getModuleActionInformationDict,\n getModuleActionInformationDict = CachingMethod(getModuleActionInformationDict,\n
id=\'ERP5Site_getModuleActionInformationDict\',\n id=\'ERP5Site_getModuleActionInformationDict\',\n
cache_factory=\'erp5_ui_long\')\n cache_factory=\'erp5_ui_long\')\n
\n
# those parameters are only used for the caching key\n
return getModuleActionInformationDict(\n return getModuleActionInformationDict(\n
user = context.portal_membership.getAuthenticatedMember().getId(), \\\n user = context.portal_membership.getAuthenticatedMember().getId(),\n
server_url = context.REQUEST.SERVER_URL,\n
language = context.Localizer.get_selected_language())\n language = context.Localizer.get_selected_language())\n
</string> </value> </string> </value>
</item> </item>
......
1110 1111
\ No newline at end of file \ No newline at end of file
##############################################################################
#
# Copyright (c) 2013 Nexedi KK and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import unittest
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
class TestAccessTab(ERP5TypeTestCase):
def getTitle(self):
return "Access Tab Test"
def getBusinessTemplateList(self):
""" return business template list """
return ('erp5_base',)
def afterSetUp(self):
""" AfterSetup """
self.addPreferenceForAccessTab()
self.configureBusinessApplication()
self.tic()
def addPreferenceForAccessTab(self):
""" Add a preference for access tab """
preference_tool = self.portal.portal_preferences
preference = getattr(preference_tool, "access_tab_test_preference", None)
if preference is None:
preference = preference_tool.newContent(id="access_tab_test_preference",
portal_type="Preference")
preference.setPreferredHtmlStyleAccessTab(True)
if preference.getPreferenceState() != "enabled":
preference.enable()
def configureBusinessApplication(self):
""" Configure business_application category on module property.
This is mandatory for access_tab."""
business_application = self.portal.portal_categories.business_application
base = getattr(business_application, 'base', None)
if base is None:
base = self.portal.portal_categories.business_application.newContent(
portal_type='Category',
id='base',
title='base')
self.portal.organisation_module.setBusinessApplicationValue(base)
self.portal.person_module.setBusinessApplicationValue(base)
self.tic()
def enableAccessTab(self):
""" make enable access tab """
portal = self.portal
preference = portal.portal_preferences.access_tab_test_preference
preference.setPreferredHtmlStyleAccessTab(True)
self.tic()
def checkSelectedTabDict(self):
""" Check a script which is used in access tab view """
tab_info = self.portal.ERP5Site_getSelectedTab()
expected_tab_info = {'title': 'Browse',
'renderer': 'ERP5Site_renderViewActionList',
'id': 'browse_tab',
'icon': 'tab_icon/list.png'}
self.assertEquals(tab_info, expected_tab_info)
def checkStatusDict(self):
""" Check a script which is used in access tab view """
status_dict = self.portal.ERP5Site_getConfiguredStatusDict()
expected_status_dict = {'express_mode': 'support_disabled',
'dms_mode': False,
'basic_mode': True}
self.assertEquals(status_dict, expected_status_dict)
def checkInformationDictBasic(self):
""" Check a script which is used in the main part in access tab view """
portal = self.portal
info_dict = portal.ERP5Site_getCategorizedModuleActionInformationDict()
view_list = info_dict['view']
self.assertEquals(len(view_list), 1)
self.assertEquals(len(view_list[0]), 2)
base = view_list[0]
(label, menu_list) = base
self.assertEquals(label, 'base')
self.assertEquals(len(menu_list), 2)
organisation_menu = menu_list[0]
person_menu = menu_list[1]
self.assertEquals(len(organisation_menu), 2)
self.assertEquals(type(organisation_menu), tuple)
self.assertEquals(len(person_menu), 2)
self.assertEquals(type(person_menu), tuple)
(organisation_label, organisation_url) = organisation_menu
(person_label, person_url) = person_menu
self.assertEquals(organisation_label, 'Organisations')
self.assertEquals(person_label, 'Persons')
def addCurrencyModuleIntoAccessTab(self):
""" add currency module into access tab page so that we can
recognise existing cache is not used """
base = self.portal.portal_categories.business_application.base
self.portal.currency_module.setBusinessApplicationValue(base)
self.tic()
def checkInformationDictAfterSwitchingServerUrl(self):
""" Check a script which is used in the main part in access tab view """
# simulate a https access with '127.0.0.1' address
request=self.portal.REQUEST
request.setServerURL(protocol='https', hostname='127.0.0.1')
portal = self.getPortal()
# make sure that existing cache is not used because the server_url is
# different when the view is cached.
info_dict = portal.ERP5Site_getCategorizedModuleActionInformationDict()
view_list = info_dict['view']
self.assertEquals(len(view_list), 1)
self.assertEquals(len(view_list[0]), 2)
base = view_list[0]
(label, menu_list) = base
self.assertEquals(len(menu_list), 3)
currency_menu = menu_list[0]
self.assertEquals(len(currency_menu), 2)
self.assertEquals(type(currency_menu), tuple)
(currency_label, currency_url) = currency_menu
self.assertEquals(currency_label, 'Currencies')
self.assertTrue('https' in currency_url[0][1])
def test_01_testAccessTab(self):
"""
Test the basic functionalities of Access Tab.
[setup]
- enable accesstab flag on a preference
- configure 'business_application' category at module property
[test]
- check access tab is usable
"""
self.enableAccessTab()
self.checkSelectedTabDict()
self.checkStatusDict()
self.checkInformationDictBasic()
def test_02_testAccessTabCacheAfterSwitchingUrl(self):
"""
Check that when access url is changed, exisiting access tab cache is
not used.
The view is cached with CachingMethod by (user, language and server_url)
"""
self.enableAccessTab()
self.checkInformationDictBasic()
self.addCurrencyModuleIntoAccessTab()
self.checkInformationDictAfterSwitchingServerUrl()
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestAccessTab))
return suite
##############################################################################
#
# Copyright (c) 2013 Nexedi KK and Contributors. All Rights Reserved.
#
# WARNING: This program as such is intended to be used by professional
# programmers who take the whole responsability of assessing all potential
# consequences resulting from its eventual inadequacies and bugs
# End users who are looking for a ready-to-use solution with commercial
# garantees and support are strongly adviced to contract a Free Software
# Service Company
#
# This program is Free Software; you can redistribute it and/or
# modify it under the terms of the GNU General Public License
# as published by the Free Software Foundation; either version 2
# of the License, or (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
##############################################################################
import unittest
from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
class TestArrow(ERP5TypeTestCase):
def getTitle(self):
return "Arrow property Sheet Test"
def getBusinessTemplateList(self):
""" return business template list """
return ('erp5_base',)
def test_01_testGetterSetter(self):
"""
Test the getter/setter of Arrow properties.
"""
person_module = self.portal.person_module
person = person_module.newContent(portal_type='Person')
career = person.newContent(portal_type='Career')
person_sda = person_module.newContent(portal_type='Person', id='sda')
person_dda = person_module.newContent(portal_type='Person', id='dda')
person_sca = person_module.newContent(portal_type='Person', id='sca')
person_dca = person_module.newContent(portal_type='Person', id='dca')
person_ssa = person_module.newContent(portal_type='Person', id='ssa')
person_dsa = person_module.newContent(portal_type='Person', id='dsa')
# Career portal type provides Arrow properties
# so here we use Career testing Arrow
career.setSourceDecisionAdministrationValue(person_sda)
career.setDestinationDecisionAdministrationValue(person_dda)
career.setSourceCarrierAdministrationValue(person_sca)
career.setDestinationCarrierAdministrationValue(person_dca)
career.setSourceSectionAdministrationValue(person_ssa)
career.setDestinationSectionAdministrationValue(person_dsa)
self.assertEqual(career.getSourceDecisionAdministrationValue(), person_sda)
self.assertEqual(career.getDestinationDecisionAdministrationValue(),
person_dda)
self.assertEqual(career.getSourceCarrierAdministrationValue(), person_sca)
self.assertEqual(career.getDestinationCarrierAdministrationValue(),
person_dca)
self.assertEqual(career.getSourceSectionAdministrationValue(), person_ssa)
self.assertEqual(career.getDestinationSectionAdministrationValue(),
person_dsa)
# set the parent document to the property
# make sure it is not confusing because of acquisition
career.setSourceDecisionAdministrationValue(person)
self.assertEqual(career.getSourceDecisionAdministrationValue(), person)
def test_suite():
suite = unittest.TestSuite()
suite.addTest(unittest.makeSuite(TestArrow))
return suite
...@@ -49,6 +49,7 @@ import random ...@@ -49,6 +49,7 @@ import random
import string import string
import tempfile import tempfile
import glob import glob
import sys
WORKFLOW_TYPE = 'erp5_workflow' WORKFLOW_TYPE = 'erp5_workflow'
...@@ -57,6 +58,14 @@ from Products.PortalTransforms.Transform import Transform ...@@ -57,6 +58,14 @@ from Products.PortalTransforms.Transform import Transform
Transform_tr_init = Transform._tr_init Transform_tr_init = Transform._tr_init
Transform_manage_beforeDelete = Transform.manage_beforeDelete Transform_manage_beforeDelete = Transform.manage_beforeDelete
from Products.ERP5.Document.Organisation import Organisation
from Products.ERP5Type.Accessor.Constant import PropertyGetter as ConstantGetter
from ZODB.broken import Broken
class MockBrokenOrganisation(Organisation, Broken):
meta_type = 'ERP5 Mock Broken Organisation'
portal_type = 'Mock Broken Organisation'
class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor): class BusinessTemplateMixin(ERP5TypeTestCase, LogInterceptor):
def getBusinessTemplateList(self): def getBusinessTemplateList(self):
return ('erp5_base', return ('erp5_base',
...@@ -6907,6 +6916,182 @@ class TestBusinessTemplate(BusinessTemplateMixin): ...@@ -6907,6 +6916,182 @@ class TestBusinessTemplate(BusinessTemplateMixin):
sequence_list.addSequenceString(sequence_string) sequence_list.addSequenceString(sequence_string)
sequence_list.play(self) sequence_list.play(self)
def stepCreateOrganisation(self, sequence=None, **kw):
"""
Organisation
"""
organisation_module = self.portal.organisation_module
id_list = []
for i in range(self.organisation_amount):
organisation = organisation_module.newContent(
portal_type = 'Organisation')
self.failUnless(organisation is not None)
organisation.setTitle('organisation %d' % (i + 1))
for j in range(self.email_amount):
organisation.newContent(id='email%d' % (j+1),
title='my email%d' % (j+1),
portal_type='Email')
id_list.append(organisation.getId())
self.assertNotEquals(id_list, [])
sequence.edit(organisation_id_list=id_list)
def stepModifyOrganisation(self, sequence=None, **kw):
""" Modify Organisation """
organisation_id_list = sequence.get('organisation_id_list', [])
self.assertNotEquals(organisation_id_list, [])
for organisation_id in organisation_id_list:
organisation_module = self.portal.organisation_module
organisation = organisation_module[organisation_id]
organisation.setTitle('[modified] ' + organisation.getTitle())
for j in range(self.email_amount):
email = organisation['email%d' % (j+1)]
email.setTitle('[modified] ' + email.getTitle())
def stepRewriteWithBrokenOrganisation(self, sequence=None, **kw):
"""
Rewrite the organisation with a broken object.
[Note]: In fact, it is a *mock* broken object. It behave like a broken
object but it's not broken. To use *real* broken object is better.
However it is rather difficult to create a real broken
object in ZODB without restart Zope. Even if removing
sys.modules['Products.ERP5.Document'].MockBrokenOrganisation, and
retrieve it with a new connection, it does not become a broken object.
Probablly there is remaing the object-cache somewhere in Zope.
"""
setattr(sys.modules['Products.ERP5.Document'],
'MockBrokenOrganisation', MockBrokenOrganisation)
from Products.ERP5Type.Utils import registerDocumentClass
registerDocumentClass('Products.ERP5.Document',
'MockBrokenOrganisation')
self.commit()
pt = self.getTypeTool()
# create module object portal type
pt.newContent('Mock Broken Organisation', 'Base Type',
type_class='MockBrokenOrganisation')
pt['Organisation Module'].edit(
type_allowed_content_type_list=('Organisation',
'Mock Broken Organisation',))
self.commit()
self.portal.organisation_module.manage_delObjects(['1'])
broken = self.portal.organisation_module.newContent(
portal_type='Mock Broken Organisation', id='1')
self.commit()
self.tic() # triger undex/index the document
# set unindexable so that it will act as Broken object
self.portal.organisation_module['1'].isIndexable = \
ConstantGetter('isIndexable', value=False)
self.commit()
# to reproduce this problem we need to clear portal_caches
self.portal.portal_caches.clearAllCache()
def stepCheckOrganisationModified(self, sequence=None, **kw):
organisation_id_list = sequence.get('organisation_id_list', [])
self.assertNotEquals(organisation_id_list, [])
for organisation_id in organisation_id_list:
organisation_module = self.portal.organisation_module
organisation = organisation_module[organisation_id]
self.assertTrue(organisation.getTitle().startswith('[modified]'))
for j in range(self.email_amount):
email = organisation['email%d' % (j+1)]
self.assertTrue(email.getTitle().startswith('[modified]'))
def stepAddOrganisationToBusinessTemplate(self, sequence=None, **kw):
bt = sequence.get('current_bt', None)
self.failUnless(bt is not None)
if bt.getTemplatePathList():
path_list = bt.getTemplatePathList()[:]
path_list = path_list + ('organisation_module/**',)
bt.edit(template_path_list=path_list)
else:
bt.edit(template_path_list=['organisation_module/**'])
def stepRevertOrganisation(self, sequence=None, **kw):
organisation_id_list = sequence.get('organisation_id_list', [])
self.assertNotEquals(organisation_id_list, [])
for organisation_id in organisation_id_list:
organisation_module = self.portal.organisation_module
organisation = organisation_module[organisation_id]
organisation.setTitle(organisation.getTitle().replace('[modified] ', ''))
for j in range(self.email_amount):
email = organisation['email%d' % (j+1)]
email.setTitle(email.getTitle().replace('[modified] ', ''))
def stepRemoveOrganisation(self, sequence=None, **kw):
id_list = sequence.get('organisation_id_list', None)
self.assertNotEquals(id_list, [])
organisation_id_list = id_list[:]
organisation_module = self.portal.organisation_module
organisation_module.manage_delObjects(organisation_id_list)
self.assertNotEquals(id_list, [])
def stepCheckOrganisationRestored(self, sequence=None, **kw):
organisation_id_list = sequence.get('organisation_id_list', [])
self.assertNotEquals(organisation_id_list, [])
for organisation_id in organisation_id_list:
organisation_module = self.portal.organisation_module
organisation = organisation_module[organisation_id]
self.assertTrue(organisation.getTitle().startswith('organisation'))
for j in range(self.email_amount):
email = organisation['email%d' % (j+1)]
self.assertTrue(email.getTitle().startswith('my email'))
def test_UpgradeBrokenObject(self):
"""
Test a case that there is an broken object and upgrade the path.
[Test summary]
1. create organisation_module/1
2. set organisation_module/1 as a broken object (in fact it's a mock)
3. upgrade organisation_module/1 by the PathTemplateItem
"""
self.portal.portal_activities.manage_enableActivityTracking()
self.organisation_amount = 2
self.email_amount = 2
sequence_list = SequenceList()
sequence_string = """
CreateOrganisation
CreateNewBusinessTemplate
UseExportBusinessTemplate
AddOrganisationToBusinessTemplate
Tic
BuildBusinessTemplate
SaveBusinessTemplate
Tic
RemoveOrganisation
RemoveBusinessTemplate
RemoveAllTrashBins
Tic
ImportBusinessTemplate
UseImportBusinessTemplate
InstallBusinessTemplate
Tic
CheckOrganisationRestored
ModifyOrganisation
CreateNewBusinessTemplate
UseExportBusinessTemplate
AddOrganisationToBusinessTemplate
BuildBusinessTemplate
SaveBusinessTemplate
RevertOrganisation
Tic
CheckOrganisationRestored
RewriteWithBrokenOrganisation
Tic
ImportBusinessTemplate
UseImportBusinessTemplate
InstallBusinessTemplate
Tic
CheckOrganisationModified
"""
sequence_list.addSequenceString(sequence_string)
sequence_list.play(self)
from Products.ERP5Type.Core.DocumentComponent import DocumentComponent from Products.ERP5Type.Core.DocumentComponent import DocumentComponent
class TestDocumentTemplateItem(BusinessTemplateMixin): class TestDocumentTemplateItem(BusinessTemplateMixin):
......
...@@ -1341,6 +1341,22 @@ class TestDocument(TestDocumentMixin): ...@@ -1341,6 +1341,22 @@ class TestDocument(TestDocumentMixin):
self.commit() self.commit()
self.tic() self.tic()
def test_upload_bad_pdf_file(self):
""" Test that pypdf2 handle wrong formatted PDF """
path = os.path.join(os.path.dirname(__file__), 'test_document',
'FEUILLE BLANCHE.pdf')
file_upload = FileUpload(path, 'FEUILLE BLANCHE.pdf')
pdf = self.portal.document_module.newContent(
portal_type='PDF',
file=file_upload,
title='Bad PDF')
self.tic()
pdf.share()
self.tic()
self.assertEquals(pdf.getValidationState(), "shared")
result = pdf.getContentInformation()
self.assertNotEquals(result, None)
def test_PDF_content_content_type(self): def test_PDF_content_content_type(self):
upload_file = makeFileUpload('REF-en-001.pdf') upload_file = makeFileUpload('REF-en-001.pdf')
document = self.portal.document_module.newContent(portal_type='PDF') document = self.portal.document_module.newContent(portal_type='PDF')
......
...@@ -190,3 +190,8 @@ ModuleSecurityInfo('Products.ERP5Type.Constraint').declarePublic('PropertyTypeVa ...@@ -190,3 +190,8 @@ ModuleSecurityInfo('Products.ERP5Type.Constraint').declarePublic('PropertyTypeVa
ModuleSecurityInfo('Products.ERP5Type.collections').declarePublic('OrderedDict') ModuleSecurityInfo('Products.ERP5Type.collections').declarePublic('OrderedDict')
ModuleSecurityInfo('Products.ERP5Type.DiffUtils').declarePublic('DiffFile') ModuleSecurityInfo('Products.ERP5Type.DiffUtils').declarePublic('DiffFile')
ModuleSecurityInfo('pprint').declarePublic('pformat', 'pprint') ModuleSecurityInfo('pprint').declarePublic('pformat', 'pprint')
import zExceptions
ModuleSecurityInfo('zExceptions').declarePublic(*filter(
lambda x: Exception in getattr(getattr(zExceptions, x), '__mro__', ()),
dir(zExceptions)))
...@@ -27,7 +27,6 @@ ...@@ -27,7 +27,6 @@
############################################################################## ##############################################################################
from ply import lex, yacc from ply import lex, yacc
import os
import sys import sys
from cStringIO import StringIO from cStringIO import StringIO
...@@ -37,8 +36,6 @@ except ImportError: ...@@ -37,8 +36,6 @@ except ImportError:
def LOG(channel, level, message): def LOG(channel, level, message):
print >>sys.stderr, message print >>sys.stderr, message
module_path = os.path.dirname(os.path.abspath(__file__))
class ParserOrLexerError(Exception): class ParserOrLexerError(Exception):
pass pass
...@@ -56,8 +53,7 @@ class lexer(object): ...@@ -56,8 +53,7 @@ class lexer(object):
self.lexer = lex.lex(object=self, **kw) self.lexer = lex.lex(object=self, **kw)
self.parser = yacc.yacc(module=self, debug=debug, self.parser = yacc.yacc(module=self, debug=debug,
debugfile="%s.out" % (self.__class__.__name__, ), debugfile="%s.out" % (self.__class__.__name__, ),
tabmodule="%s_parsetab" % (self.__class__.__name__, ), write_tables=False)
outputdir=module_path)
sys.stdout, sys.stderr = sys.__stdout__, sys.__stderr__ sys.stdout, sys.stderr = sys.__stdout__, sys.__stderr__
# Emit all logs with regular Zope logging # Emit all logs with regular Zope logging
for line in output.getvalue().split('\n'): for line in output.getvalue().split('\n'):
......
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