Commit de0784c5 authored by Aurel's avatar Aurel

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

parents c302bb68 badb7a60
1550 1551
\ No newline at end of file \ No newline at end of file
...@@ -72,7 +72,6 @@ Internal Invoice Transaction | document_list ...@@ -72,7 +72,6 @@ Internal Invoice Transaction | document_list
Internal Invoice Transaction | jump_related_payment Internal Invoice Transaction | jump_related_payment
Internal Invoice Transaction | profile_view Internal Invoice Transaction | profile_view
Internal Invoice Transaction | source_asset Internal Invoice Transaction | source_asset
Internal Invoice Transaction | view
Invoice Root Simulation Rule | view Invoice Root Simulation Rule | view
Organisation | account_statement_export Organisation | account_statement_export
Organisation | account_statement_report Organisation | account_statement_report
......
...@@ -60,7 +60,7 @@ reference_list = [x.reference for x in\n ...@@ -60,7 +60,7 @@ reference_list = [x.reference for x in\n
select_list=[\'reference\'],\n select_list=[\'reference\'],\n
portal_type="Person", title=value)]\n portal_type="Person", title=value)]\n
\n \n
return SimpleQuery(owner=reference_list or -1)\n return SimpleQuery(owner=reference_list or value or -1)\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -58,6 +58,7 @@ if owner_id_list:\n ...@@ -58,6 +58,7 @@ if owner_id_list:\n
found_user_list = getUserByLogin(context.getPortalObject(), tuple(owner_id_list))\n found_user_list = getUserByLogin(context.getPortalObject(), tuple(owner_id_list))\n
if found_user_list:\n if found_user_list:\n
return found_user_list[0].getTitle()\n return found_user_list[0].getTitle()\n
return owner_id_list[0]\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
...@@ -52,7 +52,7 @@ ...@@ -52,7 +52,7 @@
<key> <string>_body</string> </key> <key> <string>_body</string> </key>
<value> <string>context.getVcsTool().setLogin(auth, user, password)\n <value> <string>context.getVcsTool().setLogin(auth, user, password)\n
\n \n
return context.REQUEST.traverseName(context, caller)(**caller_kw)\n return context.restrictedTraverse(caller)(**caller_kw)\n
</string> </value> </string> </value>
</item> </item>
<item> <item>
......
676 677
\ No newline at end of file \ No newline at end of file
...@@ -86,8 +86,7 @@ excluded_portal_type_list = context.getPortalTaxMovementTypeList() \\\n ...@@ -86,8 +86,7 @@ excluded_portal_type_list = context.getPortalTaxMovementTypeList() \\\n
def getSubLineList(obj):\n def getSubLineList(obj):\n
sub_list = []\n sub_list = []\n
for x in obj.contentValues(portal_type=context.getPortalInvoiceMovementTypeList(),\n for x in obj.contentValues(portal_type=context.getPortalInvoiceMovementTypeList(),\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')],\n sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')],):\n
checked_permission=\'View\'):\n
if x.getPortalType() in excluded_portal_type_list:\n if x.getPortalType() in excluded_portal_type_list:\n
continue\n continue\n
sub_list.append(x)\n sub_list.append(x)\n
......
393 394
\ No newline at end of file
...@@ -56,8 +56,7 @@ ...@@ -56,8 +56,7 @@
def getSubLineList(obj):\n def getSubLineList(obj):\n
sub_list = []\n sub_list = []\n
for x in obj.contentValues(portal_type=context.getPortalOrderMovementTypeList(),\n for x in obj.contentValues(portal_type=context.getPortalOrderMovementTypeList(),\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')],\n sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')]):\n
checked_permission=\'View\'):\n
if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n
continue\n continue\n
sub_list.append(x)\n sub_list.append(x)\n
......
...@@ -55,7 +55,7 @@ ...@@ -55,7 +55,7 @@
\n \n
def getSubLineList(obj):\n def getSubLineList(obj):\n
sub_list = []\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 sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')]):\n
if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n
continue\n continue\n
......
480 481
\ No newline at end of file \ No newline at end of file
...@@ -83,8 +83,7 @@ else:\n ...@@ -83,8 +83,7 @@ else:\n
def getSubLineList(obj):\n def getSubLineList(obj):\n
sub_list = []\n sub_list = []\n
for x in obj.contentValues(portal_type=context.getPortalOrderMovementTypeList(),\n for x in obj.contentValues(portal_type=context.getPortalOrderMovementTypeList(),\n
sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')],\n sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')]):\n
checked_permission=\'View\'):\n
if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n
continue\n continue\n
sub_list.append(x)\n sub_list.append(x)\n
......
...@@ -66,7 +66,7 @@ ...@@ -66,7 +66,7 @@
\n \n
def getSubLineList(obj):\n def getSubLineList(obj):\n
sub_list = []\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 sort_on=[(\'int_index\', \'ascending\'), (\'reference\', \'ascending\')]):\n
if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n if x.getPortalType() in obj.getPortalTaxMovementTypeList():\n
continue\n continue\n
......
1174 1175
\ No newline at end of file \ No newline at end of file
...@@ -1489,18 +1489,19 @@ class PathTemplateItem(ObjectTemplateItem): ...@@ -1489,18 +1489,19 @@ class PathTemplateItem(ObjectTemplateItem):
def install(self, context, *args, **kw): def install(self, context, *args, **kw):
super(PathTemplateItem, self).install(context, *args, **kw) super(PathTemplateItem, self).install(context, *args, **kw)
# Regenerate local roles for all paths in this business template
p = context.getPortalObject() p = context.getPortalObject()
portal_type_role_list_len_dict = {} portal_type_role_list_len_dict = {}
update_dict = defaultdict(list) update_dict = defaultdict(list)
for path in self._objects: for path in self._objects:
obj = p.unrestrictedTraverse(path) obj = p.unrestrictedTraverse(path, None)
try: try:
portal_type = aq_base(obj).getPortalType() portal_type = aq_base(obj).getPortalType()
except Exception, e: except Exception, e:
LOG("BusinessTemplate", WARNING, LOG("BusinessTemplate", WARNING,
"Could not update Local Roles as Portal Type for '%s' is not " "Could not update Local Roles as Portal Type for '%s' (obj: %s)"
"available (%s)" % (obj, e)) " is not available" % (path, obj), error=True)
continue continue
...@@ -3282,7 +3283,7 @@ class PortalTypeRolesTemplateItem(BaseTemplateItem): ...@@ -3282,7 +3283,7 @@ class PortalTypeRolesTemplateItem(BaseTemplateItem):
for role_property_dict in type_roles_list: for role_property_dict in type_roles_list:
obj._importRole(role_property_dict) obj._importRole(role_property_dict)
else: else:
raise AttributeError("Path '%r' not found while " raise AttributeError("Path %r not found while "
"installing roles" % (path, )) "installing roles" % (path, ))
def uninstall(self, context, **kw): def uninstall(self, context, **kw):
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>text</string> </key> <key> <string>text</string> </key>
<value> <string>string:${object_url}/Component_view</string> </value> <value> <string>string:${object_url}/ComponentMixin_view</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>text</string> </key> <key> <string>text</string> </key>
<value> <string>string:${object_url}/Component_view</string> </value> <value> <string>string:${object_url}/ComponentMixin_view</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -16,13 +16,13 @@ ...@@ -16,13 +16,13 @@
<key> <string>categories</string> </key> <key> <string>categories</string> </key>
<value> <value>
<tuple> <tuple>
<string>action_type/object_view</string> <string>action_type/object_action</string>
</tuple> </tuple>
</value> </value>
</item> </item>
<item> <item>
<key> <string>category</string> </key> <key> <string>category</string> </key>
<value> <string>object_view</string> </value> <value> <string>object_action</string> </value>
</item> </item>
<item> <item>
<key> <string>condition</string> </key> <key> <string>condition</string> </key>
...@@ -30,7 +30,9 @@ ...@@ -30,7 +30,9 @@
</item> </item>
<item> <item>
<key> <string>description</string> </key> <key> <string>description</string> </key>
<value> <string></string> </value> <value>
<none/>
</value>
</item> </item>
<item> <item>
<key> <string>icon</string> </key> <key> <string>icon</string> </key>
...@@ -38,13 +40,13 @@ ...@@ -38,13 +40,13 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>view</string> </value> <value> <string>change_password</string> </value>
</item> </item>
<item> <item>
<key> <string>permissions</string> </key> <key> <string>permissions</string> </key>
<value> <value>
<tuple> <tuple>
<string>View</string> <string>Set own password</string>
</tuple> </tuple>
</value> </value>
</item> </item>
...@@ -54,7 +56,7 @@ ...@@ -54,7 +56,7 @@
</item> </item>
<item> <item>
<key> <string>title</string> </key> <key> <string>title</string> </key>
<value> <string>Accounting View</string> </value> <value> <string>Change Password</string> </value>
</item> </item>
<item> <item>
<key> <string>visible</string> </key> <key> <string>visible</string> </key>
...@@ -71,7 +73,7 @@ ...@@ -71,7 +73,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>text</string> </key> <key> <string>text</string> </key>
<value> <string>string:${object_url}/InternalInvoiceTransaction_view</string> </value> <value> <string>string:${object_url}/PreferenceTool_viewChangePasswordDialog</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </pickle>
......
...@@ -75,7 +75,7 @@ ...@@ -75,7 +75,7 @@
<dictionary> <dictionary>
<item> <item>
<key> <string>text</string> </key> <key> <string>text</string> </key>
<value> <string>string:${object_url}/Component_view</string> </value> <value> <string>string:${object_url}/ComponentMixin_view</string> </value>
</item> </item>
</dictionary> </dictionary>
</pickle> </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: ...@@ -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) par=Part(tags,trail)
sw=sw.translate(tr).strip().lower().split() sw=sw.translate(tr).strip().lower().split()
test=lambda w:w.translate(tr).strip().lower() in sw test=lambda w:w.translate(tr).strip().lower() in sw
...@@ -122,7 +122,7 @@ if __name__=='__main__': ...@@ -122,7 +122,7 @@ if __name__=='__main__':
tags=('<b>','</b>') tags=('<b>','</b>')
trail=5 trail=5
maxlines=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 print p
......
...@@ -117,7 +117,7 @@ ...@@ -117,7 +117,7 @@
</item> </item>
<item> <item>
<key> <string>id</string> </key> <key> <string>id</string> </key>
<value> <string>Component_view</string> </value> <value> <string>ComponentMixin_view</string> </value>
</item> </item>
<item> <item>
<key> <string>method</string> </key> <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 2013-10-17 tatuya
* Add {source,destination}_{decision,carrier,section}_administration categories. * Add {source,destination}_{decision,carrier,section}_administration categories.
......
41130 41134
\ No newline at end of file \ No newline at end of file
...@@ -88,6 +88,7 @@ Preference Type | role_view ...@@ -88,6 +88,7 @@ Preference Type | role_view
Preference Type | translation_view Preference Type | translation_view
Preference Type | update_local_roles Preference Type | update_local_roles
Preference Type | view Preference Type | view
Preference | change_password
Preference | html_style_preferences Preference | html_style_preferences
Preference | view Preference | view
Preference | view_template Preference | view_template
......
...@@ -8,6 +8,7 @@ delivery ...@@ -8,6 +8,7 @@ delivery
destination destination
destination_account destination_account
destination_administration destination_administration
destination_advice
destination_carrier_administration destination_carrier_administration
destination_decision destination_decision
destination_decision_administration destination_decision_administration
...@@ -33,6 +34,7 @@ size ...@@ -33,6 +34,7 @@ size
source source
source_account source_account
source_administration source_administration
source_advice
source_carrier_administration source_carrier_administration
source_decision source_decision
source_decision_administration 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 68
\ No newline at end of file \ No newline at end of file
...@@ -29,7 +29,6 @@ ...@@ -29,7 +29,6 @@
import unittest import unittest
import os import os
import popen2
import urllib import urllib
from subprocess import Popen, PIPE from subprocess import Popen, PIPE
...@@ -450,15 +449,14 @@ class W3Validator(object): ...@@ -450,15 +449,14 @@ class W3Validator(object):
# Zope 2.12 renders page templates as unicode # Zope 2.12 renders page templates as unicode
page_source = page_source.encode('utf-8') page_source = page_source.encode('utf-8')
source = 'fragment=%s&output=soap12' % urllib.quote_plus(page_source) source = 'fragment=%s&output=soap12' % urllib.quote_plus(page_source)
os.environ['CONTENT_LENGTH'] = str(len(source)) stdout, stderr = Popen(self.validator_path,
os.environ['REQUEST_METHOD'] = 'POST' stdin=PIPE, stdout=PIPE, stderr=PIPE,
stdout, stdin, stderr = popen2.popen3(self.validator_path) close_fds=True,
stdin.write(source) env={"CONTENT_LENGTH": str(len(source)),
stdin.close() "REQUEST_METHOD": "POST"}).communicate(source)
while stdout.readline() != '\n': # Output is a set of headers then the XML content.
pass return self._parse_validation_results(
result = stdout.read() stdout.split('<?xml version="1.0" encoding="UTF-8"?>')[1])
return self._parse_validation_results(result)
class TidyValidator(object): class TidyValidator(object):
...@@ -498,9 +496,9 @@ class TidyValidator(object): ...@@ -498,9 +496,9 @@ class TidyValidator(object):
''' '''
retrun two list : a list of errors and an other for warnings retrun two list : a list of errors and an other for warnings
''' '''
stdout, stdin, stderr = popen2.popen3('%s -e -q -utf8' % self.validator_path) stdout, stderr = Popen('%s -e -q -utf8' % self.validator_path,
stdin.write(page_source) stdin=PIPE, stdout=PIPE, stderr=PIPE,
stdin.close() close_fds=True).communicate(page_source)
return self._parse_validation_results(stderr) return self._parse_validation_results(stderr)
......
...@@ -40,6 +40,11 @@ else: ...@@ -40,6 +40,11 @@ else:
from Products.ERP5Type.tests.backportUnittest import \ from Products.ERP5Type.tests.backportUnittest import \
expectedFailure as newSimulationExpectedFailure 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: class BusinessTemplateInfoBase:
...@@ -103,15 +108,12 @@ class BusinessTemplateInfoBase: ...@@ -103,15 +108,12 @@ class BusinessTemplateInfoBase:
def setUpActions(self): def setUpActions(self):
def parse(file_path): def parse(file_path):
db = DB(DemoStorage()) action_information = importXML(connection, file_path)
_connection = db.open()
action_information = importXML(_connection, file_path)
action_information.__repr__() action_information.__repr__()
for key, value in action_information.__dict__.iteritems(): for key, value in action_information.__dict__.iteritems():
if value not in (None, "") and key in ('action', 'condition') : if value not in (None, "") and key in ('action', 'condition') :
setattr(action_information, key, value.text) setattr(action_information, key, value.text)
actions = action_information.__dict__.copy() actions = action_information.__dict__.copy()
db.close()
return actions return actions
name = '%s/ActionTemplateItem/portal_types/' % self.getPrefix() name = '%s/ActionTemplateItem/portal_types/' % self.getPrefix()
......
...@@ -42,10 +42,6 @@ from hashlib import md5 ...@@ -42,10 +42,6 @@ from hashlib import md5
import time import time
from zope.interface import Interface from zope.interface import Interface
from zope.interface import implements from zope.interface import implements
_field_value_cache = {}
def purgeFieldValueCache():
_field_value_cache.clear()
class ICaptchaProvider(Interface): class ICaptchaProvider(Interface):
"""The CaptchaProvider interface provides a captcha generator.""" """The CaptchaProvider interface provides a captcha generator."""
......
...@@ -48,9 +48,38 @@ from Products.PageTemplates.Expressions import SecureModuleImporter ...@@ -48,9 +48,38 @@ from Products.PageTemplates.Expressions import SecureModuleImporter
from Products.ERP5Type.PsycoWrapper import psyco from Products.ERP5Type.PsycoWrapper import psyco
import sys import sys
_field_value_cache = {} class FieldValueCacheDict(dict):
def purgeFieldValueCache(): _last_sync = -1
_field_value_cache.clear()
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 # Patch the fiels methods to provide improved namespace handling
...@@ -343,7 +372,7 @@ def get_value(self, id, REQUEST=None, **kw): ...@@ -343,7 +372,7 @@ def get_value(self, id, REQUEST=None, **kw):
id) id)
try: try:
value = _field_value_cache[cache_id] value = field_value_cache[cache_id]
except KeyError: except KeyError:
# either returns non callable value (ex. "Title") # either returns non callable value (ex. "Title")
# or a FieldValue instance of appropriate class # or a FieldValue instance of appropriate class
...@@ -353,7 +382,7 @@ def get_value(self, id, REQUEST=None, **kw): ...@@ -353,7 +382,7 @@ def get_value(self, id, REQUEST=None, **kw):
# and caching sometimes break these field settings at initialization. # and caching sometimes break these field settings at initialization.
# As the result, we would see broken field editing screen in ZMI. # As the result, we would see broken field editing screen in ZMI.
if cacheable and self._p_oid: if cacheable and self._p_oid:
_field_value_cache[cache_id] = value field_value_cache[cache_id] = value
if callable(value): if callable(value):
return value(field, id, **kw) return value(field, id, **kw)
......
...@@ -52,6 +52,5 @@ class FieldValueCacheInteractor(Interactor): ...@@ -52,6 +52,5 @@ class FieldValueCacheInteractor(Interactor):
Interaction method (defined at the Interactor level). Interaction method (defined at the Interactor level).
Make sure all field value caches are purged Make sure all field value caches are purged
""" """
from Products.ERP5Form import Form, ProxyField from Products.ERP5Form.Form import field_value_cache
Form.purgeFieldValueCache() field_value_cache.clear()
ProxyField.purgeFieldValueCache()
...@@ -60,10 +60,6 @@ from thread import get_ident ...@@ -60,10 +60,6 @@ from thread import get_ident
_USE_ORIGINAL_GET_VALUE_MARKER = [] _USE_ORIGINAL_GET_VALUE_MARKER = []
_field_value_cache = {}
def purgeFieldValueCache():
_field_value_cache.clear()
class WidgetDelegatedMethod(Method): class WidgetDelegatedMethod(Method):
"""Method delegated to the proxied field's widget. """Method delegated to the proxied field's widget.
""" """
...@@ -740,14 +736,15 @@ class ProxyField(ZMIField): ...@@ -740,14 +736,15 @@ class ProxyField(ZMIField):
field._p_oid, field._p_oid,
id) id)
from Products.ERP5Form.Form import field_value_cache
try: try:
value = _field_value_cache[cache_id] value = field_value_cache[cache_id]
except KeyError: except KeyError:
# either returns non callable value (ex. "Title") # either returns non callable value (ex. "Title")
# or a FieldValue instance of appropriate class # or a FieldValue instance of appropriate class
value, cacheable = self.getFieldValue(field, id, **kw) value, cacheable = self.getFieldValue(field, id, **kw)
if cacheable: if cacheable:
_field_value_cache[cache_id] = value field_value_cache[cache_id] = value
if value is _USE_ORIGINAL_GET_VALUE_MARKER: if value is _USE_ORIGINAL_GET_VALUE_MARKER:
return proxy_field.get_value(id, **kw) return proxy_field.get_value(id, **kw)
......
...@@ -70,23 +70,23 @@ class TestFieldValueCache(ERP5TypeTestCase): ...@@ -70,23 +70,23 @@ class TestFieldValueCache(ERP5TypeTestCase):
# Get form value # Get form value
field = form.my_first_name field = form.my_first_name
id = 'title' id = 'title'
from Products.ERP5Form.ProxyField import _field_value_cache from Products.ERP5Form.Form import field_value_cache
cache_id = ('ProxyField.get_value', cache_id = ('ProxyField.get_value',
field._p_oid, field._p_oid,
field._p_oid, field._p_oid,
id) id)
# Make sure cache has field # 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 # 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 # Call manage_renameObject
form.manage_renameObject('my_first_name', 'my_first_name2') form.manage_renameObject('my_first_name', 'my_first_name2')
form.manage_renameObject('my_first_name2', 'my_first_name') form.manage_renameObject('my_first_name2', 'my_first_name')
# Make sure cache has no field # 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 # Render
form() form()
# Make sure cache has field # 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 # 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 ...@@ -46,7 +46,7 @@ from Products.Formulator.TALESField import TALESMethod
from Products.ERP5Type.Core.Folder import Folder from Products.ERP5Type.Core.Folder import Folder
from Products.ERP5Form.Form import ERP5Form 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.Form import getFieldValue
from Products.ERP5Form import Form from Products.ERP5Form import Form
from Products.ERP5Form import ProxyField from Products.ERP5Form import ProxyField
...@@ -110,6 +110,15 @@ class TestFloatField(ERP5TypeTestCase): ...@@ -110,6 +110,15 @@ class TestFloatField(ERP5TypeTestCase):
self.field.values['input_style'] = '-1,234.5' self.field.values['input_style'] = '-1,234.5'
self.field.values['precision'] = 0 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.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): def test_format_percent_style(self):
self.field.values['input_style'] = '-12.3%' self.field.values['input_style'] = '-12.3%'
...@@ -121,7 +130,7 @@ class TestFloatField(ERP5TypeTestCase): ...@@ -121,7 +130,7 @@ class TestFloatField(ERP5TypeTestCase):
# value is rounded # value is rounded
self.assertEquals('13', self.widget.format_value(self.field, 12.9)) 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.field.values['precision'] = 2
self.assertEquals('0.01', self.widget.format_value(self.field, 0.011)) self.assertEquals('0.01', self.widget.format_value(self.field, 0.011))
# value is rounded # value is rounded
...@@ -925,42 +934,50 @@ class TestFieldValueCache(ERP5TypeTestCase): ...@@ -925,42 +934,50 @@ class TestFieldValueCache(ERP5TypeTestCase):
self.assertEqual(False, value.value is field.values['external_validator']) self.assertEqual(False, value.value is field.values['external_validator'])
self.assertEqual(True, type(value.value) is Method) 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): def test_using_cache_or_not(self):
# check standard field in zodb # check standard field in zodb
# make sure that this will use cache. # 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.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 # check on-memory field
# make sure that this will not use cache. # 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.assertEqual(repr(self.root),
self.root.form.my_on_memory_tales_field.get_value('default')) self.root.form.my_on_memory_tales_field.get_value('default'))
self.assertEqual('123', self.assertEqual('123',
self.root.form.my_on_memory_field.get_value('default')) 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 # check proxy field
# make sure that this will use cache. # 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.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 # check proxy field with tales
# make sure that this will not use cache. # 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.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): def test_datetime_field(self):
purgeFieldValueCache() field_value_cache.clear()
# make sure that boundmethod must not be cached. # make sure that boundmethod must not be cached.
year_field = self.root.form.datetime_field.sub_form.get_field('year', include_disabled=1) 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) 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') year_field.get_value('items')
# See Formulator/StandardFields.py(line:174) # See Formulator/StandardFields.py(line:174)
...@@ -972,22 +989,22 @@ class TestFieldValueCache(ERP5TypeTestCase): ...@@ -972,22 +989,22 @@ class TestFieldValueCache(ERP5TypeTestCase):
self.root.form.datetime_field._p_oid, self.root.form.datetime_field._p_oid,
self.root.form.datetime_field._p_oid, self.root.form.datetime_field._p_oid,
'start_datetime' 'start_datetime'
) in Form._field_value_cache) ) in field_value_cache)
self.assertEqual(True, ('Form.get_value', self.assertEqual(True, ('Form.get_value',
self.root.form.datetime_field._p_oid, self.root.form.datetime_field._p_oid,
self.root.form.datetime_field._p_oid, self.root.form.datetime_field._p_oid,
'end_datetime' 'end_datetime'
) in Form._field_value_cache) ) in field_value_cache)
self.assertEqual(False, ('Form.get_value', self.assertEqual(False, ('Form.get_value',
year_field._p_oid, year_field._p_oid,
year_field._p_oid, year_field._p_oid,
'items' 'items'
) in Form._field_value_cache) ) in field_value_cache)
self.assertEqual(cache_size, len(Form._field_value_cache)) self.assertEqual(cache_size, len(field_value_cache))
year_field.get_value('size') year_field.get_value('size')
year_field.get_value('default') 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(): def makeDummyOid():
import time, random import time, random
......
...@@ -30,8 +30,7 @@ from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase ...@@ -30,8 +30,7 @@ from Products.ERP5Type.tests.ERP5TypeTestCase import ERP5TypeTestCase
from Products.Formulator.TALESField import TALESMethod from Products.Formulator.TALESField import TALESMethod
from Products.ERP5Type.Core.Folder import Folder from Products.ERP5Type.Core.Folder import Folder
from Products.ERP5Form.Form import ERP5Form from Products.ERP5Form.Form import ERP5Form
from Products.ERP5Form.ProxyField import purgeFieldValueCache from Products.ERP5Form.Form import field_value_cache
class TestProxify(ERP5TypeTestCase): class TestProxify(ERP5TypeTestCase):
...@@ -103,12 +102,12 @@ class TestProxify(ERP5TypeTestCase): ...@@ -103,12 +102,12 @@ class TestProxify(ERP5TypeTestCase):
self.assertEqual(field.is_delegated('description'), True) self.assertEqual(field.is_delegated('description'), True)
self.assertEqual(field.get_value('description'), '') 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 = self.base_view.my_string_field
template_field.values['description'] = 'Description' template_field.values['description'] = 'Description'
self.assertEqual(field.get_value('description'), 'Description') self.assertEqual(field.get_value('description'), 'Description')
purgeFieldValueCache() field_value_cache.clear()
# ListField # ListField
self.person_view.manage_addField('my_gender', 'Gender', 'ListField') self.person_view.manage_addField('my_gender', 'Gender', 'ListField')
...@@ -119,7 +118,7 @@ class TestProxify(ERP5TypeTestCase): ...@@ -119,7 +118,7 @@ class TestProxify(ERP5TypeTestCase):
self.assertEqual(field.is_delegated('items'), True) self.assertEqual(field.is_delegated('items'), True)
self.assertEqual(field.get_value('items'), [('Male', 'Male'), ('Female', 'Female')]) self.assertEqual(field.get_value('items'), [('Male', 'Male'), ('Female', 'Female')])
purgeFieldValueCache() field_value_cache.clear()
def test_multi_level_proxify(self): def test_multi_level_proxify(self):
...@@ -146,7 +145,7 @@ class TestProxify(ERP5TypeTestCase): ...@@ -146,7 +145,7 @@ class TestProxify(ERP5TypeTestCase):
self.assertEqual(field.has_value('scrap_variable'), 0) 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 = self.address_view.my_region
template_field.values['title'] = 'Region' template_field.values['title'] = 'Region'
self.assertEqual(field.get_value('title'), 'Region') self.assertEqual(field.get_value('title'), 'Region')
...@@ -192,7 +191,7 @@ class TestProxify(ERP5TypeTestCase): ...@@ -192,7 +191,7 @@ class TestProxify(ERP5TypeTestCase):
#Proxify First #Proxify First
self.address_view.proxifyField({'my_region':'Base_view.my_list_field'}) self.address_view.proxifyField({'my_region':'Base_view.my_list_field'})
self.person_view.proxifyField({'my_default_region':'Address_view.my_region'}) self.person_view.proxifyField({'my_default_region':'Address_view.my_region'})
purgeFieldValueCache() field_value_cache.clear()
#UnProxify #UnProxify
self.person_view.unProxifyField({'my_default_region':'on'}) self.person_view.unProxifyField({'my_default_region':'on'})
field = self.person_view.my_default_region field = self.person_view.my_default_region
...@@ -204,7 +203,7 @@ class TestProxify(ERP5TypeTestCase): ...@@ -204,7 +203,7 @@ class TestProxify(ERP5TypeTestCase):
#Test unproxify with old instance. #Test unproxify with old instance.
#Proxify First #Proxify First
self.person_view.proxifyField({'my_career_subordination_title':'Base_view.my_relation_string_field'}) self.person_view.proxifyField({'my_career_subordination_title':'Base_view.my_relation_string_field'})
purgeFieldValueCache() field_value_cache.clear()
#UnProxify #UnProxify
self.person_view.unProxifyField({'my_career_subordination_title':'on'}) self.person_view.unProxifyField({'my_career_subordination_title':'on'})
field = self.person_view.my_career_subordination_title 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 ...@@ -39,6 +39,7 @@ from Products.ERP5Type.patches import sqlvar
from Products.ERP5Type.patches import CMFCatalogAware from Products.ERP5Type.patches import CMFCatalogAware
from Products.ERP5Type.patches import ProductContext from Products.ERP5Type.patches import ProductContext
from Products.ERP5Type.patches import PropertiedUser from Products.ERP5Type.patches import PropertiedUser
from Products.ERP5Type.patches import PluggableAuthService
from Products.ERP5Type.patches import States from Products.ERP5Type.patches import States
from Products.ERP5Type.patches import FSZSQLMethod from Products.ERP5Type.patches import FSZSQLMethod
from Products.ERP5Type.patches import ActionInformation from Products.ERP5Type.patches import ActionInformation
......
...@@ -301,8 +301,8 @@ class ComponentMixin(PropertyRecordableMixin, Base): ...@@ -301,8 +301,8 @@ class ComponentMixin(PropertyRecordableMixin, Base):
try: try:
from pylint.lint import Run from pylint.lint import Run
from pylint.reporters.text import TextReporter from pylint.reporters.text import TextReporter
except ImportError: except ImportError, error:
return ['F: Cannot check Source Code: Pylint is not available'], [] return ['F: Cannot check Source Code: Pylint is not available (%s)' % error], []
import cStringIO import cStringIO
import tempfile 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( ...@@ -189,6 +189,7 @@ ModuleSecurityInfo('os.path').declarePublic(
# Alias modules - only applied to restricted python. # Alias modules - only applied to restricted python.
MNAME_MAP = { MNAME_MAP = {
'zipfile': 'Products.ERP5Type.ZipFile', 'zipfile': 'Products.ERP5Type.ZipFile',
'calendar': 'Products.ERP5Type.Calendar',
} }
for alias, real in MNAME_MAP.items(): for alias, real in MNAME_MAP.items():
assert '.' not in alias, alias # TODO: support this assert '.' not in alias, alias # TODO: support this
......
...@@ -294,12 +294,7 @@ class SearchKey(object): ...@@ -294,12 +294,7 @@ class SearchKey(object):
if logical_operator is None: if logical_operator is None:
logical_operator = default_logical_operator logical_operator = default_logical_operator
operator_value_dict = {} operator_value_dict = {}
if None in search_value: if comparison_operator is None:
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 issubclass(reference_class, basestring): if issubclass(reference_class, basestring):
if get_operator_from_value: if get_operator_from_value:
parsed = True parsed = True
......
...@@ -264,7 +264,9 @@ class AdvancedSearchTextParser(lexer): ...@@ -264,7 +264,9 @@ class AdvancedSearchTextParser(lexer):
def p_value(self, p): def p_value(self, p):
'''value : OPERATOR string '''value : OPERATOR string
| string''' | OPERATOR NULL
| string
| NULL'''
if len(p) == 2: if len(p) == 2:
p[0] = ValueNode(p[1]) p[0] = ValueNode(p[1])
else: else:
......
...@@ -116,10 +116,7 @@ if __name__ == '__main__': ...@@ -116,10 +116,7 @@ if __name__ == '__main__':
return (self.column, self.value, self.comparison_operator) return (self.column, self.value, self.comparison_operator)
def __repr__(self): def __repr__(self):
value = self.value return 'Query(%r, %r, %r)' % (self.column, self.value, self.comparison_operator)
if len(value) == 1:
value = value[0]
return 'Query(%r, %r, %r)' % (self.column, value, self.comparison_operator)
def __eq__(self, other): def __eq__(self, other):
if isinstance(other, Query): if isinstance(other, Query):
......
from SearchTextParser import parse, isAdvancedSearchText from SearchTextParser import parse, isAdvancedSearchText
def dequote(value): def dequote(value):
assert isinstance(value, basestring), value if isinstance(value, basestring) and len(value) >= 2 and \
if len(value) >= 2 and value[0] == value[-1] == '"' and value[-2] != '\\': value[0] == value[-1] == '"' and value[-2] != '\\':
escaped = False escaped = False
value_list = [] value_list = []
append = value_list.append append = value_list.append
......
...@@ -82,7 +82,9 @@ class lexer(object): ...@@ -82,7 +82,9 @@ class lexer(object):
'WORD', 'WORD',
'OPERATOR', 'OPERATOR',
'LEFT_PARENTHESE', 'LEFT_PARENTHESE',
'RIGHT_PARENTHESE') 'RIGHT_PARENTHESE',
'NULL',
)
t_ignore = ' ' t_ignore = ' '
...@@ -123,6 +125,11 @@ class lexer(object): ...@@ -123,6 +125,11 @@ class lexer(object):
r'[^><= :\(\)"][^ :\(\)"]*' r'[^><= :\(\)"][^ :\(\)"]*'
return t return t
def t_NULL(self, t):
r'NULL'
t.value = None
return t
def parse(self, *args, **kw): def parse(self, *args, **kw):
kw['lexer'] = self kw['lexer'] = self
return self.parser.parse(*args, **kw) 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