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
Labels
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Commits
Open sidebar
Romain Courteaud
erp5
Commits
126ae257
Commit
126ae257
authored
Sep 23, 2022
by
Kazuhiko Shiozaki
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
fixup! py2/py3: dict_key does not have sort().
parent
c98ecf4a
Changes
9
Show whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
44 additions
and
59 deletions
+44
-59
product/ERP5/Document/BusinessTemplate.py
product/ERP5/Document/BusinessTemplate.py
+26
-30
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Base_callDialogMethod.py
...plateItem/portal_skins/erp5_core/Base_callDialogMethod.py
+3
-3
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/BusinessTemplate_getDiffObjectList.py
...tal_skins/erp5_core/BusinessTemplate_getDiffObjectList.py
+2
-6
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/BusinessTemplate_getModifiedObject.py
...tal_skins/erp5_core/BusinessTemplate_getModifiedObject.py
+3
-5
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/ListBox_initializeFastInput.py
...tem/portal_skins/erp5_core/ListBox_initializeFastInput.py
+1
-1
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/TemplateTool_getModifiedObjectList.py
...tal_skins/erp5_core/TemplateTool_getModifiedObjectList.py
+2
-2
product/ERP5Type/XMLExportImport/__init__.py
product/ERP5Type/XMLExportImport/__init__.py
+5
-7
product/Localizer/MessageCatalog.py
product/Localizer/MessageCatalog.py
+1
-3
product/MailTemplates/BaseMailTemplate.py
product/MailTemplates/BaseMailTemplate.py
+1
-2
No files found.
product/ERP5/Document/BusinessTemplate.py
View file @
126ae257
...
...
@@ -536,7 +536,7 @@ class BaseTemplateItem(Implicit, Persistent):
# if you choose remove, the object and all its subobjects will be removed
# even if you choose backup or keep for subobjects
# it is same behaviour for backup_and_remove, all we be save
for
path
in
sorted
(
self
.
_objects
.
keys
()
):
for
path
in
sorted
(
self
.
_objects
):
if
path
in
remove_dict
:
action
=
remove_dict
[
path
]
if
action
==
'save_and_remove'
:
...
...
@@ -1193,7 +1193,7 @@ class ObjectTemplateItem(BaseTemplateItem):
def
_getObjectKeyList
(
self
):
# sort to add objects before their subobjects
return
sorted
(
self
.
_objects
.
keys
()
)
return
sorted
(
self
.
_objects
)
def
unindexBrokenObject
(
self
,
item_path
):
"""
...
...
@@ -1446,7 +1446,7 @@ class ObjectTemplateItem(BaseTemplateItem):
#remove previous owners
local_role_dict
=
obj
.
__ac_local_roles__
removable_role_key_list
=
[]
for
key
,
value
in
local_role_dict
.
items
(
):
for
key
,
value
in
six
.
iteritems
(
local_role_dict
):
if
'Owner'
in
value
:
value
.
remove
(
'Owner'
)
if
len
(
value
)
==
0
:
...
...
@@ -1985,7 +1985,7 @@ class CategoryTemplateItem(ObjectTemplateItem):
# as PathTemplateItem.install
kw
[
'object_to_update'
]
=
{
path
:
action
for
(
path
,
action
)
in
ensure_list
(
kw
[
'object_to_update'
].
items
()
)
for
(
path
,
action
)
in
six
.
iteritems
(
kw
[
'object_to_update'
]
)
if
path
.
split
(
'/'
)[:
-
1
]
==
[
'portal_categories'
]
or
path
in
self
.
_objects
}
return
super
(
CategoryTemplateItem
,
self
).
install
(
context
,
trashbin
,
**
kw
)
...
...
@@ -2075,11 +2075,11 @@ class RegisteredSkinSelectionTemplateItem(BaseTemplateItem):
# Function to generate XML Code Manually
def
generateXml
(
self
,
path
=
None
):
xml_data
=
'<registered_skin_selection>'
for
key
in
sorted
(
self
.
_objects
.
keys
(
)):
for
key
,
value
in
sorted
(
six
.
iteritems
(
self
.
_objects
)):
xml_data
+=
'
\
n
<skin_folder_selection>'
xml_data
+=
'
\
n
<skin_folder>%s</skin_folder>'
%
key
xml_data
+=
'
\
n
<skin_selection>%s</skin_selection>'
\
%
','
.
join
(
sorted
(
self
.
_objects
[
key
]
))
%
','
.
join
(
sorted
(
value
))
xml_data
+=
'
\
n
</skin_folder_selection>'
xml_data
+=
'
\
n
</registered_skin_selection>'
return
xml_data
...
...
@@ -2551,11 +2551,11 @@ class PortalTypeWorkflowChainTemplateItem(BaseTemplateItem):
# Function to generate XML Code Manually
def
generateXml
(
self
,
path
=
None
):
xml_data
=
'<workflow_chain>'
for
key
in
sorted
(
self
.
_objects
.
keys
(
)):
for
key
,
value
in
sorted
(
six
.
iteritems
(
self
.
_objects
)):
xml_data
+=
'
\
n
<chain>'
xml_data
+=
'
\
n
<type>%s</type>'
%
(
key
,)
xml_data
+=
'
\
n
<workflow>%s</workflow>'
%
(
self
.
_chain_string_separator
.
join
(
sorted
(
self
.
_objects
[
key
]
)))
self
.
_chain_string_separator
.
join
(
sorted
(
value
)))
xml_data
+=
'
\
n
</chain>'
xml_data
+=
'
\
n
</workflow_chain>'
return
xml_data
...
...
@@ -2765,11 +2765,10 @@ class PortalTypeAllowedContentTypeTemplateItem(BaseTemplateItem):
# Function to generate XML Code Manually
def
generateXml
(
self
,
path
=
None
):
xml_data
=
'<%s>'
%
(
self
.
xml_tag
,)
for
key
in
sorted
(
self
.
_objects
.
keys
(
)):
for
key
,
value
in
sorted
(
six
.
iteritems
(
self
.
_objects
)):
id_value
=
key
.
replace
(
'%s/'
%
self
.
class_property
,
''
)
allowed_item_list
=
sorted
(
self
.
_objects
[
key
])
xml_data
+=
'
\
n
<portal_type id="%s">'
%
(
id_value
)
for
allowed_item
in
allowed_item_list
:
for
allowed_item
in
sorted
(
value
)
:
xml_data
+=
'
\
n
<item>%s</item>'
%
(
allowed_item
,)
xml_data
+=
'
\
n
</portal_type>'
xml_data
+=
'
\
n
</%s>'
%
(
self
.
xml_tag
,)
...
...
@@ -2996,7 +2995,7 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
method_id
=
obj
.
id
xml_data
=
'<catalog_method>'
if
method_id
in
self
.
_method_properties
:
for
method_property
,
value
in
s
elf
.
_method_properties
[
method_id
].
items
(
):
for
method_property
,
value
in
s
ix
.
iteritems
(
self
.
_method_properties
[
method_id
]
):
xml_data
+=
'
\
n
<item key="%s" type="int">'
%
(
method_property
,)
xml_data
+=
'
\
n
<value>%s</value>'
%
(
value
,)
xml_data
+=
'
\
n
</item>'
...
...
@@ -3047,9 +3046,7 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
script_class
=
getattr
(
erp5
.
portal_type
,
'Python Script'
)
portal
=
self
.
getPortalObject
()
# Will be modifying dict, so better to use .items()
# XXX: In python3 it should be .copy.items().
for
path
,
obj
in
ensure_list
(
self
.
_objects
.
items
()):
for
path
,
obj
in
six
.
iteritems
(
self
.
_objects
):
method
=
self
.
unrestrictedResolveValue
(
portal
,
path
)
method_id
=
path
.
split
(
'/'
)[
-
1
]
if
method
.
meta_type
==
'Z SQL Method'
:
...
...
@@ -3060,7 +3057,7 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
self
.
_objects
[
path
]
=
new_obj
if
force
:
# get all objects
values
=
ensure_list
(
self
.
_objects
.
values
()
)
values
=
six
.
itervalues
(
self
.
_objects
)
else
:
# get only selected object
for
key
,
value
in
six
.
iteritems
(
self
.
_objects
):
if
key
in
update_dict
or
force
:
...
...
@@ -3153,7 +3150,7 @@ class CatalogMethodTemplateItem(ObjectTemplateItem):
object_path
=
kw
.
get
(
'object_path'
,
None
)
# get required values
if
object_path
is
None
:
values
=
ensure_list
(
self
.
_objects
.
values
()
)
values
=
six
.
itervalues
(
self
.
_objects
)
else
:
try
:
value
=
self
.
_objects
[
object_path
]
...
...
@@ -3653,7 +3650,7 @@ class SitePropertyTemplateItem(BaseTemplateItem):
if
len
(
self
.
_objects
)
==
0
:
return
xml_data
=
'<site_property>'
for
path
in
sorted
(
self
.
_objects
.
keys
()
):
for
path
in
sorted
(
self
.
_objects
):
xml_data
+=
self
.
generateXml
(
path
)
xml_data
+=
'
\
n
</site_property>'
bta
.
addObject
(
xml_data
,
name
=
'properties'
,
path
=
self
.
__class__
.
__name__
)
...
...
@@ -3677,12 +3674,11 @@ class ModuleTemplateItem(BaseTemplateItem):
def
generateXml
(
self
,
path
=
None
):
mapping
=
self
.
_objects
[
path
]
xml_data
=
[
'<module>'
]
for
key
in
sorted
(
mapping
):
for
key
,
value
in
sorted
(
six
.
iteritems
(
mapping
)
):
if
key
==
'permission_list'
:
# separe permission dict into xml
xml_data
.
append
(
' <%s>'
%
(
key
,
))
permission_list
=
mapping
[
key
]
for
perm
in
permission_list
:
for
perm
in
value
:
# the type of the permission defined if we use acquired or not
if
isinstance
(
perm
[
1
],
list
):
ptype
=
"list"
...
...
@@ -3703,7 +3699,7 @@ class ModuleTemplateItem(BaseTemplateItem):
xml_data
.
append
(
' </permission>'
)
xml_data
.
append
(
' </%s>'
%
(
key
,
))
elif
key
==
'category_list'
:
category_list
=
mapping
[
key
]
category_list
=
value
if
not
category_list
:
continue
xml_data
.
append
(
' <%s>'
%
(
key
,
))
...
...
@@ -3719,7 +3715,7 @@ class ModuleTemplateItem(BaseTemplateItem):
if
len
(
self
.
_objects
)
==
0
:
return
path
=
self
.
__class__
.
__name__
for
key
in
sorted
(
self
.
_objects
.
keys
()
):
for
key
in
sorted
(
self
.
_objects
):
# export modules one by one
xml_data
=
self
.
generateXml
(
path
=
key
)
bta
.
addObject
(
xml_data
,
name
=
key
,
path
=
path
)
...
...
@@ -4629,7 +4625,7 @@ class CatalogUniqueKeyTemplateItemBase(CatalogKeyTemplateItemBase):
for
key
in
key_list
)
def
_getListFromKeyMap
(
self
,
key_map
):
return
[
" | "
.
join
(
item
)
for
item
in
sorted
(
key_map
.
items
(
))]
return
[
" | "
.
join
(
item
)
for
item
in
sorted
(
six
.
iteritems
(
key_map
))]
def
_getUpdatedCatalogKeyList
(
self
,
catalog_key_list
,
new_key_list
):
# treat key lists as dictionaries, parse and update:
...
...
@@ -4784,7 +4780,7 @@ class MessageTranslationTemplateItem(BaseTemplateItem):
localizer
=
context
.
getPortalObject
().
Localizer
update_dict
=
kw
.
get
(
'object_to_update'
,
{})
force
=
kw
.
get
(
'force'
)
for
key
in
sorted
(
self
.
_objects
.
keys
(
)):
for
key
,
value
in
sorted
(
six
.
iteritems
(
self
.
_objects
)):
if
key
in
update_dict
or
force
:
if
not
force
:
action
=
update_dict
[
key
]
...
...
@@ -4793,7 +4789,7 @@ class MessageTranslationTemplateItem(BaseTemplateItem):
lang
,
catalog
=
self
.
_splitKey
(
key
)
if
catalog
is
None
:
name
=
self
.
_objects
[
key
]
name
=
value
for
lang_dict
in
localizer
.
get_all_languages
():
if
lang_dict
[
'code'
]
==
lang
:
# When the Localizer has the language as a user-defined
...
...
@@ -4810,7 +4806,7 @@ class MessageTranslationTemplateItem(BaseTemplateItem):
if
lang
not
in
localizer
.
get_languages
():
localizer
.
manage_addLanguage
(
lang
)
else
:
po
=
self
.
_objects
[
key
]
po
=
value
if
lang
not
in
localizer
.
get_languages
():
localizer
.
manage_addLanguage
(
lang
)
self
.
_importCatalogLanguage
(
localizer
,
catalog
,
lang
,
po
)
...
...
@@ -4904,7 +4900,7 @@ class LocalRolesTemplateItem(BaseTemplateItem):
xml_data
=
'<local_roles_item>'
# local roles
xml_data
+=
'
\
n
<local_roles>'
for
user_id
,
role_list
in
sorted
(
local_roles_dict
.
items
(
)):
for
user_id
,
role_list
in
sorted
(
six
.
iteritems
(
local_roles_dict
)):
if
'Owner'
in
role_list
:
# We don't export Owner role as it set automatically when installing business template.
role_list
.
remove
(
'Owner'
)
...
...
@@ -4919,7 +4915,7 @@ class LocalRolesTemplateItem(BaseTemplateItem):
# local roles group id dict (not included by default to be stable with
# old bts)
xml_data
+=
'
\
n
<local_role_group_ids>'
for
local_role_group_id
,
local_roles_group_id_list
in
sorted
(
local_roles_group_id_dict
.
items
(
)):
for
local_role_group_id
,
local_roles_group_id_list
in
sorted
(
six
.
iteritems
(
local_roles_group_id_dict
)):
xml_data
+=
"
\
n
<local_role_group_id id='%s'>"
%
escape
(
local_role_group_id
)
for
principal
,
role
in
sorted
(
local_roles_group_id_list
):
xml_data
+=
"
\
n
<principal id='%s'>%s</principal>"
%
\
...
...
@@ -4984,7 +4980,7 @@ class LocalRolesTemplateItem(BaseTemplateItem):
# We ignore the owner defined in local_roles_dict and set it to the user installing that business template.
local_roles_dict
=
deepcopy
(
local_roles_dict
)
for
user_id
,
group_list
in
list
(
local_roles_dict
.
items
()):
for
user_id
,
group_list
in
ensure_
list
(
local_roles_dict
.
items
()):
if
group_list
==
[
"Owner"
]:
del
local_roles_dict
[
user_id
]
current_user
=
getSecurityManager
().
getUser
()
...
...
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/Base_callDialogMethod.py
View file @
126ae257
...
...
@@ -2,6 +2,7 @@
Generic method called when submitting a form in dialog mode.
Responsible for validating form data and redirecting to the form action.
"""
import
six
# XXX We should not use meta_type properly,
# XXX We need to discuss this problem.(yusei)
...
...
@@ -131,9 +132,8 @@ if len(listbox_id_list):
for
listbox_id
in
listbox_id_list
:
listbox_line_list
=
[]
listbox
=
kw
[
listbox_id
]
listbox_keys
=
listbox
.
keys
()
for
key
in
sorted
(
listbox_keys
):
listbox_line
=
listbox
[
key
]
for
key
,
value
in
sorted
(
six
.
iteritems
(
listbox
)):
listbox_line
=
value
listbox_line
[
'listbox_key'
]
=
key
listbox_line_list
.
append
(
listbox_line
)
listbox_line_list
=
tuple
(
listbox_line_list
)
...
...
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/BusinessTemplate_getDiffObjectList.py
View file @
126ae257
...
...
@@ -35,16 +35,12 @@ if p.portal_templates.compareVersions(bt1.getVersion(), bt2.getVersion()) < 0:
else
:
modified_object_list
=
getModifiedObjectList
(
bt1
,
bt2
)
keys
=
modified_object_list
.
keys
()
i
=
0
object_list
=
[]
for
object_id
in
sorted
(
keys
):
object_state
,
object_class
=
modified_object_list
[
object_id
]
for
i
,
(
object_id
,
value
)
in
enumerate
(
sorted
(
six
.
iteritems
(
modified_object_list
))
):
object_state
,
object_class
=
value
line
=
newTempBase
(
context
,
'tmp_install_%s'
%
(
str
(
i
)))
line
.
edit
(
object_id
=
object_id
,
object_state
=
object_state
,
object_class
=
object_class
,
bt1
=
bt1
.
getId
(),
bt2
=
bt2
.
getId
())
line
.
setUid
(
'new_%s'
%
object_id
)
object_list
.
append
(
line
)
i
+=
1
return
object_list
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/BusinessTemplate_getModifiedObject.py
View file @
126ae257
from
Products.ERP5Type.Document
import
newTempBase
from
Products.ERP5Type.Cache
import
CachingMethod
from
Products.ERP5Type.Utils
import
ensure_list
import
six
Base_translateString
=
context
.
Base_translateString
def
getModifiedObjectList
(
context
):
...
...
@@ -21,7 +22,6 @@ getModifiedObjectList = CachingMethod(getModifiedObjectList,
cache_id_generator
=
cache_id_generator
)
modified_object_list
=
getModifiedObjectList
(
context
)
keys
=
ensure_list
(
modified_object_list
.
keys
())
no_backup_list
=
[
'Action'
,
'SiteProperty'
,
'Module'
,
'Document'
,
'PropertySheet'
,
'Extension'
,
'Test'
,
'Product'
,
'Role'
,
...
...
@@ -40,10 +40,9 @@ backup_title = Base_translateString('Backup And Upgrade')
remove_title
=
Base_translateString
(
'Remove'
)
save_and_remove_title
=
Base_translateString
(
'Backup And Remove'
)
i
=
0
object_list
=
[]
for
object_id
in
sorted
(
keys
):
object_state
,
object_class
=
modified_object_list
[
object_id
]
for
i
,
(
object_id
,
value
)
in
enumerate
(
sorted
(
six
.
iteritems
(
modified_object_list
))
):
object_state
,
object_class
=
value
line
=
newTempBase
(
context
,
'tmp_install_%s'
%
(
str
(
i
)))
if
object_state
==
'New'
:
choice_item_list
=
[[
install_title
,
'install'
]]
...
...
@@ -66,7 +65,6 @@ for object_id in sorted(keys):
choice_item_list
=
choice_item_list
)
line
.
setUid
(
'new_%s'
%
str
(
object_id
))
object_list
.
append
(
line
)
i
+=
1
object_list
.
sort
(
key
=
lambda
x
:(
x
.
object_class
,
x
.
object_state
))
return
object_list
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/ListBox_initializeFastInput.py
View file @
126ae257
...
...
@@ -19,7 +19,7 @@ if hasattr(request, listbox_id):
# initialize the listbox
listbox
=
request
[
listbox_id
]
keys_list
=
sorted
(
listbox
.
keys
()
,
key
=
int
)
keys_list
=
sorted
(
listbox
,
key
=
int
)
if
keys_list
!=
[]:
first_empty_line_id
=
int
(
keys_list
[
-
1
])
+
1
...
...
product/ERP5/bootstrap/erp5_core/SkinTemplateItem/portal_skins/erp5_core/TemplateTool_getModifiedObjectList.py
View file @
126ae257
import
six
REQUEST
=
container
.
REQUEST
Base_translateString
=
context
.
Base_translateString
...
...
@@ -45,8 +46,7 @@ save_and_remove_title = Base_translateString('Backup And Remove')
for
bt
in
bt_id_list
:
bt_title
,
modified_object_list
=
bt_object_dict
[
bt
]
keys
=
modified_object_list
.
keys
()
for
i
,
object_id
in
enumerate
(
sorted
(
keys
)):
for
i
,
(
object_id
,
value
)
in
enumerate
(
sorted
(
six
.
iteritems
(
modified_object_list
))):
object_state
,
object_class
=
modified_object_list
[
object_id
]
object_id
=
bt
+
'|'
+
object_id
line
=
newTempBase
(
context
,
'tmp_install_%s'
%
i
)
...
...
product/ERP5Type/XMLExportImport/__init__.py
View file @
126ae257
...
...
@@ -143,26 +143,24 @@ def Base_asXML(object, root=None):
# We have to describe the workflow history
if
getattr
(
self
,
'workflow_history'
,
None
)
is
not
None
:
workflow_list
=
self
.
workflow_history
workflow_list_keys
=
workflow_list
.
keys
()
for
workflow_id
in
sorted
(
workflow_list_keys
):
# Make sure it is sorted
for
workflow_action
in
workflow_
list
[
workflow_id
]
:
for
workflow_id
,
workflow_action_list
in
sorted
(
six
.
iteritems
(
workflow_list
)
):
# Make sure it is sorted
for
workflow_action
in
workflow_
action_list
:
workflow_node
=
SubElement
(
object
,
'workflow_action'
,
attrib
=
dict
(
workflow_id
=
workflow_id
))
workflow_variable_list
=
workflow_action
.
keys
()
for
workflow_variable
in
sorted
(
workflow_variable_list
):
for
workflow_variable
,
variable_node_text
in
sorted
(
six
.
iteritems
(
workflow_action
)
):
variable_type
=
"string"
# Somewhat bad, should find a better way
if
workflow_variable
.
find
(
'time'
)
>=
0
:
variable_type
=
"date"
if
workflow_variable
.
find
(
'language_revs'
)
>=
0
:
# XXX specific to cps
variable_type
=
"dict"
if
workflow_action
[
workflow_variable
]
is
None
:
if
variable_node_text
is
None
:
variable_type
=
'None'
variable_node
=
SubElement
(
workflow_node
,
workflow_variable
,
attrib
=
dict
(
type
=
variable_type
))
if
variable_type
!=
'None'
:
variable_node_text
=
str
(
workflow_action
[
workflow_variable
])
variable_node
.
text
=
six
.
text_type
(
variable_node_text
,
'utf-8'
)
variable_node
.
text
=
six
.
text_type
(
str
(
variable_node_text
),
'utf-8'
)
if
workflow_variable
==
'time'
:
time
=
variable_node
.
text
...
...
product/Localizer/MessageCatalog.py
View file @
126ae257
...
...
@@ -644,10 +644,8 @@ class MessageCatalog(LanguageManager, ObjectManager, SimpleItem):
return
x
# Generate sorted msgids to simplify diffs
dkeys
=
d
.
keys
()
for
k
in
sorted
(
dkeys
):
for
k
,
v
in
sorted
(
six
.
iteritems
(
d
)):
r
.
append
(
'msgid "%s"'
%
backslashescape
(
k
))
v
=
d
[
k
]
r
.
append
(
'msgstr "%s"'
%
backslashescape
(
v
))
r
.
append
(
''
)
...
...
product/MailTemplates/BaseMailTemplate.py
View file @
126ae257
...
...
@@ -118,8 +118,7 @@ class BaseMailTemplate:
# we want to have it stored in ERP5, for mail threading
headers
[
'Message-ID'
]
=
make_msgid
()
# turn headers into an ordered list for predictable header order
keys
=
headers
.
keys
()
return
msg
,
values
,[(
key
,
headers
[
key
])
for
key
in
sorted
(
keys
)]
return
msg
,
values
,
[(
key
,
value
)
for
key
,
value
in
sorted
(
six
.
iteritems
(
headers
))]
security
.
declarePrivate
(
'_send'
)
def
_send
(
self
,
mfrom
,
mto
,
msg
):
...
...
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