Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
erp5
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Carlos Ramos Carreño
erp5
Commits
9f1ce1ba
Commit
9f1ce1ba
authored
Aug 03, 2020
by
Arnaud Fontaine
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
WIP
parent
75309541
Changes
5
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
2039 additions
and
823 deletions
+2039
-823
product/ERP5/bootstrap/erp5_core/ModuleComponentTemplateItem/portal_components/module.erp5.Form.py
...mponentTemplateItem/portal_components/module.erp5.Form.py
+1345
-0
product/ERP5/bootstrap/erp5_core/ModuleComponentTemplateItem/portal_components/module.erp5.Form.xml
...ponentTemplateItem/portal_components/module.erp5.Form.xml
+691
-0
product/ERP5/bootstrap/erp5_core/bt/template_module_component_id_list
.../bootstrap/erp5_core/bt/template_module_component_id_list
+1
-0
product/ERP5Form/FSForm.py
product/ERP5Form/FSForm.py
+0
-63
product/ERP5Form/Form.py
product/ERP5Form/Form.py
+2
-760
No files found.
product/ERP5/bootstrap/erp5_core/ModuleComponentTemplateItem/portal_components/module.erp5.Form.py
0 → 100644
View file @
9f1ce1ba
# -*- coding: utf-8 -*-
#############################################################################
#
# Copyright (c) 2002 Nexedi SARL and Contributors. All Rights Reserved.
# Jean-Paul Smets-Solanes <jp@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.
#
##############################################################################
import
hashlib
from
copy
import
deepcopy
from
Products.Formulator.Form
import
BasicForm
,
ZMIForm
from
Products.Formulator.Errors
import
FormValidationError
,
ValidationError
from
Products.Formulator.DummyField
import
fields
from
Products.Formulator.XMLToForm
import
XMLToForm
from
Products.PageTemplates.ZopePageTemplate
import
ZopePageTemplate
from
Products.CMFCore.utils
import
_checkPermission
,
getToolByName
from
Products.CMFCore.exceptions
import
AccessControl_Unauthorized
from
Products.ERP5Type
import
PropertySheet
,
Permissions
from
urllib
import
quote
from
Products.ERP5Type.Globals
import
DTMLFile
,
get_request
from
AccessControl
import
Unauthorized
,
ClassSecurityInfo
from
DateTime
import
DateTime
from
ZODB.POSException
import
ConflictError
from
zExceptions
import
Redirect
from
Acquisition
import
aq_base
from
Products.PageTemplates.Expressions
import
SecureModuleImporter
from
zExceptions
import
Forbidden
from
Products.ERP5Type.PsycoWrapper
import
psyco
from
Products.ERP5Type.Base
import
Base
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
super
(
FieldValueCacheDict
,
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
from
Products.Formulator.Field
import
Field
from
Products.Formulator.MethodField
import
Method
,
BoundMethod
from
Products.Formulator.TALESField
import
TALESMethod
from
zLOG
import
LOG
,
PROBLEM
def
isCacheable
(
value
):
value
=
aq_base
(
value
)
if
type
(
value
)
is
BoundMethod
:
return
False
jar
=
getattr
(
value
,
'_p_jar'
,
None
)
if
jar
is
not
None
:
return
False
dic
=
getattr
(
value
,
'__dict__'
,
None
)
if
dic
is
not
None
:
for
i
in
dic
.
values
():
jar
=
getattr
(
i
,
'_p_jar'
,
None
)
if
jar
is
not
None
:
return
False
return
True
def
copyMethod
(
value
):
if
type
(
aq_base
(
value
))
is
Method
:
value
=
Method
(
value
.
method_name
)
elif
type
(
aq_base
(
value
))
is
TALESMethod
:
value
=
TALESMethod
(
value
.
_text
)
return
value
def
getFieldDict
(
field
,
value_type
):
result
=
{}
if
field
.
meta_type
==
'ProxyField'
:
if
value_type
==
'values'
:
get_method
=
getattr
(
field
,
'get_recursive_orig_value'
)
elif
value_type
==
'tales'
:
get_method
=
getattr
(
field
,
'get_recursive_tales'
)
else
:
raise
ValueError
,
'value_type must be values or tales'
template_field
=
field
.
getRecursiveTemplateField
()
for
ui_field_id
in
template_field
.
form
.
fields
.
keys
():
result
[
ui_field_id
]
=
get_method
(
ui_field_id
)
else
:
if
value_type
==
'values'
:
get_method
=
getattr
(
field
,
'get_orig_value'
)
elif
value_type
==
'tales'
:
get_method
=
getattr
(
field
,
'get_tales'
)
else
:
raise
ValueError
,
'value_type must be values or tales'
for
ui_field_id
in
field
.
form
.
fields
.
keys
():
result
[
ui_field_id
]
=
get_method
(
ui_field_id
)
return
result
class
StaticValue
:
"""
Encapsulated a static value in a class
(quite heavy, would be faster to store the
value as is)
"""
def
__init__
(
self
,
value
):
self
.
value
=
value
def
__call__
(
self
,
field
,
id
,
**
kw
):
return
self
.
returnValue
(
field
,
id
,
self
.
value
)
def
returnValue
(
self
,
field
,
id
,
value
):
# if normal value is a callable itself, wrap it
if
callable
(
value
):
value
=
value
.
__of__
(
field
)
#value=value() # Mising call ??? XXX Make sure compatible with listbox methods
if
id
==
'default'
:
# We make sure we convert values to empty strings
# for most fields (so that we do not get a 'value'
# message on screen)
# This can be overriden by using TALES in the field
if
value
is
None
:
value
=
''
return
value
class
TALESValue
(
StaticValue
):
def
__init__
(
self
,
tales_expr
):
self
.
tales_expr
=
tales_expr
def
__call__
(
self
,
field
,
id
,
**
kw
):
REQUEST
=
kw
.
get
(
'REQUEST'
,
get_request
())
if
REQUEST
is
not
None
:
# Proxyfield stores the "real" field in the request. Look if the
# corresponding field exists in request, and use it as field in the
# TALES context
field
=
REQUEST
.
get
(
'field__proxyfield_%s_%s_%s'
%
(
field
.
id
,
field
.
_p_oid
,
id
),
field
)
kw
[
'field'
]
=
field
form
=
field
.
aq_parent
# XXX (JPS) form for default is wrong apparently in listbox - double check
obj
=
getattr
(
form
,
'aq_parent'
,
None
)
if
obj
is
not
None
:
container
=
obj
.
aq_inner
.
aq_parent
else
:
container
=
None
kw
[
'form'
]
=
form
kw
[
'request'
]
=
REQUEST
kw
[
'here'
]
=
obj
kw
[
'context'
]
=
obj
kw
[
'modules'
]
=
SecureModuleImporter
kw
[
'container'
]
=
container
try
:
kw
[
'preferences'
]
=
obj
.
getPortalObject
().
portal_preferences
except
AttributeError
:
LOG
(
'ERP5Form'
,
PROBLEM
,
'portal_preferences not put in TALES context (not installed?)'
)
# This allows to pass some pointer to the local object
# through the REQUEST parameter. Not very clean.
# Used by ListBox to render different items in a list
if
kw
.
get
(
'cell'
)
is
None
:
request
=
kw
.
get
(
'REQUEST'
)
if
request
is
not
None
:
if
getattr
(
request
,
'cell'
,
None
)
is
not
None
:
kw
[
'cell'
]
=
request
.
cell
else
:
kw
[
'cell'
]
=
request
if
'cell_index'
not
in
kw
and
\
getattr
(
request
,
'cell_index'
,
None
)
is
not
None
:
kw
[
'cell_index'
]
=
request
.
cell_index
elif
getattr
(
REQUEST
,
'cell'
,
None
)
is
not
None
:
kw
[
'cell'
]
=
REQUEST
.
cell
if
'cell_index'
not
in
kw
and
\
getattr
(
REQUEST
,
'cell_index'
,
None
)
is
not
None
:
kw
[
'cell_index'
]
=
REQUEST
.
cell_index
# on Zope 2.12, only path expressions can access the CONTEXTS name
# but ERP5 has many python expressions that try to access CONTEXTS, so
# we try to keep backward compatibility
if
self
.
tales_expr
.
_text
.
startswith
(
"python:"
):
kw
[
'CONTEXTS'
]
=
kw
try
:
value
=
self
.
tales_expr
.
__of__
(
field
)(
**
kw
)
except
(
ConflictError
,
RuntimeError
,
Redirect
):
raise
except
:
# We add this safety exception to make sure we always get
# something reasonable rather than generate plenty of errors
LOG
(
'ERP5Form'
,
PROBLEM
,
'Field.get_value %r [%s], exception on tales_expr: '
%
(
field
,
id
),
error
=
True
)
# field may be ProxyField
# here we avoid calling field.get_recursive_orig_value
# on all fields because it can be acquired from another
# field in context. ie, from a listbox field.
# So, test condition on meta_type attribute to avoid
# non desirable side effects.
if
field
.
meta_type
==
'ProxyField'
:
value
=
field
.
get_recursive_orig_value
(
id
)
else
:
value
=
field
.
get_orig_value
(
id
)
return
self
.
returnValue
(
field
,
id
,
value
)
class
OverrideValue
(
StaticValue
):
def
__init__
(
self
,
override
):
self
.
override
=
override
def
__call__
(
self
,
field
,
id
,
**
kw
):
return
self
.
returnValue
(
field
,
id
,
self
.
override
.
__of__
(
field
)())
class
DefaultValue
(
StaticValue
):
def
__init__
(
self
,
field_id
,
value
):
self
.
key
=
field_id
.
split
(
'_'
,
1
)[
1
]
self
.
value
=
value
def
__call__
(
self
,
field
,
id
,
**
kw
):
REQUEST
=
kw
.
get
(
'REQUEST'
,
None
)
or
get_request
()
try
:
form
=
field
.
aq_parent
ob
=
REQUEST
.
get
(
'cell'
,
getattr
(
form
,
'aq_parent'
,
None
))
value
=
self
.
value
try
:
if
value
not
in
(
None
,
''
):
# If a default value is defined on the field, it has precedence
value
=
ob
.
getProperty
(
self
.
key
,
d
=
value
)
else
:
# else we should give a chance to the accessor to provide
# a default value (including None)
value
=
ob
.
getProperty
(
self
.
key
)
except
Unauthorized
:
value
=
ob
.
getProperty
(
self
.
key
,
d
=
value
,
checked_permission
=
'View'
)
if
REQUEST
is
not
None
:
REQUEST
.
set
(
'read_only_%s'
%
self
.
key
,
1
)
except
(
KeyError
,
AttributeError
):
value
=
None
return
self
.
returnValue
(
field
,
id
,
value
)
class
DefaultCheckBoxValue
(
DefaultValue
):
def
__call__
(
self
,
field
,
id
,
**
kw
):
try
:
form
=
field
.
aq_parent
ob
=
getattr
(
form
,
'aq_parent'
,
None
)
value
=
self
.
value
try
:
value
=
ob
.
getProperty
(
self
.
key
)
except
Unauthorized
:
value
=
ob
.
getProperty
(
self
.
key
,
d
=
value
,
checked_permission
=
'View'
)
REQUEST
=
kw
.
get
(
'REQUEST'
,
get_request
())
if
REQUEST
is
not
None
:
REQUEST
.
set
(
'read_only_%s'
%
self
.
key
,
1
)
except
(
KeyError
,
AttributeError
):
value
=
None
return
self
.
returnValue
(
field
,
id
,
value
)
class
EditableValue
(
StaticValue
):
def
__call__
(
self
,
field
,
id
,
**
kw
):
# By default, pages are editable and
# fields are editable if they are set to editable mode
# However, if the REQUEST defines editable_mode to 0
# then all fields become read only.
# This is useful to render ERP5 content as in a web site (ECommerce)
# editable_mode should be set for example by the page template
# which defines the current layout
REQUEST
=
kw
.
get
(
'REQUEST'
,
get_request
())
if
REQUEST
is
not
None
:
if
not
REQUEST
.
get
(
'editable_mode'
,
1
):
return
0
return
self
.
value
def
getFieldValue
(
self
,
field
,
id
,
**
kw
):
"""
Return a callable expression and cacheable boolean flag
"""
tales_expr
=
self
.
tales
.
get
(
id
,
""
)
if
tales_expr
:
# TALESMethod is persistent object, so that we cannot cache original one.
# Becase if connection which original talesmethod uses is closed,
# RuntimeError must occurs in __setstate__.
tales_expr
=
copyMethod
(
tales_expr
)
return
TALESValue
(
tales_expr
),
isCacheable
(
tales_expr
)
override
=
self
.
overrides
.
get
(
id
,
""
)
if
override
:
override
=
copyMethod
(
override
)
return
OverrideValue
(
override
),
isCacheable
(
override
)
# Get a normal value.
value
=
self
.
get_orig_value
(
id
)
value
=
copyMethod
(
value
)
cacheable
=
isCacheable
(
value
)
field_id
=
field
.
id
if
id
==
'default'
and
(
field_id
.
startswith
(
'my_'
)
or
field_id
.
startswith
(
'listbox_'
)):
if
field
.
meta_type
==
'ProxyField'
and
\
field
.
getRecursiveTemplateField
().
meta_type
==
'CheckBoxField'
or
\
self
.
meta_type
==
'CheckBoxField'
:
return
DefaultCheckBoxValue
(
field_id
,
value
),
cacheable
return
DefaultValue
(
field_id
,
value
),
cacheable
# For the 'editable' value, we try to get a default value
if
id
==
'editable'
:
return
EditableValue
(
value
),
cacheable
# Return default value in callable mode
if
callable
(
value
):
return
StaticValue
(
value
),
cacheable
# Return default value in non callable mode
return_value
=
StaticValue
(
value
)(
field
,
id
,
**
kw
)
return
return_value
,
isCacheable
(
return_value
)
def
get_value
(
self
,
id
,
REQUEST
=
None
,
**
kw
):
if
REQUEST
is
None
:
REQUEST
=
get_request
()
if
REQUEST
is
not
None
:
field
=
REQUEST
.
get
(
'field__proxyfield_%s_%s_%s'
%
(
self
.
id
,
self
.
_p_oid
,
id
),
self
)
else
:
field
=
self
cache_id
=
(
'Form.get_value'
,
self
.
_p_oid
,
field
.
_p_oid
,
id
)
try
:
value
=
field_value_cache
[
cache_id
]
except
KeyError
:
# either returns non callable value (ex. "Title")
# or a FieldValue instance of appropriate class
value
,
cacheable
=
getFieldValue
(
self
,
field
,
id
,
**
kw
)
# Do not cache if the field is not stored in zodb,
# because such field must be used for editing field in ZMI
# 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
if
callable
(
value
):
return
value
(
field
,
id
,
REQUEST
=
REQUEST
,
**
kw
)
return
value
psyco
.
bind
(
get_value
)
def
om_icons
(
self
):
"""Return a list of icon URLs to be displayed by an ObjectManager"""
icons
=
({
'path'
:
self
.
icon
,
'alt'
:
self
.
meta_type
,
'title'
:
self
.
meta_type
},)
return
icons
def
_get_default
(
self
,
key
,
value
,
REQUEST
):
if
value
is
not
None
:
return
value
try
:
value
=
self
.
_get_user_input_value
(
key
,
REQUEST
)
except
(
KeyError
,
AttributeError
):
# fall back on default
return
self
.
get_value
(
'default'
,
REQUEST
=
REQUEST
)
# It was missing on Formulator
# if we enter a string value while the field expects unicode,
# convert to unicode first
# this solves a problem when re-rendering a sticky form with
# values from request
if
(
self
.
has_value
(
'unicode'
)
and
self
.
get_value
(
'unicode'
)
and
type
(
value
)
==
type
(
''
)):
return
unicode
(
value
,
self
.
get_form_encoding
())
else
:
return
value
# Dynamic Patch
Field
.
get_value
=
get_value
Field
.
_get_default
=
_get_default
Field
.
om_icons
=
om_icons
# Constructors
manage_addForm
=
DTMLFile
(
"dtml/form_add"
,
globals
())
def
addERP5Form
(
self
,
id
,
title
=
""
,
REQUEST
=
None
):
"""Add form to folder.
id -- the id of the new form to add
title -- the title of the form to add
Result -- empty string
"""
# add actual object
type_info
=
self
.
getPortalObject
().
portal_types
.
getTypeInfo
(
'ERP5 Form'
)
type_info
.
constructInstance
(
container
=
self
,
id
=
id
,
title
=
title
)
# respond to the add_and_edit button if necessary
add_and_edit
(
self
,
id
,
REQUEST
)
return
''
def
add_and_edit
(
self
,
id
,
REQUEST
):
"""Helper method to point to the object's management screen if
'Add and Edit' button is pressed.
id -- id of the object we just added
"""
if
REQUEST
is
None
:
return
try
:
u
=
self
.
DestinationURL
()
except
AttributeError
:
u
=
REQUEST
[
'URL1'
]
if
REQUEST
[
'submit'
]
==
" Add and Edit "
:
u
=
"%s/%s"
%
(
u
,
quote
(
id
))
REQUEST
.
RESPONSE
.
redirect
(
u
+
'/manage_main'
)
def
initializeForm
(
field_registry
,
form_class
=
None
):
"""Sets up ZMIForm with fields from field_registry.
"""
if
form_class
is
None
:
form_class
=
ERP5Form
meta_types
=
[]
for
meta_type
,
field
in
field_registry
.
get_field_classes
().
items
():
# don't set up in form if this is a field for internal use only
if
field
.
internal_field
:
continue
# set up individual add dictionaries for meta_types
dict
=
{
'name'
:
field
.
meta_type
,
'permission'
:
'Add Formulator Fields'
,
'action'
:
'manage_addProduct/Formulator/manage_add%sForm'
%
meta_type
}
meta_types
.
append
(
dict
)
# set up add method
setattr
(
form_class
,
'manage_add%sForm'
%
meta_type
,
DTMLFile
(
'dtml/fieldAdd'
,
globals
(),
fieldname
=
meta_type
))
# set up meta_types that can be added to form
form_class
.
_meta_types
=
tuple
(
meta_types
)
# set up settings form
form_class
.
settings_form
.
_realize_fields
()
# Special Settings
def
create_settings_form
():
"""Create settings form for ZMIForm.
"""
form
=
BasicForm
(
'manage_settings'
)
title
=
fields
.
StringField
(
'title'
,
title
=
"Title"
,
required
=
0
,
default
=
""
)
description
=
fields
.
TextAreaField
(
'description'
,
title
=
"Description"
,
required
=
0
,
default
=
""
)
row_length
=
fields
.
IntegerField
(
'row_length'
,
title
=
'Number of groups in row (in order tab)'
,
required
=
1
,
default
=
4
)
name
=
fields
.
StringField
(
'name'
,
title
=
"Form name"
,
required
=
0
,
default
=
""
)
pt
=
fields
.
StringField
(
'pt'
,
title
=
"Page Template"
,
required
=
0
,
default
=
""
)
action
=
fields
.
StringField
(
'action'
,
title
=
'Form action'
,
required
=
0
,
default
=
""
)
action_title
=
fields
.
StringField
(
'action_title'
,
title
=
"Action Title"
,
required
=
0
,
default
=
""
)
update_action
=
fields
.
StringField
(
'update_action'
,
title
=
'Form update action'
,
required
=
0
,
default
=
""
)
update_action_title
=
fields
.
StringField
(
'update_action_title'
,
title
=
"Update Action Title"
,
required
=
0
,
default
=
""
)
method
=
fields
.
ListField
(
'method'
,
title
=
'Form method'
,
items
=
[(
'POST'
,
'POST'
),
(
'GET'
,
'GET'
)],
required
=
1
,
size
=
1
,
default
=
'POST'
)
enctype
=
fields
.
ListField
(
'enctype'
,
title
=
'Form enctype'
,
items
=
[(
'No enctype'
,
""
),
(
'application/x-www-form-urlencoded'
,
'application/x-www-form-urlencoded'
),
(
'multipart/form-data'
,
'multipart/form-data'
)],
required
=
0
,
size
=
1
,
default
=
None
)
encoding
=
fields
.
StringField
(
'encoding'
,
title
=
'Encoding of pages the form is in'
,
default
=
"UTF-8"
,
required
=
1
)
stored_encoding
=
fields
.
StringField
(
'stored_encoding'
,
title
=
'Encoding of form properties'
,
default
=
'UTF-8'
,
required
=
1
)
unicode_mode
=
fields
.
CheckBoxField
(
'unicode_mode'
,
title
=
'Form properties are unicode'
,
default
=
0
,
required
=
0
)
edit_order
=
fields
.
LinesField
(
'edit_order'
,
title
=
'Setters for these properties should be'
'<br /> called by edit() in the defined order'
)
form
.
add_fields
([
title
,
description
,
row_length
,
name
,
pt
,
action
,
action_title
,
update_action
,
update_action_title
,
method
,
enctype
,
encoding
,
stored_encoding
,
unicode_mode
,
edit_order
])
return
form
from
OFS.Cache
import
filterCacheTab
class
ERP5Form
(
Base
,
ZMIForm
,
ZopePageTemplate
):
"""
A Formulator form with a built-in rendering parameter based
on page templates or DTML.
"""
meta_type
=
"ERP5 Form"
portal_type
=
"ERP5 Form"
icon
=
"www/Form.png"
# Declarative Security
security
=
ClassSecurityInfo
()
# Tabs in ZMI
manage_options
=
(
ZMIForm
.
manage_options
[:
5
]
+
({
'label'
:
'Proxify'
,
'action'
:
'formProxify'
},
{
'label'
:
'UnProxify'
,
'action'
:
'formUnProxify'
},
{
'label'
:
'RelatedProxy'
,
'action'
:
'formShowRelatedProxyFields'
},
{
'label'
:
'Cache'
,
'action'
:
'ZCacheable_manage'
,
'filter'
:
filterCacheTab
,
'help'
:
(
'OFSP'
,
'Cacheable-properties.stx'
)}
)
+
ZMIForm
.
manage_options
[
5
:])
# Declarative properties
property_sheets
=
(
PropertySheet
.
Base
,
PropertySheet
.
SimpleItem
,
PropertySheet
.
Folder
,
PropertySheet
.
CategoryCore
)
# Constructors
constructors
=
(
manage_addForm
,
addERP5Form
)
# This is a patched dtml formOrder
security
.
declareProtected
(
'View management screens'
,
'formOrder'
)
formOrder
=
DTMLFile
(
'dtml/formOrder'
,
globals
())
# Proxify form
security
.
declareProtected
(
'View management screens'
,
'formProxify'
)
formProxify
=
DTMLFile
(
'dtml/formProxify'
,
globals
())
# Proxify form
security
.
declareProtected
(
'View management screens'
,
'formUnProxify'
)
formUnProxify
=
DTMLFile
(
'dtml/formUnProxify'
,
globals
())
# Related Proxy Fields
security
.
declareProtected
(
'View management screens'
,
'formShowRelatedProxyFields'
)
formShowRelatedProxyFields
=
DTMLFile
(
'dtml/formShowRelatedProxyFields'
,
globals
())
# Default Attributes
pt
=
'form_view'
action_title
=
''
update_action
=
''
update_action_title
=
''
edit_order
=
[]
# Special Settings
settings_form
=
create_settings_form
()
manage_main
=
ZMIForm
.
manage_main
objectIds
=
ZMIForm
.
objectIds
objectItems
=
ZMIForm
.
objectItems
objectValues
=
ZMIForm
.
objectValues
# If content_type is not text/html ZopePageTemplate will check that the
# source is well formed XML, but this does not really applies to Forms,
# they don't have source. By setting content_type here we make sure we
# don't get ERP5Type's Base default content_type.
content_type
=
ZopePageTemplate
.
content_type
def
__init__
(
self
,
id
,
title
=
''
,
unicode_mode
=
0
,
encoding
=
'UTF-8'
,
stored_encoding
=
'UTF-8'
):
"""Initialize form.
id -- id of form
title -- the title of the form
"""
ZMIForm
.
inheritedAttribute
(
'__init__'
)(
self
,
""
,
"POST"
,
""
,
id
,
encoding
,
stored_encoding
,
unicode_mode
)
self
.
id
=
id
self
.
title
=
title
self
.
row_length
=
4
self
.
group_list
=
[
"left"
,
"right"
,
"center"
,
"bottom"
,
"hidden"
]
groups
=
{}
for
group
in
self
.
group_list
:
groups
[
group
]
=
[]
self
.
groups
=
groups
# Proxy method to PageTemplate
def
__call__
(
self
,
*
args
,
**
kwargs
):
# Security
#
# The minimal action consists in checking that
# we have View permission on the current object
# before rendering a form. Otherwise, object with
# AccessContentInformation can be viewed by invoking
# a form directly.
#
# What would be better is to prevent calling certain
# forms to render objects. This can not be done
# through actions since we are using sometimes forms
# to render the results of a report dialog form.
# An a appropriate solutions could consist in adding
# a permission field to the form. Another solutions
# is the use of REFERER in the rendering process.
#
# Both solutions are not perfect if the goal is, for
# example, to prevent displaying private information of
# staff. The only real solution is to use a special
# permission (ex. AccessPrivateInformation) for those
# properties which are sensitive.
kwargs
.
setdefault
(
'args'
,
args
)
key_prefix
=
kwargs
.
pop
(
'key_prefix'
,
None
)
obj
=
getattr
(
self
,
'aq_parent'
,
None
)
if
obj
is
not
None
:
container
=
obj
.
aq_inner
.
aq_parent
if
not
_checkPermission
(
Permissions
.
View
,
obj
):
raise
AccessControl_Unauthorized
(
'This document is not authorized for view.'
)
else
:
container
=
None
pt
=
getattr
(
self
,
self
.
pt
)
extra_context
=
dict
(
container
=
container
,
template
=
self
,
form
=
self
,
key_prefix
=
key_prefix
,
options
=
kwargs
,
here
=
obj
,
context
=
obj
,
)
return
pt
.
pt_render
(
extra_context
=
extra_context
)
def
_exec
(
self
,
bound_names
,
args
,
kw
):
pt
=
getattr
(
self
,
self
.
pt
)
return
pt
.
_exec
(
self
,
bound_names
,
args
,
kw
)
def
manage_renameObject
(
self
,
id
,
new_id
,
REQUEST
=
None
):
# overriden to keep the order of a field after rename
groups
=
deepcopy
(
self
.
groups
)
ret
=
ZMIForm
.
manage_renameObject
(
self
,
id
,
new_id
,
REQUEST
=
REQUEST
)
for
group_id
,
field_id_list
in
groups
.
items
():
if
id
in
field_id_list
:
index
=
field_id_list
.
index
(
id
)
field_id_list
.
pop
(
index
)
field_id_list
.
insert
(
index
,
new_id
)
groups
[
group_id
]
=
field_id_list
self
.
groups
=
groups
return
ret
# Utilities
security
.
declareProtected
(
'View'
,
'ErrorFields'
)
def
ErrorFields
(
self
,
validation_errors
):
"""
Create a dictionnary of validation_errors
with field id as key
"""
ef
=
{}
for
e
in
validation_errors
.
errors
:
ef
[
e
.
field_id
]
=
e
return
ef
def
om_icons
(
self
):
"""Return a list of icon URLs to be displayed by an ObjectManager"""
icons
=
({
'path'
:
'misc_/ERP5Form/Form.png'
,
'alt'
:
self
.
meta_type
,
'title'
:
self
.
meta_type
},)
return
icons
# Pached validate_all to support ListBox validation
security
.
declareProtected
(
'View'
,
'validate_all'
)
def
validate_all
(
self
,
REQUEST
,
key_prefix
=
None
):
"""Validate all enabled fields in this form, catch any ValidationErrors
if they occur and raise a FormValidationError in the end if any
Validation Errors occured.
"""
result
=
{}
errors
=
[]
for
group
in
self
.
get_groups
():
if
group
.
lower
()
==
'hidden'
:
continue
for
field
in
self
.
get_fields_in_group
(
group
):
# skip any field we don't need to validate
if
not
field
.
need_validate
(
REQUEST
,
key_prefix
=
key_prefix
):
continue
if
not
(
field
.
get_value
(
'editable'
,
REQUEST
=
REQUEST
)):
continue
try
:
value
=
field
.
validate
(
REQUEST
,
key_prefix
=
key_prefix
)
# store under id
result
[
field
.
id
]
=
value
# store as alternate name as well if necessary
alternate_name
=
field
.
get_value
(
'alternate_name'
)
if
alternate_name
:
result
[
alternate_name
]
=
value
except
FormValidationError
,
e
:
# XXX JPS Patch for listbox
errors
.
extend
(
e
.
errors
)
result
.
update
(
e
.
result
)
except
ValidationError
,
err
:
errors
.
append
(
err
)
except
KeyError
,
err
:
LOG
(
'ERP5Form/Form.py:validate_all'
,
0
,
'KeyError : %s'
%
(
err
,
))
if
len
(
errors
)
>
0
:
raise
FormValidationError
(
errors
,
result
)
return
result
security
.
declareProtected
(
'View'
,
'hash_validated_data'
)
def
hash_validated_data
(
self
,
validated_data
):
return
hashlib
.
sha256
(
""
.
join
(
str
(
validated_data
[
key
])
for
key
in
sorted
(
validated_data
.
keys
())
if
isinstance
(
validated_data
[
key
],
(
str
,
unicode
,
int
,
long
,
float
,
DateTime
)))
).
hexdigest
()
# FTP/DAV Access
manage_FTPget
=
ZMIForm
.
get_xml
def
PUT
(
self
,
REQUEST
,
RESPONSE
):
"""Handle HTTP PUT requests."""
self
.
dav__init
(
REQUEST
,
RESPONSE
)
self
.
dav__simpleifhandler
(
REQUEST
,
RESPONSE
,
refresh
=
1
)
if
REQUEST
.
environ
[
'REQUEST_METHOD'
]
!=
'PUT'
:
raise
Forbidden
,
'REQUEST_METHOD should be PUT.'
body
=
REQUEST
.
get
(
'BODY'
,
''
)
# Empty the form (XMLToForm is unable to empty things before reopening)
for
k
in
self
.
get_field_ids
():
try
:
self
.
_delObject
(
k
)
except
AttributeError
:
pass
self
.
groups
=
{}
self
.
group_list
=
[]
# And reimport
XMLToForm
(
body
,
self
)
self
.
ZCacheable_invalidate
()
RESPONSE
.
setStatus
(
204
)
return
RESPONSE
manage_FTPput
=
PUT
security
.
declarePrivate
(
'getSimilarSkinFolderIdList'
)
def
getSimilarSkinFolderIdList
(
self
):
"""
Find other skins id installed in the same time
"""
portal
=
self
.
getPortalObject
()
folder_id
=
self
.
aq_parent
.
id
# Find a business template which manages the context skin folder.
folder_id_set
=
{
folder_id
}
for
template
in
portal
.
portal_templates
.
getInstalledBusinessTemplateList
():
template_skin_id_list
=
template
.
getTemplateSkinIdList
()
if
folder_id
in
template_skin_id_list
:
folder_id_set
.
update
(
template_skin_id_list
)
# Find folders which can be surcharged by this skin folder
if
'_'
in
folder_id
:
surcharged_folder_id
=
'erp5_%s'
%
folder_id
.
split
(
'_'
)[
-
1
]
if
(
surcharged_folder_id
!=
folder_id
)
and
\
(
getattr
(
portal
.
portal_skins
,
surcharged_folder_id
,
None
)
\
is
not
None
):
folder_id_set
.
add
(
surcharged_folder_id
)
break
return
list
(
folder_id_set
)
#Methods for Proxify tab.
security
.
declareProtected
(
'View management screens'
,
'getFormFieldList'
)
def
getFormFieldList
(
self
):
"""
find fields and forms which name ends with 'FieldLibrary' in
the same business template or in erp5_core.
"""
form_list
=
[]
def
iterate
(
obj
):
for
i
in
obj
.
objectValues
():
if
(
i
.
meta_type
==
'ERP5 Form'
and
i
.
id
.
startswith
(
'Base_view'
)
and
i
.
id
.
endswith
(
'FieldLibrary'
)
and
'_view'
in
i
.
getId
()):
form_id
=
i
.
getId
()
form_path
=
'%s.%s'
%
(
obj
.
getId
(),
form_id
)
field_list
=
[]
form_list
.
append
({
'form_path'
:
form_path
,
'form_id'
:
form_id
,
'field_list'
:
field_list
})
for
field
in
i
.
objectValues
():
field_type
,
proxy_flag
=
get_field_meta_type_and_proxy_flag
(
field
)
if
proxy_flag
:
field_type
=
'%s(Proxy)'
%
field_type
field_list
.
append
({
'field_object'
:
field
,
'field_type'
:
field_type
,
'proxy_flag'
:
proxy_flag
})
if
i
.
meta_type
==
'Folder'
:
iterate
(
i
)
skins_tool
=
self
.
portal_skins
folder_id
=
self
.
aq_parent
.
id
# for skin_folder_id in self.getSimilarSkinFolderIdList():
for
skin_folder_id
in
self
.
getPortalObject
().
portal_skins
.
objectIds
():
iterate
(
getattr
(
skins_tool
,
skin_folder_id
))
iterate
(
skins_tool
.
erp5_core
)
return
form_list
security
.
declareProtected
(
'View management screens'
,
'getProxyableFieldList'
)
def
getProxyableFieldList
(
self
,
field
,
form_field_list
=
None
):
""""""
def
extract_keyword
(
name
):
keyword_list
=
[
i
for
i
in
name
.
split
(
'_'
)
if
not
i
in
\
(
'my'
,
'default'
,
'listbox'
,
'your'
)]
if
len
(
keyword_list
)
==
0
:
# This means that the name is one of the exception keywords,
# so we have to keep it
keyword_list
=
[
name
]
return
keyword_list
def
check_keyword_list
(
name
,
keyword_list
):
count
=
0
for
i
in
keyword_list
:
if
i
in
name
:
count
+=
1
return
count
/
float
(
len
(
keyword_list
))
def
match
(
field_data
):
if
not
field_data
[
'field_type'
].
startswith
(
field
.
meta_type
):
return
0
field_object
=
field_data
[
'field_object'
]
if
field_object
.
aq_base
is
field
.
aq_base
:
return
0
field_id
=
field_object
.
getId
()
# All proxy fields in field libraries should define their
# technical context
# XXX Theses 3 following lines will need to be uncommented
# as soon as proxy guideline is fully validated on erp5_trade
#if field.meta_type == 'ProxyField' and \
# re.match('my_.*_mode', field_id) is None:
# return 0
# XXX keyword match is not useful anymore.Need different approach.
keyword_match_rate
=
check_keyword_list
(
field_id
,
extract_keyword
(
id_
))
if
keyword_match_rate
>
0.3
:
return
keyword_match_rate
else
:
def
split
(
string
):
result
=
[]
temporary
=
[]
for
char
in
string
:
if
char
.
isupper
():
if
temporary
:
result
.
append
(
''
.
join
(
temporary
))
temporary
=
[]
temporary
.
append
(
char
)
result
.
append
(
''
.
join
(
temporary
))
return
result
if
''
.
join
(
field_id
.
split
(
'_'
)[
1
:]).
startswith
(
split
(
field
.
meta_type
)[
0
].
lower
()):
# At least it seems a generic template field of the meta_type.
return
0.1
def
make_dict_list_append_function
(
dic
,
order_list
):
def
append
(
key
,
item
):
if
not
key
in
order_list
:
order_list
.
append
(
key
)
dic
[
key
]
=
[]
dic
[
key
].
append
(
item
)
return
append
def
add_default_field_library
():
portal_url
=
getToolByName
(
self
,
'portal_url'
)
portal
=
portal_url
.
getPortalObject
()
portal_skins
=
getToolByName
(
self
,
'portal_skins'
)
default_field_library_path
=
portal
.
getProperty
(
'erp5_default_field_library_path'
,
'erp5_core.Base_viewFieldLibrary'
)
if
(
not
default_field_library_path
or
len
(
default_field_library_path
.
split
(
'.'
))
!=
2
):
return
skinfolder_id
,
form_id
=
default_field_library_path
.
split
(
'.'
)
skinfolder
=
getattr
(
portal_skins
,
skinfolder_id
,
None
)
default_field_library
=
getattr
(
skinfolder
,
form_id
,
None
)
if
default_field_library
is
None
:
return
for
i
in
default_field_library
.
objectValues
():
field_meta_type
,
proxy_flag
=
get_field_meta_type_and_proxy_flag
(
i
)
if
meta_type
==
field_meta_type
:
if
proxy_flag
:
field_meta_type
=
'%s(Proxy)'
%
field_meta_type
matched_item
=
{
'form_id'
:
form_id
,
'field_type'
:
field_meta_type
,
'field_object'
:
i
,
'proxy_flag'
:
proxy_flag
,
'matched_rate'
:
0
}
if
not
i
in
[
item
[
'field_object'
]
for
item
in
matched
.
get
(
default_field_library_path
,
())]:
matched_append
(
default_field_library_path
,
matched_item
)
if
not
i
in
[
item
[
'field_object'
]
for
item
in
perfect_matched
.
get
(
default_field_library_path
,
())]:
perfect_matched_append
(
default_field_library_path
,
matched_item
)
id_
=
field
.
getId
()
meta_type
=
field
.
meta_type
matched
=
{}
form_order
=
[]
matched_append
=
make_dict_list_append_function
(
matched
,
form_order
)
perfect_matched
=
{}
perfect_matched_form_order
=
[]
perfect_matched_append
=
make_dict_list_append_function
(
perfect_matched
,
perfect_matched_form_order
)
if
form_field_list
is
None
:
form_field_list
=
self
.
getFormFieldList
()
for
i
in
form_field_list
:
for
data
in
i
[
'field_list'
]:
tmp
=
[]
matched_rate
=
match
(
data
)
if
matched_rate
>
0
:
form_path
=
i
[
'form_path'
]
form_id
=
i
[
'form_id'
]
field_type
=
data
[
'field_type'
]
field_object
=
data
[
'field_object'
]
proxy_flag
=
data
[
'proxy_flag'
]
matched_item
=
{
'form_id'
:
form_id
,
'field_type'
:
field_type
,
'field_object'
:
field_object
,
'proxy_flag'
:
proxy_flag
,
'matched_rate'
:
matched_rate
}
if
matched_rate
==
1
:
perfect_matched_append
(
form_path
,
matched_item
)
elif
not
perfect_matched
:
matched_append
(
form_path
,
matched_item
)
if
perfect_matched
:
perfect_matched_form_order
.
sort
()
add_default_field_library
()
return
perfect_matched_form_order
,
perfect_matched
form_order
.
sort
()
add_default_field_library
()
return
form_order
,
matched
security
.
declareProtected
(
'View management screens'
,
'getUnProxyableFieldList'
)
def
getUnProxyableFieldList
(
self
):
"""
Return ProxyFields
"""
return
sorted
([
f
for
f
in
self
.
objectValues
()
\
if
f
.
meta_type
==
'ProxyField'
],
key
=
lambda
x
:
x
.
id
)
security
.
declareProtected
(
'View management screens'
,
'getRelatedProxyFieldDictList'
)
def
getRelatedProxyFieldDictList
(
self
,
**
kw
):
"""
Retrieve all proxy using proxy in this form
"""
form_id
=
self
.
id
proxy_dict
=
{}
for
document
in
self
.
objectValues
():
short_path
=
"%s.%s"
%
(
form_id
,
document
.
id
)
proxy_dict
[
short_path
]
=
{
'proxy'
:
document
,
'short_path'
:
short_path
,
'related_proxy_list'
:
[]}
def
iterate
(
document
):
for
i
in
document
.
objectValues
():
if
i
.
meta_type
==
'ERP5 Form'
:
for
field
in
i
.
objectValues
():
if
field
.
meta_type
==
'ProxyField'
:
key
=
"%s.%s"
%
(
field
.
get_value
(
'form_id'
),
field
.
get_value
(
'field_id'
))
if
proxy_dict
.
has_key
(
key
):
proxy_dict
[
key
][
'related_proxy_list'
].
append
(
{
'short_path'
:
"%s.%s"
%
\
(
field
.
aq_parent
.
id
,
field
.
id
),
'proxy'
:
field
})
if
i
.
meta_type
==
'Folder'
:
iterate
(
i
)
skins_tool
=
self
.
portal_skins
proxy_dict_list
=
[]
if
len
(
proxy_dict
):
# for skin_folder_id in self.getSimilarSkinFolderIdList():
for
skin_folder_id
in
self
.
getPortalObject
().
portal_skins
.
objectIds
():
iterate
(
getattr
(
skins_tool
,
skin_folder_id
))
proxy_dict_list
=
proxy_dict
.
values
()
proxy_dict_list
.
sort
(
key
=
lambda
x
:
x
[
'short_path'
])
for
item
in
proxy_dict_list
:
item
[
'related_proxy_list'
].
sort
(
key
=
lambda
x
:
x
[
'short_path'
])
return
proxy_dict_list
_proxy_copy_type_list
=
(
bytes
,
unicode
,
int
,
long
,
float
,
bool
,
list
,
tuple
,
dict
,
DateTime
)
security
.
declareProtected
(
'Change Formulator Forms'
,
'proxifyField'
)
def
proxifyField
(
self
,
field_dict
=
None
,
force_delegate
=
False
,
keep_empty_value
=
False
,
REQUEST
=
None
):
"""Convert fields to proxy fields
If the field value is not empty and different from the proxyfield
value, the value is kept on the proxyfield, otherwise it is delegated.
If you specify force_delegate, values will be delegated even if they
are different. And if you specify keep_empty_value, then empty values
will not be delegated(force_delegate option is high priority).
"""
def
copy
(
field
,
value_type
):
new_dict
=
{}
for
key
,
value
in
getFieldDict
(
field
,
value_type
).
iteritems
():
if
isinstance
(
aq_base
(
value
),
(
Method
,
TALESMethod
)):
value
=
copyMethod
(
value
)
elif
not
(
value
is
None
or
isinstance
(
value
,
self
.
_proxy_copy_type_list
)):
raise
ValueError
(
'%s:%r'
%
(
type
(
value
),
value
))
elif
not
(
keep_empty_value
or
value
):
continue
new_dict
[
key
]
=
value
return
new_dict
def
is_equal
(
a
,
b
):
type_a
=
type
(
a
)
type_b
=
type
(
b
)
if
type_a
is
not
type_b
:
return
False
elif
type_a
is
Method
:
return
a
.
method_name
==
b
.
method_name
elif
type_a
is
TALESMethod
:
return
a
.
_text
==
b
.
_text
else
:
return
a
==
b
def
remove_same_value
(
new_dict
,
target_dict
):
for
key
,
value
in
new_dict
.
items
():
target_value
=
target_dict
.
get
(
key
)
if
force_delegate
or
is_equal
(
value
,
target_value
):
del
new_dict
[
key
]
return
new_dict
def
get_group_and_position
(
field_id
):
for
i
in
self
.
groups
.
keys
():
if
field_id
in
self
.
groups
[
i
]:
return
i
,
self
.
groups
[
i
].
index
(
field_id
)
def
set_group_and_position
(
group
,
position
,
field_id
):
self
.
field_removed
(
field_id
)
self
.
groups
[
group
].
insert
(
position
,
field_id
)
# Notify changes explicitly.
self
.
groups
=
self
.
groups
if
field_dict
is
None
:
return
for
field_id
in
field_dict
.
keys
():
target
=
field_dict
[
field_id
]
target_form_id
,
target_field_id
=
target
.
split
(
'.'
)
# keep current group and position.
group
,
position
=
get_group_and_position
(
field_id
)
# create proxy field
old_field
=
getattr
(
self
,
field_id
)
self
.
manage_delObjects
(
field_id
)
self
.
manage_addField
(
id
=
field_id
,
title
=
''
,
fieldname
=
'ProxyField'
)
proxy_field
=
getattr
(
self
,
field_id
)
proxy_field
.
values
[
'form_id'
]
=
target_form_id
proxy_field
.
values
[
'field_id'
]
=
target_field_id
target_field
=
proxy_field
.
getTemplateField
()
if
target_field
is
None
:
raise
ValueError
(
"Unable to find template : %s.%s"
%
(
target_form_id
,
target_field_id
))
# copy data
new_values
=
remove_same_value
(
copy
(
old_field
,
'values'
),
getFieldDict
(
target_field
,
'values'
))
new_tales
=
remove_same_value
(
copy
(
old_field
,
'tales'
),
getFieldDict
(
target_field
,
'tales'
))
if
target_field
.
meta_type
==
'ProxyField'
:
for
i
in
new_values
.
keys
():
if
not
i
in
target_field
.
delegated_list
:
# obsolete variable check
try
:
target_field
.
get_recursive_orig_value
(
i
)
except
KeyError
:
# then `i` is obsolete!
del
new_values
[
i
]
else
:
if
is_equal
(
target_field
.
get_recursive_orig_value
(
i
),
new_values
[
i
]):
del
new_values
[
i
]
for
i
in
new_tales
.
keys
():
if
not
i
in
target_field
.
delegated_list
:
# obsolete variable check
try
:
target_field
.
get_recursive_tales
(
i
)
except
KeyError
:
# then `i` is obsolete!
del
new_tales
[
i
]
else
:
if
is_equal
(
target_field
.
get_recursive_tales
(
i
),
new_tales
[
i
]):
del
new_tales
[
i
]
delegated_list
=
[]
for
i
in
(
new_values
.
keys
()
+
new_tales
.
keys
()):
if
not
i
in
delegated_list
:
delegated_list
.
append
(
i
)
proxy_field
.
values
.
update
(
new_values
)
proxy_field
.
tales
.
update
(
new_tales
)
proxy_field
.
delegated_list
=
delegated_list
# move back to the original group and position.
set_group_and_position
(
group
,
position
,
field_id
)
if
REQUEST
is
not
None
:
return
self
.
formProxify
(
manage_tabs_message
=
'Changed'
)
psyco
.
bind
(
__call__
)
psyco
.
bind
(
_exec
)
security
.
declareProtected
(
'Change Formulator Forms'
,
'unProxifyField'
)
def
unProxifyField
(
self
,
field_dict
=
None
,
copy_delegated_values
=
False
,
REQUEST
=
None
):
"""
Convert proxy fields to fields
"""
def
copy
(
field
,
value_type
):
new_dict
=
{}
for
key
,
value
in
getFieldDict
(
field
,
value_type
).
iteritems
():
if
isinstance
(
aq_base
(
value
),
(
Method
,
TALESMethod
)):
value
=
copyMethod
(
value
)
elif
not
(
value
is
None
or
isinstance
(
value
,
self
.
_proxy_copy_type_list
)):
raise
ValueError
(
'%s:%r'
%
(
type
(
value
),
value
))
new_dict
[
key
]
=
value
return
new_dict
def
is_equal
(
a
,
b
):
type_a
=
type
(
a
)
type_b
=
type
(
b
)
if
type_a
is
not
type_b
:
return
False
elif
type_a
is
Method
:
return
a
.
method_name
==
b
.
method_name
elif
type_a
is
TALESMethod
:
return
a
.
_text
==
b
.
_text
else
:
return
a
==
b
def
remove_same_value
(
new_dict
,
target_dict
):
for
key
,
value
in
new_dict
.
items
():
target_value
=
target_dict
.
get
(
key
)
if
is_equal
(
value
,
target_value
):
del
new_dict
[
key
]
return
new_dict
def
get_group_and_position
(
field_id
):
for
i
in
self
.
groups
.
keys
():
if
field_id
in
self
.
groups
[
i
]:
return
i
,
self
.
groups
[
i
].
index
(
field_id
)
def
set_group_and_position
(
group
,
position
,
field_id
):
self
.
field_removed
(
field_id
)
self
.
groups
[
group
].
insert
(
position
,
field_id
)
# Notify changes explicitly.
self
.
groups
=
self
.
groups
if
field_dict
is
None
:
return
for
field_id
in
field_dict
.
keys
():
# keep current group and position.
group
,
position
=
get_group_and_position
(
field_id
)
# create field
old_proxy_field
=
getattr
(
self
,
field_id
)
delegated_field
=
old_proxy_field
.
getRecursiveTemplateField
()
if
delegated_field
is
None
:
break
self
.
manage_delObjects
(
field_id
)
self
.
manage_addField
(
id
=
field_id
,
title
=
''
,
fieldname
=
delegated_field
.
meta_type
)
field
=
getattr
(
self
,
field_id
)
# copy data
new_values
=
remove_same_value
(
copy
(
old_proxy_field
,
'values'
),
field
.
values
)
new_tales
=
remove_same_value
(
copy
(
old_proxy_field
,
'tales'
),
field
.
tales
)
field
.
values
.
update
(
new_values
)
field
.
tales
.
update
(
new_tales
)
# move back to the original group and position.
set_group_and_position
(
group
,
position
,
field_id
)
if
REQUEST
is
not
None
:
return
self
.
formUnProxify
(
manage_tabs_message
=
'Changed'
)
# Overload of the Form method
# Use the include_disabled parameter since
# we should consider all fields to render the group tab
# moreoever, listbox rendering fails whenever enabled
# is based on the cell parameter.
security
.
declareProtected
(
'View'
,
'get_largest_group_length'
)
def
get_largest_group_length
(
self
):
"""Get the largest group length available; necessary for
'order' screen user interface.
XXX - Copyright issue
"""
max
=
0
for
group
in
self
.
get_groups
(
include_empty
=
1
):
fields
=
self
.
get_fields_in_group
(
group
,
include_disabled
=
1
)
if
len
(
fields
)
>
max
:
max
=
len
(
fields
)
return
max
security
.
declareProtected
(
'View'
,
'get_groups'
)
def
get_groups
(
self
,
include_empty
=
0
):
"""Get a list of all groups, in display order.
If include_empty is false, suppress groups that do not have
enabled fields.
XXX - Copyright issue
"""
if
include_empty
:
return
self
.
group_list
return
[
group
for
group
in
self
.
group_list
if
self
.
get_fields_in_group
(
group
,
include_disabled
=
1
)]
# Find support in ZMI. This is useful for development.
def
PrincipiaSearchSource
(
self
):
return
str
((
self
.
pt
,
self
.
name
,
self
.
action
,
self
.
update_action
,
self
.
encoding
,
self
.
stored_encoding
,
self
.
enctype
))
# utility function
def
get_field_meta_type_and_proxy_flag
(
field
):
if
field
.
meta_type
==
'ProxyField'
:
try
:
return
field
.
getRecursiveTemplateField
().
meta_type
,
True
except
AttributeError
:
raise
AttributeError
,
'The proxy target of %s.%s field does not '
\
'exists. Please check the field setting.'
%
\
(
field
.
aq_parent
.
id
,
field
.
getId
())
else
:
return
field
.
meta_type
,
False
# More optimizations
#psyco.bind(ERP5Field)
# XXX Not useful, as we patch those methods in FormulatorPatch
psyco
.
bind
(
Field
.
render
)
psyco
.
bind
(
Field
.
_render_helper
)
psyco
.
bind
(
Field
.
get_value
)
#from Products.PageTemplates.PageTemplate import PageTemplate
#from TAL import TALInterpreter
#psyco.bind(TALInterpreter.TALInterpreter)
#psyco.bind(TALInterpreter.TALInterpreter.interpret)
#psyco.bind(PageTemplate.pt_render)
#psyco.bind(PageTemplate.pt_macros)
#from Products.CMFCore.ActionsTool import ActionsTool
#psyco.bind(ActionsTool.listFilteredActionsFor)
product/ERP5/bootstrap/erp5_core/ModuleComponentTemplateItem/portal_components/module.erp5.Form.xml
0 → 100644
View file @
9f1ce1ba
<?xml version="1.0"?>
<ZopeData>
<record
id=
"1"
aka=
"AAAAAAAAAAE="
>
<pickle>
<global
name=
"Module Component"
module=
"erp5.portal_type"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
default_reference
</string>
</key>
<value>
<string>
Form
</string>
</value>
</item>
<item>
<key>
<string>
default_source_reference
</string>
</key>
<value>
<string>
Products.ERP5Form.Form
</string>
</value>
</item>
<item>
<key>
<string>
id
</string>
</key>
<value>
<string>
module.erp5.Form
</string>
</value>
</item>
<item>
<key>
<string>
portal_type
</string>
</key>
<value>
<string>
Module Component
</string>
</value>
</item>
<item>
<key>
<string>
sid
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
text_content_error_message
</string>
</key>
<value>
<tuple/>
</value>
</item>
<item>
<key>
<string>
text_content_warning_message
</string>
</key>
<value>
<tuple>
<string>
W:116, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:117, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:118, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:119, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:120, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:123, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:124, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:125, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:126, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:127, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:128, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:129, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:130, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:131, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:132, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:133, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:134, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:135, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:136, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:137, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:138, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:139, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:140, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:141, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:142, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:143, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:192, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:194, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:224, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:399, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:400, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:402, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:406, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:407, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:408, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:409, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:410, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:412, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:418, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:420, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:421, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:422, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:435, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:441, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:442, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:444, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:445, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:448, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:452, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:453, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:454, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:455, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:456, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:457, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:458, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:459, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:460, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:463, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:465, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:467, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:468, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:470, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:471, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:474, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:478, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:480, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:485, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:488, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:493, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:495, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:497, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:501, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:505, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:509, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:513, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:517, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:521, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:525, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:529, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:533, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:540, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:550, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:554, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:558, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:562, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:566, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:568, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:574, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:578, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:579, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:580, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:583, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:586, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:599, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:606, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:609, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:610, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:613, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:614, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:617, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:618, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:621, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:623, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:627, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:628, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:629, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:630, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:631, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:634, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:636, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:637, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:638, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:639, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:645, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:647, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:649, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:653, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:656, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:657, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:658, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:659, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:660, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:661, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:662, 0: Bad indentation. Found 10 spaces, expected 6 (bad-indentation)
</string>
<string>
W:663, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:666, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:688, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:689, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:690, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:691, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:692, 0: Bad indentation. Found 10 spaces, expected 6 (bad-indentation)
</string>
<string>
W:693, 0: Bad indentation. Found 10 spaces, expected 6 (bad-indentation)
</string>
<string>
W:694, 0: Bad indentation. Found 12 spaces, expected 8 (bad-indentation)
</string>
<string>
W:695, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:696, 0: Bad indentation. Found 10 spaces, expected 6 (bad-indentation)
</string>
<string>
W:697, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:698, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:706, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:708, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:709, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:710, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:712, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:714, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:715, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:716, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:717, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:718, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:719, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:720, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:721, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:722, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:723, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:726, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:727, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:728, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:732, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:733, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:734, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:735, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:737, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:738, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:739, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:741, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:744, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:745, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:746, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:750, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:751, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:752, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:753, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:754, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:755, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:757, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:758, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:759, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:760, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:761, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:762, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:764, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:766, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:767, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:768, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:769, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:770, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:771, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:772, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:773, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:774, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:775, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:777, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:778, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:779, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:781, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:782, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:783, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:791, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:793, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:794, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:795, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:796, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:797, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:798, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:799, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:801, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:802, 0: Bad indentation. Found 10 spaces, expected 6 (bad-indentation)
</string>
<string>
W:803, 0: Bad indentation. Found 12 spaces, expected 8 (bad-indentation)
</string>
<string>
W:804, 0: Bad indentation. Found 10 spaces, expected 6 (bad-indentation)
</string>
<string>
W:805, 0: Bad indentation. Found 12 spaces, expected 8 (bad-indentation)
</string>
<string>
W:806, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:807, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:809, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:810, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:811, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:812, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:814, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:816, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:817, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:818, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:821, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:822, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:824, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:825, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:826, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:827, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:828, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:831, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:832, 0: Bad indentation. Found 12 spaces, expected 10 (bad-indentation)
</string>
<string>
W:833, 0: Bad indentation. Found 12 spaces, expected 10 (bad-indentation)
</string>
<string>
W:836, 0: Bad indentation. Found 14 spaces, expected 12 (bad-indentation)
</string>
<string>
W:838, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:839, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:842, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:843, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:844, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:848, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:849, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:850, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:851, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:855, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:856, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:857, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:858, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:861, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:862, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:863, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:864, 0: Bad indentation. Found 28 spaces, expected 14 (bad-indentation)
</string>
<string>
W:865, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:868, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:869, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:871, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:872, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:874, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:875, 0: Bad indentation. Found 10 spaces, expected 6 (bad-indentation)
</string>
<string>
W:876, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:877, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:879, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:880, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:881, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:882, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:883, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:885, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:888, 0: Bad indentation. Found 14 spaces, expected 8 (bad-indentation)
</string>
<string>
W:889, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:891, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:892, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:893, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:894, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:895, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:896, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:898, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:899, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:900, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:901, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:902, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:903, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:904, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:913, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:914, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:915, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:916, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:917, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:918, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:919, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:920, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:921, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:922, 0: Bad indentation. Found 28 spaces, expected 14 (bad-indentation)
</string>
<string>
W:923, 0: Bad indentation. Found 32 spaces, expected 16 (bad-indentation)
</string>
<string>
W:924, 0: Bad indentation. Found 28 spaces, expected 14 (bad-indentation)
</string>
<string>
W:925, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:926, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:927, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:929, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:932, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:934, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:935, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:936, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:937, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:938, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:939, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:940, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:942, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:943, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:944, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:945, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:947, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:950, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:952, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:954, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:956, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:957, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:958, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:959, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:960, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:961, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:962, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:963, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:964, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:965, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:972, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:974, 0: Bad indentation. Found 22 spaces, expected 12 (bad-indentation)
</string>
<string>
W:975, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:977, 0: Bad indentation. Found 22 spaces, expected 12 (bad-indentation)
</string>
<string>
W:979, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:980, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:982, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:983, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:984, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:986, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:987, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:988, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:990, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:991, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:993, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:994, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:995, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:996, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:997, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:998, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:999, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1000, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1001, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1002, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1004, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1010, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1011, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:1012, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1013, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:1015, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1016, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1017, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1018, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1020, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1021, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1022, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1024, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1025, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1026, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1029, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1032, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1034, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1035, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1038, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1039, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1040, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1041, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1042, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1045, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1046, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1047, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1048, 0: Bad indentation. Found 12 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1049, 0: Bad indentation. Found 14 spaces, expected 12 (bad-indentation)
</string>
<string>
W:1050, 0: Bad indentation. Found 16 spaces, expected 14 (bad-indentation)
</string>
<string>
W:1052, 0: Bad indentation. Found 16 spaces, expected 14 (bad-indentation)
</string>
<string>
W:1053, 0: Bad indentation. Found 18 spaces, expected 16 (bad-indentation)
</string>
<string>
W:1057, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1058, 0: Bad indentation. Found 12 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1060, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1061, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1062, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1064, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1065, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1066, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1067, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1068, 0: Bad indentation. Found 8 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1069, 0: Bad indentation. Found 10 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1071, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1073, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1076, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1077, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1079, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1086, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1087, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1088, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1089, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1090, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1091, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1093, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1094, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1095, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1096, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1097, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1099, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1100, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1101, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1102, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1103, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1104, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1105, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1106, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1107, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1108, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1109, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1111, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1112, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1113, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1114, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1115, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1116, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1118, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1119, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1120, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1121, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1123, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1124, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1125, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1127, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1129, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1130, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1132, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1133, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1134, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1137, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1140, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1141, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1142, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1143, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1144, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1145, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1147, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1148, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1149, 0: Bad indentation. Found 14 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1153, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1155, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1158, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1159, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1160, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1162, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:1163, 0: Bad indentation. Found 28 spaces, expected 14 (bad-indentation)
</string>
<string>
W:1164, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:1166, 0: Bad indentation. Found 28 spaces, expected 14 (bad-indentation)
</string>
<string>
W:1167, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:1168, 0: Bad indentation. Found 28 spaces, expected 14 (bad-indentation)
</string>
<string>
W:1170, 0: Bad indentation. Found 32 spaces, expected 16 (bad-indentation)
</string>
<string>
W:1171, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1172, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1174, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:1175, 0: Bad indentation. Found 28 spaces, expected 14 (bad-indentation)
</string>
<string>
W:1176, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:1178, 0: Bad indentation. Found 28 spaces, expected 14 (bad-indentation)
</string>
<string>
W:1179, 0: Bad indentation. Found 24 spaces, expected 12 (bad-indentation)
</string>
<string>
W:1180, 0: Bad indentation. Found 28 spaces, expected 14 (bad-indentation)
</string>
<string>
W:1182, 0: Bad indentation. Found 32 spaces, expected 16 (bad-indentation)
</string>
<string>
W:1184, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1185, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1186, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1187, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1188, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1189, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1190, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1193, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1195, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1196, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1198, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1199, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1201, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1202, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1204, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1207, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1208, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1209, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1210, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1211, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1212, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1214, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1215, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1216, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1218, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1219, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1220, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1221, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1222, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1223, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1224, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1225, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1226, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1227, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1228, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1230, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1231, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1232, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1233, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1234, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1235, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1237, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1238, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1239, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1240, 0: Bad indentation. Found 20 spaces, expected 10 (bad-indentation)
</string>
<string>
W:1242, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1243, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1244, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1246, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1248, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1249, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1251, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1253, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1256, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1257, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1258, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1259, 0: Bad indentation. Found 14 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1260, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1261, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1264, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1266, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1268, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1271, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1272, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1275, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1277, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1278, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1285, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1286, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1287, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1291, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1292, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1293, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1294, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1295, 0: Bad indentation. Found 16 spaces, expected 8 (bad-indentation)
</string>
<string>
W:1296, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1298, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1299, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1300, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1306, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1307, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1308, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1312, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1313, 0: Bad indentation. Found 6 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1318, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1319, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1320, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1321, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W:1322, 0: Bad indentation. Found 12 spaces, expected 6 (bad-indentation)
</string>
<string>
W:1325, 0: Bad indentation. Found 4 spaces, expected 2 (bad-indentation)
</string>
<string>
W:1326, 0: Bad indentation. Found 8 spaces, expected 4 (bad-indentation)
</string>
<string>
W: 99, 5: Using type() instead of isinstance() for a typecheck. (unidiomatic-typecheck)
</string>
<string>
W:116, 7: Using type() instead of isinstance() for a typecheck. (unidiomatic-typecheck)
</string>
<string>
W:118, 9: Using type() instead of isinstance() for a typecheck. (unidiomatic-typecheck)
</string>
<string>
W:155, 28: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:158, 31: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:174, 2: __init__ method from base class \'StaticValue\' is not called (super-init-not-called)
</string>
<string>
W:177, 28: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:234, 4: No exception type(s) specified (bare-except)
</string>
<string>
W:254, 2: __init__ method from base class \'StaticValue\' is not called (super-init-not-called)
</string>
<string>
W:257, 28: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:261, 2: __init__ method from base class \'StaticValue\' is not called (super-init-not-called)
</string>
<string>
W:265, 28: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:288, 28: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:306, 28: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:320, 31: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:364, 20: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:419, 8: Using type() instead of isinstance() for a typecheck. (unidiomatic-typecheck)
</string>
<string>
W:434, 22: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:447, 23: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:474, 8: Redefining built-in \'dict\' (redefined-builtin)
</string>
<string>
W:647, 23: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:647, 4: __init__ method from base class \'Base\' is not called (super-init-not-called)
</string>
<string>
W:647, 4: __init__ method from base class \'ZMIForm\' is not called (super-init-not-called)
</string>
<string>
W:647, 4: __init__ method from base class \'ZopePageTemplate\' is not called (super-init-not-called)
</string>
<string>
W:712, 34: Redefining built-in \'id\' (redefined-builtin)
</string>
<string>
W:712, 4: Signature differs from overridden \'manage_renameObject\' method (signature-differs)
</string>
<string>
W:745, 4: Arguments number differs from overridden \'validate_all\' method (arguments-differ)
</string>
<string>
W:872, 8: Unused variable \'folder_id\' (unused-variable)
</string>
<string>
W:995, 16: Unused variable \'tmp\' (unused-variable)
</string>
<string>
W:1291, 8: Redefining built-in \'max\' (redefined-builtin)
</string>
<string>
W:1293, 12: Redefining name \'fields\' from outer scope (line 35) (redefined-outer-name)
</string>
</tuple>
</value>
</item>
<item>
<key>
<string>
version
</string>
</key>
<value>
<string>
erp5
</string>
</value>
</item>
<item>
<key>
<string>
workflow_history
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAI=
</string>
</persistent>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"2"
aka=
"AAAAAAAAAAI="
>
<pickle>
<global
name=
"PersistentMapping"
module=
"Persistence.mapping"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
data
</string>
</key>
<value>
<dictionary>
<item>
<key>
<string>
component_validation_workflow
</string>
</key>
<value>
<persistent>
<string
encoding=
"base64"
>
AAAAAAAAAAM=
</string>
</persistent>
</value>
</item>
</dictionary>
</value>
</item>
</dictionary>
</pickle>
</record>
<record
id=
"3"
aka=
"AAAAAAAAAAM="
>
<pickle>
<global
name=
"WorkflowHistoryList"
module=
"Products.ERP5Type.Workflow"
/>
</pickle>
<pickle>
<dictionary>
<item>
<key>
<string>
_log
</string>
</key>
<value>
<list>
<dictionary>
<item>
<key>
<string>
action
</string>
</key>
<value>
<none/>
</value>
</item>
<item>
<key>
<string>
validation_state
</string>
</key>
<value>
<string>
draft
</string>
</value>
</item>
</dictionary>
</list>
</value>
</item>
</dictionary>
</pickle>
</record>
</ZopeData>
product/ERP5/bootstrap/erp5_core/bt/template_module_component_id_list
View file @
9f1ce1ba
...
@@ -2,6 +2,7 @@ module.erp5.DateUtils
...
@@ -2,6 +2,7 @@ module.erp5.DateUtils
module.erp5.DiffUtils
module.erp5.DiffUtils
module.erp5.ExpandPolicy
module.erp5.ExpandPolicy
module.erp5.ExplanationCache
module.erp5.ExplanationCache
module.erp5.Form
module.erp5.GeneratedAmountList
module.erp5.GeneratedAmountList
module.erp5.Log
module.erp5.Log
module.erp5.MovementCollectionDiff
module.erp5.MovementCollectionDiff
...
...
product/ERP5Form/FSForm.py
deleted
100644 → 0
View file @
75309541
from
Products.ERP5Type
import
Globals
from
AccessControl
import
ClassSecurityInfo
from
Products.CMFCore.permissions
import
View
,
ViewManagementScreens
from
Products.CMFCore.FSObject
import
FSObject
from
Products.CMFCore.DirectoryView
import
registerFileExtension
,
\
registerMetaType
from
Products.ERP5Form
import
_dtmldir
from
Products.ERP5Form.Form
import
ERP5Form
from
Products.Formulator.XMLToForm
import
XMLToForm
class
ERP5FSForm
(
FSObject
,
ERP5Form
):
"""FSForm."""
meta_type
=
'ERP5 Filesystem Formulator Form'
manage_options
=
(
(
{
'label'
:
'Customize'
,
'action'
:
'manage_main'
},
{
'label'
:
'Test'
,
'action'
:
'formTest'
},
)
)
security
=
ClassSecurityInfo
()
security
.
declareObjectProtected
(
View
)
security
.
declareProtected
(
ViewManagementScreens
,
'manage_main'
)
manage_main
=
Globals
.
DTMLFile
(
'FSForm_customize'
,
_dtmldir
)
def
__init__
(
self
,
id
,
filepath
,
fullname
=
None
,
properties
=
None
):
FSObject
.
__init__
(
self
,
id
,
filepath
,
fullname
,
properties
)
def
_createZODBClone
(
self
):
"""Create a ZODB (editable) equivalent of this object."""
type_info
=
self
.
getPortalObject
().
portal_types
.
getTypeInfo
(
'ERP5 Form'
)
obj
=
type_info
.
constructInstance
(
container
=
self
,
temp_object
=
True
,
id
=
self
.
getId
(),
title
=
self
.
title
).
aq_base
obj
.
set_xml
(
self
.
get_xml
())
return
obj
def
_readFile
(
self
,
reparse
):
f
=
open
(
self
.
_filepath
,
'rb'
)
# update the form with the xml data
try
:
XMLToForm
(
f
.
read
(),
self
)
except
:
# bare except here, but I hope this is ok, as the
# exception should be reraised
# (except if the LOG raises another one ... should we be more paranoid here?)
import
zLOG
zLOG
.
LOG
(
'Formulator.FSForm'
,
zLOG
.
ERROR
,
'error reading form from file '
+
self
.
_filepath
)
raise
f
.
close
()
Globals
.
InitializeClass
(
ERP5FSForm
)
registerFileExtension
(
'form'
,
ERP5FSForm
)
registerMetaType
(
'FSForm'
,
ERP5FSForm
)
product/ERP5Form/Form.py
View file @
9f1ce1ba
...
@@ -26,31 +26,19 @@
...
@@ -26,31 +26,19 @@
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#
#
##############################################################################
##############################################################################
import
hashlib
from
copy
import
deepcopy
from
Products.Formulator.Form
import
BasicForm
from
Products.Formulator.Form
import
BasicForm
,
ZMIForm
from
Products.Formulator.Errors
import
FormValidationError
,
ValidationError
from
Products.Formulator.DummyField
import
fields
from
Products.Formulator.DummyField
import
fields
from
Products.Formulator.XMLToForm
import
XMLToForm
from
Products.PageTemplates.ZopePageTemplate
import
ZopePageTemplate
from
Products.CMFCore.utils
import
_checkPermission
,
getToolByName
from
Products.CMFCore.exceptions
import
AccessControl_Unauthorized
from
Products.ERP5Type
import
PropertySheet
,
Permissions
from
urllib
import
quote
from
urllib
import
quote
from
Products.ERP5Type.Globals
import
DTMLFile
,
get_request
from
Products.ERP5Type.Globals
import
DTMLFile
,
get_request
from
AccessControl
import
Unauthorized
,
ClassSecurityInfo
from
AccessControl
import
Unauthorized
from
DateTime
import
DateTime
from
ZODB.POSException
import
ConflictError
from
ZODB.POSException
import
ConflictError
from
zExceptions
import
Redirect
from
zExceptions
import
Redirect
from
Acquisition
import
aq_base
from
Acquisition
import
aq_base
from
Products.PageTemplates.Expressions
import
SecureModuleImporter
from
Products.PageTemplates.Expressions
import
SecureModuleImporter
from
zExceptions
import
Forbidden
from
Products.ERP5Type.PsycoWrapper
import
psyco
from
Products.ERP5Type.PsycoWrapper
import
psyco
from
Products.ERP5Type.Base
import
Base
class
FieldValueCacheDict
(
dict
):
class
FieldValueCacheDict
(
dict
):
_last_sync
=
-
1
_last_sync
=
-
1
...
@@ -567,752 +555,6 @@ def create_settings_form():
...
@@ -567,752 +555,6 @@ def create_settings_form():
method
,
enctype
,
encoding
,
stored_encoding
,
unicode_mode
,
edit_order
])
method
,
enctype
,
encoding
,
stored_encoding
,
unicode_mode
,
edit_order
])
return
form
return
form
from
OFS.Cache
import
filterCacheTab
class
ERP5Form
(
Base
,
ZMIForm
,
ZopePageTemplate
):
"""
A Formulator form with a built-in rendering parameter based
on page templates or DTML.
"""
meta_type
=
"ERP5 Form"
portal_type
=
"ERP5 Form"
icon
=
"www/Form.png"
# Declarative Security
security
=
ClassSecurityInfo
()
# Tabs in ZMI
manage_options
=
(
ZMIForm
.
manage_options
[:
5
]
+
({
'label'
:
'Proxify'
,
'action'
:
'formProxify'
},
{
'label'
:
'UnProxify'
,
'action'
:
'formUnProxify'
},
{
'label'
:
'RelatedProxy'
,
'action'
:
'formShowRelatedProxyFields'
},
{
'label'
:
'Cache'
,
'action'
:
'ZCacheable_manage'
,
'filter'
:
filterCacheTab
,
'help'
:
(
'OFSP'
,
'Cacheable-properties.stx'
)}
)
+
ZMIForm
.
manage_options
[
5
:])
# Declarative properties
property_sheets
=
(
PropertySheet
.
Base
,
PropertySheet
.
SimpleItem
,
PropertySheet
.
Folder
,
PropertySheet
.
CategoryCore
)
# Constructors
constructors
=
(
manage_addForm
,
addERP5Form
)
# This is a patched dtml formOrder
security
.
declareProtected
(
'View management screens'
,
'formOrder'
)
formOrder
=
DTMLFile
(
'dtml/formOrder'
,
globals
())
# Proxify form
security
.
declareProtected
(
'View management screens'
,
'formProxify'
)
formProxify
=
DTMLFile
(
'dtml/formProxify'
,
globals
())
# Proxify form
security
.
declareProtected
(
'View management screens'
,
'formUnProxify'
)
formUnProxify
=
DTMLFile
(
'dtml/formUnProxify'
,
globals
())
# Related Proxy Fields
security
.
declareProtected
(
'View management screens'
,
'formShowRelatedProxyFields'
)
formShowRelatedProxyFields
=
DTMLFile
(
'dtml/formShowRelatedProxyFields'
,
globals
())
# Default Attributes
pt
=
'form_view'
action_title
=
''
update_action
=
''
update_action_title
=
''
edit_order
=
[]
# Special Settings
settings_form
=
create_settings_form
()
manage_main
=
ZMIForm
.
manage_main
objectIds
=
ZMIForm
.
objectIds
objectItems
=
ZMIForm
.
objectItems
objectValues
=
ZMIForm
.
objectValues
# If content_type is not text/html ZopePageTemplate will check that the
# source is well formed XML, but this does not really applies to Forms,
# they don't have source. By setting content_type here we make sure we
# don't get ERP5Type's Base default content_type.
content_type
=
ZopePageTemplate
.
content_type
def
__init__
(
self
,
id
,
title
=
''
,
unicode_mode
=
0
,
encoding
=
'UTF-8'
,
stored_encoding
=
'UTF-8'
):
"""Initialize form.
id -- id of form
title -- the title of the form
"""
ZMIForm
.
inheritedAttribute
(
'__init__'
)(
self
,
""
,
"POST"
,
""
,
id
,
encoding
,
stored_encoding
,
unicode_mode
)
self
.
id
=
id
self
.
title
=
title
self
.
row_length
=
4
self
.
group_list
=
[
"left"
,
"right"
,
"center"
,
"bottom"
,
"hidden"
]
groups
=
{}
for
group
in
self
.
group_list
:
groups
[
group
]
=
[]
self
.
groups
=
groups
# Proxy method to PageTemplate
def
__call__
(
self
,
*
args
,
**
kwargs
):
# Security
#
# The minimal action consists in checking that
# we have View permission on the current object
# before rendering a form. Otherwise, object with
# AccessContentInformation can be viewed by invoking
# a form directly.
#
# What would be better is to prevent calling certain
# forms to render objects. This can not be done
# through actions since we are using sometimes forms
# to render the results of a report dialog form.
# An a appropriate solutions could consist in adding
# a permission field to the form. Another solutions
# is the use of REFERER in the rendering process.
#
# Both solutions are not perfect if the goal is, for
# example, to prevent displaying private information of
# staff. The only real solution is to use a special
# permission (ex. AccessPrivateInformation) for those
# properties which are sensitive.
kwargs
.
setdefault
(
'args'
,
args
)
key_prefix
=
kwargs
.
pop
(
'key_prefix'
,
None
)
obj
=
getattr
(
self
,
'aq_parent'
,
None
)
if
obj
is
not
None
:
container
=
obj
.
aq_inner
.
aq_parent
if
not
_checkPermission
(
Permissions
.
View
,
obj
):
raise
AccessControl_Unauthorized
(
'This document is not authorized for view.'
)
else
:
container
=
None
pt
=
getattr
(
self
,
self
.
pt
)
extra_context
=
dict
(
container
=
container
,
template
=
self
,
form
=
self
,
key_prefix
=
key_prefix
,
options
=
kwargs
,
here
=
obj
,
context
=
obj
,
)
return
pt
.
pt_render
(
extra_context
=
extra_context
)
def
_exec
(
self
,
bound_names
,
args
,
kw
):
pt
=
getattr
(
self
,
self
.
pt
)
return
pt
.
_exec
(
self
,
bound_names
,
args
,
kw
)
def
manage_renameObject
(
self
,
id
,
new_id
,
REQUEST
=
None
):
# overriden to keep the order of a field after rename
groups
=
deepcopy
(
self
.
groups
)
ret
=
ZMIForm
.
manage_renameObject
(
self
,
id
,
new_id
,
REQUEST
=
REQUEST
)
for
group_id
,
field_id_list
in
groups
.
items
():
if
id
in
field_id_list
:
index
=
field_id_list
.
index
(
id
)
field_id_list
.
pop
(
index
)
field_id_list
.
insert
(
index
,
new_id
)
groups
[
group_id
]
=
field_id_list
self
.
groups
=
groups
return
ret
# Utilities
security
.
declareProtected
(
'View'
,
'ErrorFields'
)
def
ErrorFields
(
self
,
validation_errors
):
"""
Create a dictionnary of validation_errors
with field id as key
"""
ef
=
{}
for
e
in
validation_errors
.
errors
:
ef
[
e
.
field_id
]
=
e
return
ef
def
om_icons
(
self
):
"""Return a list of icon URLs to be displayed by an ObjectManager"""
icons
=
({
'path'
:
'misc_/ERP5Form/Form.png'
,
'alt'
:
self
.
meta_type
,
'title'
:
self
.
meta_type
},)
return
icons
# Pached validate_all to support ListBox validation
security
.
declareProtected
(
'View'
,
'validate_all'
)
def
validate_all
(
self
,
REQUEST
,
key_prefix
=
None
):
"""Validate all enabled fields in this form, catch any ValidationErrors
if they occur and raise a FormValidationError in the end if any
Validation Errors occured.
"""
result
=
{}
errors
=
[]
for
group
in
self
.
get_groups
():
if
group
.
lower
()
==
'hidden'
:
continue
for
field
in
self
.
get_fields_in_group
(
group
):
# skip any field we don't need to validate
if
not
field
.
need_validate
(
REQUEST
,
key_prefix
=
key_prefix
):
continue
if
not
(
field
.
get_value
(
'editable'
,
REQUEST
=
REQUEST
)):
continue
try
:
value
=
field
.
validate
(
REQUEST
,
key_prefix
=
key_prefix
)
# store under id
result
[
field
.
id
]
=
value
# store as alternate name as well if necessary
alternate_name
=
field
.
get_value
(
'alternate_name'
)
if
alternate_name
:
result
[
alternate_name
]
=
value
except
FormValidationError
,
e
:
# XXX JPS Patch for listbox
errors
.
extend
(
e
.
errors
)
result
.
update
(
e
.
result
)
except
ValidationError
,
err
:
errors
.
append
(
err
)
except
KeyError
,
err
:
LOG
(
'ERP5Form/Form.py:validate_all'
,
0
,
'KeyError : %s'
%
(
err
,
))
if
len
(
errors
)
>
0
:
raise
FormValidationError
(
errors
,
result
)
return
result
security
.
declareProtected
(
'View'
,
'hash_validated_data'
)
def
hash_validated_data
(
self
,
validated_data
):
return
hashlib
.
sha256
(
""
.
join
(
str
(
validated_data
[
key
])
for
key
in
sorted
(
validated_data
.
keys
())
if
isinstance
(
validated_data
[
key
],
(
str
,
unicode
,
int
,
long
,
float
,
DateTime
)))
).
hexdigest
()
# FTP/DAV Access
manage_FTPget
=
ZMIForm
.
get_xml
def
PUT
(
self
,
REQUEST
,
RESPONSE
):
"""Handle HTTP PUT requests."""
self
.
dav__init
(
REQUEST
,
RESPONSE
)
self
.
dav__simpleifhandler
(
REQUEST
,
RESPONSE
,
refresh
=
1
)
if
REQUEST
.
environ
[
'REQUEST_METHOD'
]
!=
'PUT'
:
raise
Forbidden
,
'REQUEST_METHOD should be PUT.'
body
=
REQUEST
.
get
(
'BODY'
,
''
)
# Empty the form (XMLToForm is unable to empty things before reopening)
for
k
in
self
.
get_field_ids
():
try
:
self
.
_delObject
(
k
)
except
AttributeError
:
pass
self
.
groups
=
{}
self
.
group_list
=
[]
# And reimport
XMLToForm
(
body
,
self
)
self
.
ZCacheable_invalidate
()
RESPONSE
.
setStatus
(
204
)
return
RESPONSE
manage_FTPput
=
PUT
security
.
declarePrivate
(
'getSimilarSkinFolderIdList'
)
def
getSimilarSkinFolderIdList
(
self
):
"""
Find other skins id installed in the same time
"""
portal
=
self
.
getPortalObject
()
folder_id
=
self
.
aq_parent
.
id
# Find a business template which manages the context skin folder.
folder_id_set
=
{
folder_id
}
for
template
in
portal
.
portal_templates
.
getInstalledBusinessTemplateList
():
template_skin_id_list
=
template
.
getTemplateSkinIdList
()
if
folder_id
in
template_skin_id_list
:
folder_id_set
.
update
(
template_skin_id_list
)
# Find folders which can be surcharged by this skin folder
if
'_'
in
folder_id
:
surcharged_folder_id
=
'erp5_%s'
%
folder_id
.
split
(
'_'
)[
-
1
]
if
(
surcharged_folder_id
!=
folder_id
)
and
\
(
getattr
(
portal
.
portal_skins
,
surcharged_folder_id
,
None
)
\
is
not
None
):
folder_id_set
.
add
(
surcharged_folder_id
)
break
return
list
(
folder_id_set
)
#Methods for Proxify tab.
security
.
declareProtected
(
'View management screens'
,
'getFormFieldList'
)
def
getFormFieldList
(
self
):
"""
find fields and forms which name ends with 'FieldLibrary' in
the same business template or in erp5_core.
"""
form_list
=
[]
def
iterate
(
obj
):
for
i
in
obj
.
objectValues
():
if
(
i
.
meta_type
==
'ERP5 Form'
and
i
.
id
.
startswith
(
'Base_view'
)
and
i
.
id
.
endswith
(
'FieldLibrary'
)
and
'_view'
in
i
.
getId
()):
form_id
=
i
.
getId
()
form_path
=
'%s.%s'
%
(
obj
.
getId
(),
form_id
)
field_list
=
[]
form_list
.
append
({
'form_path'
:
form_path
,
'form_id'
:
form_id
,
'field_list'
:
field_list
})
for
field
in
i
.
objectValues
():
field_type
,
proxy_flag
=
get_field_meta_type_and_proxy_flag
(
field
)
if
proxy_flag
:
field_type
=
'%s(Proxy)'
%
field_type
field_list
.
append
({
'field_object'
:
field
,
'field_type'
:
field_type
,
'proxy_flag'
:
proxy_flag
})
if
i
.
meta_type
==
'Folder'
:
iterate
(
i
)
skins_tool
=
self
.
portal_skins
folder_id
=
self
.
aq_parent
.
id
# for skin_folder_id in self.getSimilarSkinFolderIdList():
for
skin_folder_id
in
self
.
getPortalObject
().
portal_skins
.
objectIds
():
iterate
(
getattr
(
skins_tool
,
skin_folder_id
))
iterate
(
skins_tool
.
erp5_core
)
return
form_list
security
.
declareProtected
(
'View management screens'
,
'getProxyableFieldList'
)
def
getProxyableFieldList
(
self
,
field
,
form_field_list
=
None
):
""""""
def
extract_keyword
(
name
):
keyword_list
=
[
i
for
i
in
name
.
split
(
'_'
)
if
not
i
in
\
(
'my'
,
'default'
,
'listbox'
,
'your'
)]
if
len
(
keyword_list
)
==
0
:
# This means that the name is one of the exception keywords,
# so we have to keep it
keyword_list
=
[
name
]
return
keyword_list
def
check_keyword_list
(
name
,
keyword_list
):
count
=
0
for
i
in
keyword_list
:
if
i
in
name
:
count
+=
1
return
count
/
float
(
len
(
keyword_list
))
def
match
(
field_data
):
if
not
field_data
[
'field_type'
].
startswith
(
field
.
meta_type
):
return
0
field_object
=
field_data
[
'field_object'
]
if
field_object
.
aq_base
is
field
.
aq_base
:
return
0
field_id
=
field_object
.
getId
()
# All proxy fields in field libraries should define their
# technical context
# XXX Theses 3 following lines will need to be uncommented
# as soon as proxy guideline is fully validated on erp5_trade
#if field.meta_type == 'ProxyField' and \
# re.match('my_.*_mode', field_id) is None:
# return 0
# XXX keyword match is not useful anymore.Need different approach.
keyword_match_rate
=
check_keyword_list
(
field_id
,
extract_keyword
(
id_
))
if
keyword_match_rate
>
0.3
:
return
keyword_match_rate
else
:
def
split
(
string
):
result
=
[]
temporary
=
[]
for
char
in
string
:
if
char
.
isupper
():
if
temporary
:
result
.
append
(
''
.
join
(
temporary
))
temporary
=
[]
temporary
.
append
(
char
)
result
.
append
(
''
.
join
(
temporary
))
return
result
if
''
.
join
(
field_id
.
split
(
'_'
)[
1
:]).
startswith
(
split
(
field
.
meta_type
)[
0
].
lower
()):
# At least it seems a generic template field of the meta_type.
return
0.1
def
make_dict_list_append_function
(
dic
,
order_list
):
def
append
(
key
,
item
):
if
not
key
in
order_list
:
order_list
.
append
(
key
)
dic
[
key
]
=
[]
dic
[
key
].
append
(
item
)
return
append
def
add_default_field_library
():
portal_url
=
getToolByName
(
self
,
'portal_url'
)
portal
=
portal_url
.
getPortalObject
()
portal_skins
=
getToolByName
(
self
,
'portal_skins'
)
default_field_library_path
=
portal
.
getProperty
(
'erp5_default_field_library_path'
,
'erp5_core.Base_viewFieldLibrary'
)
if
(
not
default_field_library_path
or
len
(
default_field_library_path
.
split
(
'.'
))
!=
2
):
return
skinfolder_id
,
form_id
=
default_field_library_path
.
split
(
'.'
)
skinfolder
=
getattr
(
portal_skins
,
skinfolder_id
,
None
)
default_field_library
=
getattr
(
skinfolder
,
form_id
,
None
)
if
default_field_library
is
None
:
return
for
i
in
default_field_library
.
objectValues
():
field_meta_type
,
proxy_flag
=
get_field_meta_type_and_proxy_flag
(
i
)
if
meta_type
==
field_meta_type
:
if
proxy_flag
:
field_meta_type
=
'%s(Proxy)'
%
field_meta_type
matched_item
=
{
'form_id'
:
form_id
,
'field_type'
:
field_meta_type
,
'field_object'
:
i
,
'proxy_flag'
:
proxy_flag
,
'matched_rate'
:
0
}
if
not
i
in
[
item
[
'field_object'
]
for
item
in
matched
.
get
(
default_field_library_path
,
())]:
matched_append
(
default_field_library_path
,
matched_item
)
if
not
i
in
[
item
[
'field_object'
]
for
item
in
perfect_matched
.
get
(
default_field_library_path
,
())]:
perfect_matched_append
(
default_field_library_path
,
matched_item
)
id_
=
field
.
getId
()
meta_type
=
field
.
meta_type
matched
=
{}
form_order
=
[]
matched_append
=
make_dict_list_append_function
(
matched
,
form_order
)
perfect_matched
=
{}
perfect_matched_form_order
=
[]
perfect_matched_append
=
make_dict_list_append_function
(
perfect_matched
,
perfect_matched_form_order
)
if
form_field_list
is
None
:
form_field_list
=
self
.
getFormFieldList
()
for
i
in
form_field_list
:
for
data
in
i
[
'field_list'
]:
tmp
=
[]
matched_rate
=
match
(
data
)
if
matched_rate
>
0
:
form_path
=
i
[
'form_path'
]
form_id
=
i
[
'form_id'
]
field_type
=
data
[
'field_type'
]
field_object
=
data
[
'field_object'
]
proxy_flag
=
data
[
'proxy_flag'
]
matched_item
=
{
'form_id'
:
form_id
,
'field_type'
:
field_type
,
'field_object'
:
field_object
,
'proxy_flag'
:
proxy_flag
,
'matched_rate'
:
matched_rate
}
if
matched_rate
==
1
:
perfect_matched_append
(
form_path
,
matched_item
)
elif
not
perfect_matched
:
matched_append
(
form_path
,
matched_item
)
if
perfect_matched
:
perfect_matched_form_order
.
sort
()
add_default_field_library
()
return
perfect_matched_form_order
,
perfect_matched
form_order
.
sort
()
add_default_field_library
()
return
form_order
,
matched
security
.
declareProtected
(
'View management screens'
,
'getUnProxyableFieldList'
)
def
getUnProxyableFieldList
(
self
):
"""
Return ProxyFields
"""
return
sorted
([
f
for
f
in
self
.
objectValues
()
\
if
f
.
meta_type
==
'ProxyField'
],
key
=
lambda
x
:
x
.
id
)
security
.
declareProtected
(
'View management screens'
,
'getRelatedProxyFieldDictList'
)
def
getRelatedProxyFieldDictList
(
self
,
**
kw
):
"""
Retrieve all proxy using proxy in this form
"""
form_id
=
self
.
id
proxy_dict
=
{}
for
document
in
self
.
objectValues
():
short_path
=
"%s.%s"
%
(
form_id
,
document
.
id
)
proxy_dict
[
short_path
]
=
{
'proxy'
:
document
,
'short_path'
:
short_path
,
'related_proxy_list'
:
[]}
def
iterate
(
document
):
for
i
in
document
.
objectValues
():
if
i
.
meta_type
==
'ERP5 Form'
:
for
field
in
i
.
objectValues
():
if
field
.
meta_type
==
'ProxyField'
:
key
=
"%s.%s"
%
(
field
.
get_value
(
'form_id'
),
field
.
get_value
(
'field_id'
))
if
proxy_dict
.
has_key
(
key
):
proxy_dict
[
key
][
'related_proxy_list'
].
append
(
{
'short_path'
:
"%s.%s"
%
\
(
field
.
aq_parent
.
id
,
field
.
id
),
'proxy'
:
field
})
if
i
.
meta_type
==
'Folder'
:
iterate
(
i
)
skins_tool
=
self
.
portal_skins
proxy_dict_list
=
[]
if
len
(
proxy_dict
):
# for skin_folder_id in self.getSimilarSkinFolderIdList():
for
skin_folder_id
in
self
.
getPortalObject
().
portal_skins
.
objectIds
():
iterate
(
getattr
(
skins_tool
,
skin_folder_id
))
proxy_dict_list
=
proxy_dict
.
values
()
proxy_dict_list
.
sort
(
key
=
lambda
x
:
x
[
'short_path'
])
for
item
in
proxy_dict_list
:
item
[
'related_proxy_list'
].
sort
(
key
=
lambda
x
:
x
[
'short_path'
])
return
proxy_dict_list
_proxy_copy_type_list
=
(
bytes
,
unicode
,
int
,
long
,
float
,
bool
,
list
,
tuple
,
dict
,
DateTime
)
security
.
declareProtected
(
'Change Formulator Forms'
,
'proxifyField'
)
def
proxifyField
(
self
,
field_dict
=
None
,
force_delegate
=
False
,
keep_empty_value
=
False
,
REQUEST
=
None
):
"""Convert fields to proxy fields
If the field value is not empty and different from the proxyfield
value, the value is kept on the proxyfield, otherwise it is delegated.
If you specify force_delegate, values will be delegated even if they
are different. And if you specify keep_empty_value, then empty values
will not be delegated(force_delegate option is high priority).
"""
def
copy
(
field
,
value_type
):
new_dict
=
{}
for
key
,
value
in
getFieldDict
(
field
,
value_type
).
iteritems
():
if
isinstance
(
aq_base
(
value
),
(
Method
,
TALESMethod
)):
value
=
copyMethod
(
value
)
elif
not
(
value
is
None
or
isinstance
(
value
,
self
.
_proxy_copy_type_list
)):
raise
ValueError
(
'%s:%r'
%
(
type
(
value
),
value
))
elif
not
(
keep_empty_value
or
value
):
continue
new_dict
[
key
]
=
value
return
new_dict
def
is_equal
(
a
,
b
):
type_a
=
type
(
a
)
type_b
=
type
(
b
)
if
type_a
is
not
type_b
:
return
False
elif
type_a
is
Method
:
return
a
.
method_name
==
b
.
method_name
elif
type_a
is
TALESMethod
:
return
a
.
_text
==
b
.
_text
else
:
return
a
==
b
def
remove_same_value
(
new_dict
,
target_dict
):
for
key
,
value
in
new_dict
.
items
():
target_value
=
target_dict
.
get
(
key
)
if
force_delegate
or
is_equal
(
value
,
target_value
):
del
new_dict
[
key
]
return
new_dict
def
get_group_and_position
(
field_id
):
for
i
in
self
.
groups
.
keys
():
if
field_id
in
self
.
groups
[
i
]:
return
i
,
self
.
groups
[
i
].
index
(
field_id
)
def
set_group_and_position
(
group
,
position
,
field_id
):
self
.
field_removed
(
field_id
)
self
.
groups
[
group
].
insert
(
position
,
field_id
)
# Notify changes explicitly.
self
.
groups
=
self
.
groups
if
field_dict
is
None
:
return
for
field_id
in
field_dict
.
keys
():
target
=
field_dict
[
field_id
]
target_form_id
,
target_field_id
=
target
.
split
(
'.'
)
# keep current group and position.
group
,
position
=
get_group_and_position
(
field_id
)
# create proxy field
old_field
=
getattr
(
self
,
field_id
)
self
.
manage_delObjects
(
field_id
)
self
.
manage_addField
(
id
=
field_id
,
title
=
''
,
fieldname
=
'ProxyField'
)
proxy_field
=
getattr
(
self
,
field_id
)
proxy_field
.
values
[
'form_id'
]
=
target_form_id
proxy_field
.
values
[
'field_id'
]
=
target_field_id
target_field
=
proxy_field
.
getTemplateField
()
if
target_field
is
None
:
raise
ValueError
(
"Unable to find template : %s.%s"
%
(
target_form_id
,
target_field_id
))
# copy data
new_values
=
remove_same_value
(
copy
(
old_field
,
'values'
),
getFieldDict
(
target_field
,
'values'
))
new_tales
=
remove_same_value
(
copy
(
old_field
,
'tales'
),
getFieldDict
(
target_field
,
'tales'
))
if
target_field
.
meta_type
==
'ProxyField'
:
for
i
in
new_values
.
keys
():
if
not
i
in
target_field
.
delegated_list
:
# obsolete variable check
try
:
target_field
.
get_recursive_orig_value
(
i
)
except
KeyError
:
# then `i` is obsolete!
del
new_values
[
i
]
else
:
if
is_equal
(
target_field
.
get_recursive_orig_value
(
i
),
new_values
[
i
]):
del
new_values
[
i
]
for
i
in
new_tales
.
keys
():
if
not
i
in
target_field
.
delegated_list
:
# obsolete variable check
try
:
target_field
.
get_recursive_tales
(
i
)
except
KeyError
:
# then `i` is obsolete!
del
new_tales
[
i
]
else
:
if
is_equal
(
target_field
.
get_recursive_tales
(
i
),
new_tales
[
i
]):
del
new_tales
[
i
]
delegated_list
=
[]
for
i
in
(
new_values
.
keys
()
+
new_tales
.
keys
()):
if
not
i
in
delegated_list
:
delegated_list
.
append
(
i
)
proxy_field
.
values
.
update
(
new_values
)
proxy_field
.
tales
.
update
(
new_tales
)
proxy_field
.
delegated_list
=
delegated_list
# move back to the original group and position.
set_group_and_position
(
group
,
position
,
field_id
)
if
REQUEST
is
not
None
:
return
self
.
formProxify
(
manage_tabs_message
=
'Changed'
)
psyco
.
bind
(
__call__
)
psyco
.
bind
(
_exec
)
security
.
declareProtected
(
'Change Formulator Forms'
,
'unProxifyField'
)
def
unProxifyField
(
self
,
field_dict
=
None
,
copy_delegated_values
=
False
,
REQUEST
=
None
):
"""
Convert proxy fields to fields
"""
def
copy
(
field
,
value_type
):
new_dict
=
{}
for
key
,
value
in
getFieldDict
(
field
,
value_type
).
iteritems
():
if
isinstance
(
aq_base
(
value
),
(
Method
,
TALESMethod
)):
value
=
copyMethod
(
value
)
elif
not
(
value
is
None
or
isinstance
(
value
,
self
.
_proxy_copy_type_list
)):
raise
ValueError
(
'%s:%r'
%
(
type
(
value
),
value
))
new_dict
[
key
]
=
value
return
new_dict
def
is_equal
(
a
,
b
):
type_a
=
type
(
a
)
type_b
=
type
(
b
)
if
type_a
is
not
type_b
:
return
False
elif
type_a
is
Method
:
return
a
.
method_name
==
b
.
method_name
elif
type_a
is
TALESMethod
:
return
a
.
_text
==
b
.
_text
else
:
return
a
==
b
def
remove_same_value
(
new_dict
,
target_dict
):
for
key
,
value
in
new_dict
.
items
():
target_value
=
target_dict
.
get
(
key
)
if
is_equal
(
value
,
target_value
):
del
new_dict
[
key
]
return
new_dict
def
get_group_and_position
(
field_id
):
for
i
in
self
.
groups
.
keys
():
if
field_id
in
self
.
groups
[
i
]:
return
i
,
self
.
groups
[
i
].
index
(
field_id
)
def
set_group_and_position
(
group
,
position
,
field_id
):
self
.
field_removed
(
field_id
)
self
.
groups
[
group
].
insert
(
position
,
field_id
)
# Notify changes explicitly.
self
.
groups
=
self
.
groups
if
field_dict
is
None
:
return
for
field_id
in
field_dict
.
keys
():
# keep current group and position.
group
,
position
=
get_group_and_position
(
field_id
)
# create field
old_proxy_field
=
getattr
(
self
,
field_id
)
delegated_field
=
old_proxy_field
.
getRecursiveTemplateField
()
if
delegated_field
is
None
:
break
self
.
manage_delObjects
(
field_id
)
self
.
manage_addField
(
id
=
field_id
,
title
=
''
,
fieldname
=
delegated_field
.
meta_type
)
field
=
getattr
(
self
,
field_id
)
# copy data
new_values
=
remove_same_value
(
copy
(
old_proxy_field
,
'values'
),
field
.
values
)
new_tales
=
remove_same_value
(
copy
(
old_proxy_field
,
'tales'
),
field
.
tales
)
field
.
values
.
update
(
new_values
)
field
.
tales
.
update
(
new_tales
)
# move back to the original group and position.
set_group_and_position
(
group
,
position
,
field_id
)
if
REQUEST
is
not
None
:
return
self
.
formUnProxify
(
manage_tabs_message
=
'Changed'
)
# Overload of the Form method
# Use the include_disabled parameter since
# we should consider all fields to render the group tab
# moreoever, listbox rendering fails whenever enabled
# is based on the cell parameter.
security
.
declareProtected
(
'View'
,
'get_largest_group_length'
)
def
get_largest_group_length
(
self
):
"""Get the largest group length available; necessary for
'order' screen user interface.
XXX - Copyright issue
"""
max
=
0
for
group
in
self
.
get_groups
(
include_empty
=
1
):
fields
=
self
.
get_fields_in_group
(
group
,
include_disabled
=
1
)
if
len
(
fields
)
>
max
:
max
=
len
(
fields
)
return
max
security
.
declareProtected
(
'View'
,
'get_groups'
)
def
get_groups
(
self
,
include_empty
=
0
):
"""Get a list of all groups, in display order.
If include_empty is false, suppress groups that do not have
enabled fields.
XXX - Copyright issue
"""
if
include_empty
:
return
self
.
group_list
return
[
group
for
group
in
self
.
group_list
if
self
.
get_fields_in_group
(
group
,
include_disabled
=
1
)]
# Find support in ZMI. This is useful for development.
def
PrincipiaSearchSource
(
self
):
return
str
((
self
.
pt
,
self
.
name
,
self
.
action
,
self
.
update_action
,
self
.
encoding
,
self
.
stored_encoding
,
self
.
enctype
))
# 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'
:
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment