Commit de0784c5 authored by Aurel's avatar Aurel

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

parents c302bb68 badb7a60
1550
\ No newline at end of file
1551
\ No newline at end of file
......@@ -72,7 +72,6 @@ Internal Invoice Transaction | document_list
Internal Invoice Transaction | jump_related_payment
Internal Invoice Transaction | profile_view
Internal Invoice Transaction | source_asset
Internal Invoice Transaction | view
Invoice Root Simulation Rule | view
Organisation | account_statement_export
Organisation | account_statement_report
......
......@@ -60,7 +60,7 @@ reference_list = [x.reference for x in\n
select_list=[\'reference\'],\n
portal_type="Person", title=value)]\n
\n
return SimpleQuery(owner=reference_list or -1)\n
return SimpleQuery(owner=reference_list or value or -1)\n
</string> </value>
</item>
<item>
......
......@@ -58,6 +58,7 @@ if owner_id_list:\n
found_user_list = getUserByLogin(context.getPortalObject(), tuple(owner_id_list))\n
if found_user_list:\n
return found_user_list[0].getTitle()\n
return owner_id_list[0]\n
</string> </value>
</item>
<item>
......
......@@ -52,7 +52,7 @@
<key> <string>_body</string> </key>
<value> <string>context.getVcsTool().setLogin(auth, user, password)\n
\n
return context.REQUEST.traverseName(context, caller)(**caller_kw)\n
return context.restrictedTraverse(caller)(**caller_kw)\n
</string> </value>
</item>
<item>
......
676
\ No newline at end of file
677
\ No newline at end of file
......@@ -86,8 +86,7 @@ excluded_portal_type_list = context.getPortalTaxMovementTypeList() \\\n
def getSubLineList(obj):\n
sub_list = []\n
for x in obj.contentValues(portal_type=context.getPortalInvoiceMovementTypeList(),\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')],\n
checked_permission=\'View\'):\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')],):\n
if x.getPortalType() in excluded_portal_type_list:\n
continue\n
sub_list.append(x)\n
......
393
394
\ No newline at end of file
......@@ -56,8 +56,7 @@
def getSubLineList(obj):\n
sub_list = []\n
for x in obj.contentValues(portal_type=context.getPortalOrderMovementTypeList(),\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')],\n
checked_permission=\'View\'):\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')]):\n
if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n
continue\n
sub_list.append(x)\n
......
......@@ -55,7 +55,7 @@
\n
def getSubLineList(obj):\n
sub_list = []\n
for x in obj.searchFolder(portal_type=context.getPortalDeliveryMovementTypeList(),\n
for x in obj.contentValues(portal_type=context.getPortalDeliveryMovementTypeList(),\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')]):\n
if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n
continue\n
......
480
\ No newline at end of file
481
\ No newline at end of file
......@@ -83,8 +83,7 @@ else:\n
def getSubLineList(obj):\n
sub_list = []\n
for x in obj.contentValues(portal_type=context.getPortalOrderMovementTypeList(),\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')],\n
checked_permission=\'View\'):\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')]):\n
if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n
continue\n
sub_list.append(x)\n
......
......@@ -66,7 +66,7 @@
\n
def getSubLineList(obj):\n
sub_list = []\n
for x in obj.searchFolder(portal_type=context.getPortalDeliveryMovementTypeList(),\n
for x in obj.contentValues(portal_type=context.getPortalDeliveryMovementTypeList(),\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')]):\n
if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n
continue\n
......
1174
\ No newline at end of file
1175
\ No newline at end of file
......@@ -1489,18 +1489,19 @@ class PathTemplateItem(ObjectTemplateItem):
def install(self, context, *args, **kw):
super(PathTemplateItem, self).install(context, *args, **kw)
# Regenerate local roles for all paths in this business template
p = context.getPortalObject()
portal_type_role_list_len_dict = {}
update_dict = defaultdict(list)
for path in self._objects:
obj = p.unrestrictedTraverse(path)
obj = p.unrestrictedTraverse(path, None)
try:
portal_type = aq_base(obj).getPortalType()
except Exception, e:
LOG("BusinessTemplate", WARNING,
"Could not update Local Roles as Portal Type for '%s' is not "
"available (%s)" % (obj, e))
"Could not update Local Roles as Portal Type for '%s' (obj: %s)"
" is not available" % (path, obj), error=True)
continue
......@@ -3282,7 +3283,7 @@ class PortalTypeRolesTemplateItem(BaseTemplateItem):
for role_property_dict in type_roles_list:
obj._importRole(role_property_dict)
else:
raise AttributeError("Path '%r' not found while "
raise AttributeError("Path %r not found while "
"installing roles" % (path, ))
def uninstall(self, context, **kw):
......
......@@ -75,7 +75,7 @@
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Component_view</string> </value>
<value> <string>string:${object_url}/ComponentMixin_view</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -75,7 +75,7 @@
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Component_view</string> </value>
<value> <string>string:${object_url}/ComponentMixin_view</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -16,13 +16,13 @@
<key> <string>categories</string> </key>
<value>
<tuple>
<string>action_type/object_view</string>
<string>action_type/object_action</string>
</tuple>
</value>
</item>
<item>
<key> <string>category</string> </key>
<value> <string>object_view</string> </value>
<value> <string>object_action</string> </value>
</item>
<item>
<key> <string>condition</string> </key>
......@@ -30,7 +30,9 @@
</item>
<item>
<key> <string>description</string> </key>
<value> <string></string> </value>
<value>
<none/>
</value>
</item>
<item>
<key> <string>icon</string> </key>
......@@ -38,13 +40,13 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>view</string> </value>
<value> <string>change_password</string> </value>
</item>
<item>
<key> <string>permissions</string> </key>
<value>
<tuple>
<string>View</string>
<string>Set own password</string>
</tuple>
</value>
</item>
......@@ -54,7 +56,7 @@
</item>
<item>
<key> <string>title</string> </key>
<value> <string>Accounting View</string> </value>
<value> <string>Change Password</string> </value>
</item>
<item>
<key> <string>visible</string> </key>
......@@ -71,7 +73,7 @@
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/InternalInvoiceTransaction_view</string> </value>
<value> <string>string:${object_url}/PreferenceTool_viewChangePasswordDialog</string> </value>
</item>
</dictionary>
</pickle>
......
......@@ -75,7 +75,7 @@
<dictionary>
<item>
<key> <string>text</string> </key>
<value> <string>string:${object_url}/Component_view</string> </value>
<value> <string>string:${object_url}/ComponentMixin_view</string> </value>
</item>
</dictionary>
</pickle>
......
<?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_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.getPortalSupplyTypeList() + portal.getPortalSupplyPathTypeList() + portal.getPortalAccountingTransactionTypeList() + portal.getPortalProjectTypeList() + 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_advice</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>
<none/>
</value>
</item>
<item>
<key> <string>fallback_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>destination_advice</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 Advice</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value>
<none/>
</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="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_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.getPortalSupplyTypeList() + portal.getPortalSupplyPathTypeList() + portal.getPortalAccountingTransactionTypeList() + portal.getPortalProjectTypeList() + 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>source_advice</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>
<none/>
</value>
</item>
<item>
<key> <string>fallback_base_category</string> </key>
<value>
<tuple/>
</value>
</item>
<item>
<key> <string>id</string> </key>
<value> <string>source_advice</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 Advice</string> </value>
</item>
<item>
<key> <string>write_permission</string> </key>
<value>
<none/>
</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>
......@@ -67,7 +67,7 @@ class Part:
def generateParts(context,text,sw,tags,trail,maxlines):
def generateParts(_,text,sw,tags,trail,maxlines):
par=Part(tags,trail)
sw=sw.translate(tr).strip().lower().split()
test=lambda w:w.translate(tr).strip().lower() in sw
......@@ -122,7 +122,7 @@ if __name__=='__main__':
tags=('<b>','</b>')
trail=5
maxlines=5
for p in cutFound(None,txt,sw,tags,trail,maxlines):
for p in getExcerptText(None,txt,sw,tags,trail,maxlines):
print p
......
......@@ -117,7 +117,7 @@
</item>
<item>
<key> <string>id</string> </key>
<value> <string>Component_view</string> </value>
<value> <string>ComponentMixin_view</string> </value>
</item>
<item>
<key> <string>method</string> </key>
......
2013-10-04 arnaud.fontaine
* ZODB Components: Rename common view to ComponentMixin_view (naming conventions and clash with erp5_pdm).
2013-10-03 arnaud.fontaine
* erp5_core: Cosmetic: Get rid of a pylint warning.
2013-10-03 arnaud.fontaine
* erp5_core: A function was renamed but some code has not been updated accordingly (24ccf35).
2013-10-17 tatuya
* Add {source,destination}_{decision,carrier,section}_administration categories.
......
41130
\ No newline at end of file
41134
\ No newline at end of file
......@@ -88,6 +88,7 @@ Preference Type | role_view
Preference Type | translation_view
Preference Type | update_local_roles
Preference Type | view
Preference | change_password
Preference | html_style_preferences
Preference | view
Preference | view_template
......
......@@ -8,6 +8,7 @@ delivery
destination
destination_account
destination_administration
destination_advice
destination_carrier_administration
destination_decision
destination_decision_administration
......@@ -33,6 +34,7 @@ size
source
source_account
source_administration
source_advice
source_carrier_administration
source_decision
source_decision_administration
......
<?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_advice_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_advice_category</string> </value>
</item>
<item>
<key> <string>portal_type</string> </key>
<value> <string>Category Property</string> </value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
67
\ No newline at end of file
68
\ No newline at end of file
......@@ -29,7 +29,6 @@
import unittest
import os
import popen2
import urllib
from subprocess import Popen, PIPE
......@@ -450,15 +449,14 @@ class W3Validator(object):
# Zope 2.12 renders page templates as unicode
page_source = page_source.encode('utf-8')
source = 'fragment=%s&output=soap12' % urllib.quote_plus(page_source)
os.environ['CONTENT_LENGTH'] = str(len(source))
os.environ['REQUEST_METHOD'] = 'POST'
stdout, stdin, stderr = popen2.popen3(self.validator_path)
stdin.write(source)
stdin.close()
while stdout.readline() != '\n':
pass
result = stdout.read()
return self._parse_validation_results(result)
stdout, stderr = Popen(self.validator_path,
stdin=PIPE, stdout=PIPE, stderr=PIPE,
close_fds=True,
env={"CONTENT_LENGTH": str(len(source)),
"REQUEST_METHOD": "POST"}).communicate(source)
# Output is a set of headers then the XML content.
return self._parse_validation_results(
stdout.split('<?xml version="1.0" encoding="UTF-8"?>')[1])
class TidyValidator(object):
......@@ -498,9 +496,9 @@ class TidyValidator(object):
'''
retrun two list : a list of errors and an other for warnings
'''
stdout, stdin, stderr = popen2.popen3('%s -e -q -utf8' % self.validator_path)
stdin.write(page_source)
stdin.close()
stdout, stderr = Popen('%s -e -q -utf8' % self.validator_path,
stdin=PIPE, stdout=PIPE, stderr=PIPE,
close_fds=True).communicate(page_source)
return self._parse_validation_results(stderr)
......
......@@ -40,6 +40,11 @@ else:
from Products.ERP5Type.tests.backportUnittest import \
expectedFailure as newSimulationExpectedFailure
# Keep a global reference to a ZODB storage so that we can import business
# template xml files. XXX this connection will remain open.
db = DB(DemoStorage())
connection = db.open()
class BusinessTemplateInfoBase:
......@@ -103,15 +108,12 @@ class BusinessTemplateInfoBase:
def setUpActions(self):
def parse(file_path):
db = DB(DemoStorage())
_connection = db.open()
action_information = importXML(_connection, file_path)
action_information = importXML(connection, file_path)
action_information.__repr__()
for key, value in action_information.__dict__.iteritems():
if value not in (None, "") and key in ('action', 'condition') :
setattr(action_information, key, value.text)
actions = action_information.__dict__.copy()
db.close()
return actions
name = '%s/ActionTemplateItem/portal_types/' % self.getPrefix()
......
......@@ -42,10 +42,6 @@ from hashlib import md5
import time
from zope.interface import Interface
from zope.interface import implements
_field_value_cache = {}
def purgeFieldValueCache():
_field_value_cache.clear()
class ICaptchaProvider(Interface):
"""The CaptchaProvider interface provides a captcha generator."""
......
......@@ -48,9 +48,38 @@ from Products.PageTemplates.Expressions import SecureModuleImporter
from Products.ERP5Type.PsycoWrapper import psyco
import sys
_field_value_cache = {}
def purgeFieldValueCache():
_field_value_cache.clear()
class FieldValueCacheDict(dict):
_last_sync = -1
def clear(self):
super(FieldValueCacheDict, self).clear()
from Products.ERP5.ERP5Site import getSite
try:
portal = getSite()
except IndexError:
pass
else:
portal.newCacheCookie('form_field_value_cache')
self._last_sync = portal.getCacheCookie('form_field_value_cache')
def __getitem__(self, cache_id):
from Products.ERP5.ERP5Site import getSite
try:
portal = getSite()
except IndexError:
pass
else:
cookie = portal.getCacheCookie('form_field_value_cache')
if cookie != self._last_sync:
LOG("ERP5Form.Form", 0, "Resetting form field value cache")
self._last_sync = cookie
self.clear()
raise KeyError('Field cache is outdated and has been reset')
return super(FieldValueCacheDict, self).__getitem__(cache_id)
field_value_cache = FieldValueCacheDict()
# Patch the fiels methods to provide improved namespace handling
......@@ -343,7 +372,7 @@ def get_value(self, id, REQUEST=None, **kw):
id)
try:
value = _field_value_cache[cache_id]
value = field_value_cache[cache_id]
except KeyError:
# either returns non callable value (ex. "Title")
# or a FieldValue instance of appropriate class
......@@ -353,7 +382,7 @@ def get_value(self, id, REQUEST=None, **kw):
# and caching sometimes break these field settings at initialization.
# As the result, we would see broken field editing screen in ZMI.
if cacheable and self._p_oid:
_field_value_cache[cache_id] = value
field_value_cache[cache_id] = value
if callable(value):
return value(field, id, **kw)
......
......@@ -52,6 +52,5 @@ class FieldValueCacheInteractor(Interactor):
Interaction method (defined at the Interactor level).
Make sure all field value caches are purged
"""
from Products.ERP5Form import Form, ProxyField
Form.purgeFieldValueCache()
ProxyField.purgeFieldValueCache()
from Products.ERP5Form.Form import field_value_cache
field_value_cache.clear()
......@@ -60,10 +60,6 @@ from thread import get_ident
_USE_ORIGINAL_GET_VALUE_MARKER = []
_field_value_cache = {}
def purgeFieldValueCache():
_field_value_cache.clear()
class WidgetDelegatedMethod(Method):
"""Method delegated to the proxied field's widget.
"""
......@@ -740,14 +736,15 @@ class ProxyField(ZMIField):
field._p_oid,
id)
from Products.ERP5Form.Form import field_value_cache
try:
value = _field_value_cache[cache_id]
value = field_value_cache[cache_id]
except KeyError:
# either returns non callable value (ex. "Title")
# or a FieldValue instance of appropriate class
value, cacheable = self.getFieldValue(field, id, **kw)
if cacheable:
_field_value_cache[cache_id] = value
field_value_cache[cache_id] = value
if value is _USE_ORIGINAL_GET_VALUE_MARKER:
return proxy_field.get_value(id, **kw)
......
......@@ -70,23 +70,23 @@ class TestFieldValueCache(ERP5TypeTestCase):
# Get form value
field = form.my_first_name
id = 'title'
from Products.ERP5Form.ProxyField import _field_value_cache
from Products.ERP5Form.Form import field_value_cache
cache_id = ('ProxyField.get_value',
field._p_oid,
field._p_oid,
id)
# Make sure cache has field
self.assertTrue(_field_value_cache.has_key(cache_id))
self.assertTrue(field_value_cache.has_key(cache_id))
# Make sure cache and field are equal
self.assertEquals(field.get_value(id), _field_value_cache[cache_id])
self.assertEquals(field.get_value(id), field_value_cache[cache_id])
# Call manage_renameObject
form.manage_renameObject('my_first_name', 'my_first_name2')
form.manage_renameObject('my_first_name2', 'my_first_name')
# Make sure cache has no field
self.assertFalse(_field_value_cache.has_key(cache_id))
self.assertFalse(field_value_cache.has_key(cache_id))
# Render
form()
# Make sure cache has field
self.assertTrue(_field_value_cache.has_key(cache_id))
self.assertTrue(field_value_cache.has_key(cache_id))
# Make sure cache and field are equal
self.assertEquals(field.get_value(id), _field_value_cache[cache_id])
self.assertEquals(field.get_value(id), field_value_cache[cache_id])
......@@ -46,7 +46,7 @@ from Products.Formulator.TALESField import TALESMethod
from Products.ERP5Type.Core.Folder import Folder
from Products.ERP5Form.Form import ERP5Form
from Products.ERP5Form.Form import purgeFieldValueCache
from Products.ERP5Form.Form import field_value_cache
from Products.ERP5Form.Form import getFieldValue
from Products.ERP5Form import Form
from Products.ERP5Form import ProxyField
......@@ -110,6 +110,15 @@ class TestFloatField(ERP5TypeTestCase):
self.field.values['input_style'] = '-1,234.5'
self.field.values['precision'] = 0
self.assertEquals('-1,000', self.widget.format_value(self.field, -1000.25))
self.assertEquals('-1,000', self.widget.format_value(self.field, -1000.49))
self.assertEquals('-1,001', self.widget.format_value(self.field, -1000.99))
self.assertEquals('-1,001', self.widget.format_value(self.field, -1000.80))
self.assertEquals('-1,001', self.widget.format_value(self.field, -1000.70))
self.assertEquals('-1,001', self.widget.format_value(self.field, -1000.60))
self.assertEquals('-1,001', self.widget.format_value(self.field, -1000.59))
self.assertEquals('-1,001', self.widget.format_value(self.field, -1000.51))
# this is not -1,001 (is this a specification?)
self.assertEquals('-1,000', self.widget.format_value(self.field, -1000.50))
def test_format_percent_style(self):
self.field.values['input_style'] = '-12.3%'
......@@ -121,7 +130,7 @@ class TestFloatField(ERP5TypeTestCase):
# value is rounded
self.assertEquals('13', self.widget.format_value(self.field, 12.9))
purgeFieldValueCache() # call this before changing internal field values.
field_value_cache.clear() # call this before changing internal field values.
self.field.values['precision'] = 2
self.assertEquals('0.01', self.widget.format_value(self.field, 0.011))
# value is rounded
......@@ -925,42 +934,50 @@ class TestFieldValueCache(ERP5TypeTestCase):
self.assertEqual(False, value.value is field.values['external_validator'])
self.assertEqual(True, type(value.value) is Method)
def _getCacheSize(self, cache_id):
count = 0
for cache_key in field_value_cache.viewkeys():
if cache_key[0] == cache_id:
count += 1
return count
def test_using_cache_or_not(self):
# check standard field in zodb
# make sure that this will use cache.
cache_size = len(Form._field_value_cache)
cache_size = self._getCacheSize('Form.get_value')
self.root.form.field.get_value('title')
self.assertEqual(True, cache_size < len(Form._field_value_cache))
self.assertEqual(True, cache_size < self._getCacheSize('Form.get_value'))
# check on-memory field
# make sure that this will not use cache.
cache_size = len(Form._field_value_cache)
cache_size = self._getCacheSize('Form.get_value')
self.assertEqual(repr(self.root),
self.root.form.my_on_memory_tales_field.get_value('default'))
self.assertEqual('123',
self.root.form.my_on_memory_field.get_value('default'))
self.assertEqual(True, cache_size == len(Form._field_value_cache))
self.assertEqual(True, cache_size == self._getCacheSize('Form.get_value'))
# check proxy field
# make sure that this will use cache.
cache_size = len(ProxyField._field_value_cache)
cache_size = self._getCacheSize('ProxyField.get_value')
self.root.form.proxy_field.get_value('title')
self.assertEqual(True, cache_size < len(ProxyField._field_value_cache))
self.assertEqual(True, cache_size < self._getCacheSize('ProxyField.get_value'))
# check proxy field with tales
# make sure that this will not use cache.
cache_size = len(ProxyField._field_value_cache)
cache_size = self._getCacheSize('ProxyField.get_value')
self.root.form.proxy_field_tales.get_value('title')
self.assertEqual(True, cache_size == len(ProxyField._field_value_cache))
self.assertEqual(True, cache_size == self._getCacheSize('ProxyField.get_value'))
def test_datetime_field(self):
purgeFieldValueCache()
field_value_cache.clear()
# make sure that boundmethod must not be cached.
year_field = self.root.form.datetime_field.sub_form.get_field('year', include_disabled=1)
self.assertEqual(True, type(year_field.overrides['items']) is BoundMethod)
cache_size = len(Form._field_value_cache)
cache_size = len(field_value_cache)
year_field.get_value('items')
# See Formulator/StandardFields.py(line:174)
......@@ -972,22 +989,22 @@ class TestFieldValueCache(ERP5TypeTestCase):
self.root.form.datetime_field._p_oid,
self.root.form.datetime_field._p_oid,
'start_datetime'
) in Form._field_value_cache)
) in field_value_cache)
self.assertEqual(True, ('Form.get_value',
self.root.form.datetime_field._p_oid,
self.root.form.datetime_field._p_oid,
'end_datetime'
) in Form._field_value_cache)
) in field_value_cache)
self.assertEqual(False, ('Form.get_value',
year_field._p_oid,
year_field._p_oid,
'items'
) in Form._field_value_cache)
self.assertEqual(cache_size, len(Form._field_value_cache))
) in field_value_cache)
self.assertEqual(cache_size, len(field_value_cache))
year_field.get_value('size')
year_field.get_value('default')
self.assertEqual(cache_size+2, len(Form._field_value_cache))
self.assertEqual(cache_size+2, len(field_value_cache))
def makeDummyOid():
import time, random
......
......@@ -30,8 +30,7 @@ from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.Formulator.TALESField import TALESMethod
from Products.ERP5Type.Core.Folder import Folder
from Products.ERP5Form.Form import ERP5Form
from Products.ERP5Form.ProxyField import purgeFieldValueCache
from Products.ERP5Form.Form import field_value_cache
class TestProxify(ERP5TypeTestCase):
......@@ -103,12 +102,12 @@ class TestProxify(ERP5TypeTestCase):
self.assertEqual(field.is_delegated('description'), True)
self.assertEqual(field.get_value('description'), '')
purgeFieldValueCache() # must purge cache before changing internal field value.
field_value_cache.clear() # must purge cache before changing internal field value.
template_field = self.base_view.my_string_field
template_field.values['description'] = 'Description'
self.assertEqual(field.get_value('description'), 'Description')
purgeFieldValueCache()
field_value_cache.clear()
# ListField
self.person_view.manage_addField('my_gender', 'Gender', 'ListField')
......@@ -119,7 +118,7 @@ class TestProxify(ERP5TypeTestCase):
self.assertEqual(field.is_delegated('items'), True)
self.assertEqual(field.get_value('items'), [('Male', 'Male'), ('Female', 'Female')])
purgeFieldValueCache()
field_value_cache.clear()
def test_multi_level_proxify(self):
......@@ -146,7 +145,7 @@ class TestProxify(ERP5TypeTestCase):
self.assertEqual(field.has_value('scrap_variable'), 0)
purgeFieldValueCache() # must purge cache before changing internal field value.
field_value_cache.clear() # must purge cache before changing internal field value.
template_field = self.address_view.my_region
template_field.values['title'] = 'Region'
self.assertEqual(field.get_value('title'), 'Region')
......@@ -192,7 +191,7 @@ class TestProxify(ERP5TypeTestCase):
#Proxify First
self.address_view.proxifyField({'my_region':'Base_view.my_list_field'})
self.person_view.proxifyField({'my_default_region':'Address_view.my_region'})
purgeFieldValueCache()
field_value_cache.clear()
#UnProxify
self.person_view.unProxifyField({'my_default_region':'on'})
field = self.person_view.my_default_region
......@@ -204,7 +203,7 @@ class TestProxify(ERP5TypeTestCase):
#Test unproxify with old instance.
#Proxify First
self.person_view.proxifyField({'my_career_subordination_title':'Base_view.my_relation_string_field'})
purgeFieldValueCache()
field_value_cache.clear()
#UnProxify
self.person_view.unProxifyField({'my_career_subordination_title':'on'})
field = self.person_view.my_career_subordination_title
......
##############################################################################
#
# Copyright (c) 2013 Nexedi SARL and Contributors. All Rights Reserved.
# Vincent Pelletier <vincent@nexedi.com>
#
# 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.
#
##############################################################################
"""
Restricted calendar module.
Disable functions writing to stdout:
- TextCalendar.prweek
- TextCalendar.prmonth
- TextCalendar.pryear
- prcal
- prmonth
Do not provide access to locale-dependent representations, as it's not the
right way to handle l10n in Zope:
- day_name
- day_abbr
- month_name
- month_abbr
- LocaleTextCalendar
- LocaleHTMLCalendar
Provide access to HTMLCalendar, although it's probably not a good idea to use
it.
From restricted python, use "import calendar" (see patches/Restricted.py).
"""
from AccessControl import allow_class as _allow_class
from zExceptions import Unauthorized
import calendar as _calendar
def _disallowed(*args, **kw):
raise Unauthorized
prcal = _disallowed
prmonth = _disallowed
IllegalMonthError = _calendar.IllegalMonthError
IllegalWeekdayError = _calendar.IllegalWeekdayError
calendar = _calendar.calendar
firstweekday = _calendar.firstweekday
isleap = _calendar.isleap
leapdays = _calendar.leapdays
month = _calendar.month
monthcalendar = _calendar.monthcalendar
monthrange = _calendar.monthrange
setfirstweekday = _calendar.setfirstweekday
timegm = _calendar.timegm
weekday = _calendar.weekday
Calendar = _calendar.Calendar
_allow_class(Calendar)
HTMLCalendar = _calendar.HTMLCalendar
_allow_class(HTMLCalendar)
class TextCalendar(_calendar.TextCalendar):
prweek = _disallowed
prmonth = _disallowed
pryear = _disallowed
_allow_class(TextCalendar)
......@@ -39,6 +39,7 @@ from Products.ERP5Type.patches import sqlvar
from Products.ERP5Type.patches import CMFCatalogAware
from Products.ERP5Type.patches import ProductContext
from Products.ERP5Type.patches import PropertiedUser
from Products.ERP5Type.patches import PluggableAuthService
from Products.ERP5Type.patches import States
from Products.ERP5Type.patches import FSZSQLMethod
from Products.ERP5Type.patches import ActionInformation
......
......@@ -301,8 +301,8 @@ class ComponentMixin(PropertyRecordableMixin, Base):
try:
from pylint.lint import Run
from pylint.reporters.text import TextReporter
except ImportError:
return ['F: Cannot check Source Code: Pylint is not available'], []
except ImportError, error:
return ['F: Cannot check Source Code: Pylint is not available (%s)' % error], []
import cStringIO
import tempfile
......
##############################################################################
#
# Copyright (c) 2001 Zope Foundation and Contributors
# Copyright (c) 2013 Nexedi SARL and Contributors. All Rights Reserved.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this
# distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE.
#
##############################################################################
from hashlib import md5
from Products.PluggableAuthService.PluggableAuthService \
import PluggableAuthService, _noroles, nobody
from Products.ERP5Type.Cache import caching_instance_method
if 1:
assert md5(PluggableAuthService.validate.func_code.co_code).hexdigest() in (
# PluggableAuthService 1.9.0
'5e2e6adabd03124bfd21278d3b6fb1c7', # Python 2.6
'5ef8421949366195dbb2d15d979a14c9', # Python 2.7
)
# When no user is found, try to create anonymous user even if we're not the
# top user folder, so that anonymous user can be customized in appropriate
# context (in particular: assign anonymous user to groups).
# Because it's common to define admin users at root, original behaviour
# is kept if any basic auth string is passed.
def validate( self, request, auth='', roles=_noroles ):
""" See IUserFolder.
"""
plugins = self._getOb( 'plugins' )
is_top = self._isTop()
if not is_top and self._isNotCompetent( request, plugins ):
# this user folder should not try to authenticate this request
return None
user_ids = self._extractUserIds(request, plugins)
( accessed
, container
, name
, value
) = self._getObjectContext( request[ 'PUBLISHED' ], request )
for user_id, login in user_ids:
user = self._findUser(plugins, user_id, login, request=request)
if aq_base( user ) is emergency_user:
if is_top:
return user
else:
return None
if self._authorizeUser( user
, accessed
, container
, name
, value
, roles
):
return user
if auth and not is_top: # patch 1
return None
#
# No other user folder above us can satisfy, and we have no user;
# return a constructed anonymous only if anonymous is authorized.
#
anonymous = self._createAnonymousUser( plugins )
if self._authorizeUser( anonymous
, accessed
, container
, name
, value
, roles
):
return anonymous
return None
PluggableAuthService.validate.im_func.func_code = validate.func_code
@caching_instance_method('createAnonymousUser',
cache_factory='erp5_content_short')
def createAnonymousUser(self):
try:
role_list, group_list = self.ERP5Site_getAnonymousUserSecurity()
if role_list or group_list:
from Products.ERP5Security.ERP5UserFactory import ERP5User
user = ERP5User(nobody.getId(), nobody.getUserName())
user._addRoles(nobody.getRoles())
user._addRoles(role_list)
user._addGroups(group_list)
return user
except Exception:
pass
# AnonymousUserFactory plugins have never been usable in ERP5 so
# instead of bothering user to create one on existing site, ignore
# these plugins and call directly our code to create anonymous users.
def _createAnonymousUser(self, plugins):
user = createAnonymousUser(self)
return (nobody if user is None else user).__of__(self)
PluggableAuthService._createAnonymousUser = _createAnonymousUser
\ No newline at end of file
......@@ -189,6 +189,7 @@ ModuleSecurityInfo('os.path').declarePublic(
# Alias modules - only applied to restricted python.
MNAME_MAP = {
'zipfile': 'Products.ERP5Type.ZipFile',
'calendar': 'Products.ERP5Type.Calendar',
}
for alias, real in MNAME_MAP.items():
assert '.' not in alias, alias # TODO: support this
......
......@@ -294,12 +294,7 @@ class SearchKey(object):
if logical_operator is None:
logical_operator = default_logical_operator
operator_value_dict = {}
if None in search_value:
if comparison_operator not in (None, 'is'):
LOG('KeywordKey', 100,
'None value requires an "is" comparison operator. Fixed.')
operator_value_dict['is'] = search_value
elif comparison_operator is None:
if comparison_operator is None:
if issubclass(reference_class, basestring):
if get_operator_from_value:
parsed = True
......
......@@ -264,7 +264,9 @@ class AdvancedSearchTextParser(lexer):
def p_value(self, p):
'''value : OPERATOR string
| string'''
| OPERATOR NULL
| string
| NULL'''
if len(p) == 2:
p[0] = ValueNode(p[1])
else:
......
......@@ -116,10 +116,7 @@ if __name__ == '__main__':
return (self.column, self.value, self.comparison_operator)
def __repr__(self):
value = self.value
if len(value) == 1:
value = value[0]
return 'Query(%r, %r, %r)' % (self.column, value, self.comparison_operator)
return 'Query(%r, %r, %r)' % (self.column, self.value, self.comparison_operator)
def __eq__(self, other):
if isinstance(other, Query):
......
from SearchTextParser import parse, isAdvancedSearchText
def dequote(value):
assert isinstance(value, basestring), value
if len(value) >= 2 and value[0] == value[-1] == '"' and value[-2] != '\\':
if isinstance(value, basestring) and len(value) >= 2 and \
value[0] == value[-1] == '"' and value[-2] != '\\':
escaped = False
value_list = []
append = value_list.append
......
......@@ -82,7 +82,9 @@ class lexer(object):
'WORD',
'OPERATOR',
'LEFT_PARENTHESE',
'RIGHT_PARENTHESE')
'RIGHT_PARENTHESE',
'NULL',
)
t_ignore = ' '
......@@ -123,6 +125,11 @@ class lexer(object):
r'[^><= :\(\)"][^ :\(\)"]*'
return t
def t_NULL(self, t):
r'NULL'
t.value = None
return t
def parse(self, *args, **kw):
kw['lexer'] = self
return self.parser.parse(*args, **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