Commit 31dd57fe authored by Jérome Perrin's avatar Jérome Perrin

CodingStyle: implement a basic ERP5Form.checkConsistency

Checking some conventions for form, dialog and reports based on
https://www.erp5.com/documentation/developer/guideline/programming/
and https://www.erp5.com/documentation/developer/guideline/module/

For now we implement only a few checks, we will extend later.
parent 2d2f2b57
...@@ -27,6 +27,7 @@ ...@@ -27,6 +27,7 @@
# #
############################################################################## ##############################################################################
import hashlib import hashlib
import re
from copy import deepcopy from copy import deepcopy
...@@ -38,6 +39,8 @@ from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate ...@@ -38,6 +39,8 @@ from Products.PageTemplates.ZopePageTemplate import ZopePageTemplate
from Products.CMFCore.utils import _checkPermission, getToolByName from Products.CMFCore.utils import _checkPermission, getToolByName
from Products.CMFCore.exceptions import AccessControl_Unauthorized from Products.CMFCore.exceptions import AccessControl_Unauthorized
from Products.ERP5Type import PropertySheet, Permissions from Products.ERP5Type import PropertySheet, Permissions
from Products.ERP5Type import CodingStyle
from Products.ERP5Type.ObjectMessage import ObjectMessage
from urllib import quote from urllib import quote
from Products.ERP5Type.Globals import DTMLFile, get_request from Products.ERP5Type.Globals import DTMLFile, get_request
...@@ -1313,6 +1316,71 @@ class ERP5Form(Base, ZMIForm, ZopePageTemplate): ...@@ -1313,6 +1316,71 @@ class ERP5Form(Base, ZMIForm, ZopePageTemplate):
return str((self.pt, self.name, self.action, self.update_action, return str((self.pt, self.name, self.action, self.update_action,
self.encoding, self.stored_encoding, self.enctype)) self.encoding, self.stored_encoding, self.enctype))
def _checkConsistency(self, fixit=0, filter=None, **kw):
message_list = CodingStyle.checkConsistency(self, fixit=fixit, source_code=self.asXML())
object_relative_url = '/'.join(self.getPhysicalPath())[len(self.getPortalObject().getPath()):]
def addMessage(rule_reference, message):
"""Adds a message to the list of problems.
* rule_reference: reference of the web page on erp5.com defining the rule
* message: the message
"""
message_list.append(
ObjectMessage(
object_relative_url=object_relative_url,
message="{rule_reference}: {message}".format(
rule_reference=rule_reference,
message=message)))
if self.pt:
prefix, method = self.getId().split('_', 1)
del prefix
if self.pt in ('form_view', 'form_list', 'form_dialog', 'report_view'):
if self.getId() not in CodingStyle.ignored_skin_id_set:
# For ignored_skin_id_set, we only ignore naming of the form itself.
if not method.startswith('view'):
addMessage(
'erp5-Guideline.Form.Name.Uses.Lowercase.View.After.Portal.Type',
# note: ${portal_type} is *not* a translation substitution
'Form name must follow ${portal_type}_view.* naming')
if self.pt == 'form_dialog' and not method.endswith('Dialog'):
addMessage(
'erp5-Guideline.Form.Report.Dialog.Is.Postfixed.With.Dialog',
'Dialog form name must follow ${portal_type}_view.*Dialog naming')
if self.pt == 'report_view' and not method.endswith('Report'):
addMessage(
'erp5-Guideline.Report.Name.Uses.Portal.Type.Followed.By.View.Report.Name.And.Report',
'Report form name must follow ${portal_type}_view.*Report naming')
is_field_library = self.getId().endswith('FieldLibrary')
if self.pt == 'form_view' and not is_field_library:
translated_workflow_state_field_re = re.compile('my_translated_.*state_title$')
def isTranslatedWorkflowStateField(f):
return translated_workflow_state_field_re.match(f.getId()) and f.getId() not in (
# exception for some properties containing "state" in their names
'my_initial_implementation_state', )
not_translated_workflow_state_field_re = re.compile('my_(?!translated_).*state(_title|)$')
for group_name in self.get_groups():
field_list = self.get_fields_in_group(group_name)
for index, field in enumerate(field_list):
if isTranslatedWorkflowStateField(field):
is_in_right_group = 'right' in group_name
# workflow states fields must be the last ones, so we check
# that this field or all the one below match the
# my_translated_${state_variable}_title regex
all_bottom_fields_are_workflow_state_fields = {True} == {
isTranslatedWorkflowStateField(f) for f in field_list[index:]}
if not (all_bottom_fields_are_workflow_state_fields and is_in_right_group):
addMessage(
'erp5-Guideline.Place.Simulation.And.Validation.Fields.In.Bottom.Of.Right.Group',
'Workflow state fields must be at the bottom right')
if not_translated_workflow_state_field_re.match(field.getId()):
addMessage(
'erp5-Guideline.Use.Correct.Names.For.Simulation.And.Validation.Titles',
'Workflow state fields should be named my_translated_${state_variable}_title')
return message_list
# utility function # utility function
def get_field_meta_type_and_proxy_flag(field): def get_field_meta_type_and_proxy_flag(field):
if field.meta_type=='ProxyField': if field.meta_type=='ProxyField':
......
...@@ -208,7 +208,7 @@ def checkConsistency(self, fixit=0, source_code=None): ...@@ -208,7 +208,7 @@ def checkConsistency(self, fixit=0, source_code=None):
if prefix not in getSkinPrefixList(self): if prefix not in getSkinPrefixList(self):
message_list.append( message_list.append(
ObjectMessage(object_relative_url='/'.join(self.getPhysicalPath())[portal_path_len:], ObjectMessage(object_relative_url='/'.join(self.getPhysicalPath())[portal_path_len:],
message='Wrong prefix %s for python script %s' % (prefix, document_id))) message='Wrong prefix %s for %s %s' % (prefix, self.meta_type, document_id)))
# Make sure source code does not contain legacy callables # Make sure source code does not contain legacy callables
if source_code: if source_code:
......
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