Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
E
erp5_rtl_support
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
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Romain Courteaud
erp5_rtl_support
Commits
6b4c73c5
Commit
6b4c73c5
authored
Mar 01, 2017
by
Ayush Tiwari
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
bt5_config: Added import function for BusinessManager and BusinessItem classes
parent
13245d4c
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
193 additions
and
19 deletions
+193
-19
product/ERP5/Document/BusinessManager.py
product/ERP5/Document/BusinessManager.py
+193
-19
No files found.
product/ERP5/Document/BusinessManager.py
View file @
6b4c73c5
...
...
@@ -57,6 +57,7 @@ from Products.ERP5Type import Permissions, PropertySheet, interfaces
from
AccessControl
import
ClassSecurityInfo
,
Unauthorized
,
getSecurityManager
from
Acquisition
import
Implicit
,
aq_base
,
aq_inner
,
aq_parent
from
Products.ERP5Type.Globals
import
InitializeClass
from
Products.ERP5Type.TransactionalVariable
import
getTransactionalVariable
from
zLOG
import
LOG
,
INFO
,
WARNING
from
Products.ERP5Type.patches.ppml
import
importXML
from
Products.ERP5Type.Accessor.Constant
import
PropertyGetter
as
ConstantGetter
...
...
@@ -143,7 +144,7 @@ class BusinessManager(XMLObject):
security
.
declareObjectProtected
(
Permissions
.
AccessContentsInformation
)
_properties
=
(
{
'id'
:
'template_path'
,
{
'id'
:
'template_path
_list
'
,
'type'
:
'lines'
,
'default'
:
'python: ()'
,
'acquisition_base_category'
:
(),
...
...
@@ -152,9 +153,19 @@ class BusinessManager(XMLObject):
'acquisition_accessor_id'
:
'getTemplatePathList'
,
'override'
:
1
,
'mode'
:
'w'
},
{
'id'
:
'template_format_version'
,
'type'
:
'int'
,
'default'
:
'python: 3'
,
'acquisition_base_category'
:
(),
'acquisition_portal_type'
:
(),
'acquisition_depends'
:
None
,
'acquisition_accessor_id'
:
'getTemplateFormatVersion'
,
'override'
:
1
,
'mode'
:
'w'
},
)
template_path_list
=
()
template_format_version
=
3
status
=
'uninstalled'
# Declarative security
...
...
@@ -194,9 +205,10 @@ class BusinessManager(XMLObject):
def
edit
(
self
,
**
kw
):
"""
Explicilty edit the class instance
XXX: No need of this class ? as we already have _edit from ERP5Type.Folder
"""
if
'
path_item
_list'
in
kw
:
path_item_list
=
kw
.
pop
(
'
path_item
_list'
)
if
'
template_path
_list'
in
kw
:
path_item_list
=
kw
.
pop
(
'
template_path
_list'
)
self
.
_setTemplatePathList
(
path_item_list
)
def
_setTemplatePathList
(
self
,
path_item_list
):
...
...
@@ -212,6 +224,16 @@ class BusinessManager(XMLObject):
result
=
tuple
(
result
)
return
result
def
getTemplateFormatVersion
(
self
):
return
self
.
template_format_version
def
_setTemplateFormatVersion
(
self
,
value
):
self
.
template_format_version
=
int
(
value
)
def
propertyMap
(
self
):
prop_map
=
super
(
BusinessManager
,
self
).
propertyMap
()
final_prop_map
=
prop_map
+
self
.
_properties
return
final_prop_map
security
.
declareProtected
(
Permissions
.
ManagePortal
,
'export'
)
def
export
(
self
,
path
=
None
,
local
=
0
,
bma
=
None
,
**
kw
):
...
...
@@ -221,7 +243,7 @@ class BusinessManager(XMLObject):
XXX: Are we planning to use something like archive for saving the exported
objects inside a Business Manager
"""
if
not
self
.
getStat
e
()
==
'built'
:
if
not
self
.
getStat
us
()
==
'built'
:
raise
ValueError
,
'Manager not built properly'
return
self
.
_export
(
path
,
local
,
bma
,
**
kw
)
...
...
@@ -232,7 +254,7 @@ class BusinessManager(XMLObject):
# we export into a folder tree
bma
=
BusinessManagerFolder
(
path
,
creation
=
1
)
else
:
# We export
BP
into a tarball file
# We export
bm
into a tarball file
if
path
is
None
:
path
=
self
.
getTitle
()
bma
=
BusinessManagerTarball
(
path
,
creation
=
1
)
...
...
@@ -242,15 +264,15 @@ class BusinessManager(XMLObject):
prop_type
=
prop
[
'type'
]
id
=
prop
[
'id'
]
if
id
in
(
'id'
,
'uid'
,
'rid'
,
'sid'
,
'id_group'
,
'last_id'
,
'revision'
,
'install_object_list_list'
,
'id_generator'
,
'b
p
_for_diff'
):
'install_object_list_list'
,
'id_generator'
,
'b
m
_for_diff'
):
continue
value
=
self
.
getProperty
(
id
)
if
not
value
:
continue
if
prop_type
in
(
'text'
,
'string'
,
'int'
,
'boolean'
):
b
pa
.
addObject
(
str
(
value
),
name
=
id
,
path
=
'bp
'
,
ext
=
''
)
b
ma
.
addObject
(
str
(
value
),
name
=
id
,
path
=
'bm
'
,
ext
=
''
)
elif
prop_type
in
(
'lines'
,
'tokens'
):
b
pa
.
addObject
(
'
\
n
'
.
join
(
value
),
name
=
id
,
path
=
'bp
'
,
ext
=
''
)
b
ma
.
addObject
(
'
\
n
'
.
join
(
value
),
name
=
id
,
path
=
'bm
'
,
ext
=
''
)
# Export each part
for
item
in
self
.
_path_item_list
:
...
...
@@ -258,6 +280,42 @@ class BusinessManager(XMLObject):
return
bma
.
finishCreation
()
security
.
declareProtected
(
Permissions
.
ManagePortal
,
'importFile'
)
def
importFile
(
self
,
path
):
"""
Import all xml files in Business Manager
"""
bma
=
(
BusinessManagerFolder
if
os
.
path
.
isdir
(
path
)
else
BusinessManagerTarball
)(
path
,
importing
=
1
)
bm_item
=
bm
()
bma
.
importFiles
(
bm_item
,
parent
=
self
)
prop_dict
=
{}
for
prop
in
self
.
propertyMap
():
pid
=
prop
[
'id'
]
if
pid
!=
'id'
:
prop_type
=
prop
[
'type'
]
value
=
bm_item
.
get
(
pid
)
if
prop_type
in
(
'text'
,
'string'
):
prop_dict
[
pid
]
=
value
or
''
elif
prop_type
in
(
'int'
,
'boolean'
):
prop_dict
[
pid
]
=
value
or
0
elif
prop_type
in
(
'lines'
,
'tokens'
):
# XXX: Do add pid[:-5] after we switch to proper getters and setters
prop_dict
[
pid
]
=
(
value
or
''
).
splitlines
()
# XXX: This is not working, needs to be fixed so as it copies all the
# properties from BMA to the newly created Business Manager
self
.
_edit
(
**
prop_dict
)
self
.
storeTemplateData
()
#workflow_tool = self.getPortalObject().portal_workflow
#workflow_tool.business_package_building_workflow.notifyWorkflowMethod(
# self, 'edit', kw={'comment': 'Downloaded'})
for
item_object
in
self
.
_path_item_list
:
item_object
.
importFile
(
bma
,
parent
=
self
)
# Set the status to uninstalled
self
.
setStatus
(
'uninstalled'
)
def
__add__
(
self
,
other
):
"""
Adds the Business Item objects for the given Business Manager objects
...
...
@@ -872,7 +930,7 @@ class BusinessItem(Implicit, Persistent):
path
=
self
.
__class__
.
__name__
+
'/'
# We now will add the XML object and its sha hash while exporting the object
# to Business
package
itself
# to Business
Manager
itself
# Back compatibility with filesystem Documents
key
=
self
.
_path
...
...
@@ -920,7 +978,7 @@ class BusinessItem(Implicit, Persistent):
extension
=
self
.
guessExtensionOfDocument
(
obj
,
key
,
data
if
record_id
==
'data'
else
None
)
b
p
a
.
addObject
(
StringIO
(
data
),
key
,
path
=
path
,
b
m
a
.
addObject
(
StringIO
(
data
),
key
,
path
=
path
,
ext
=
'._xml'
if
extension
==
'xml'
else
'.'
+
extension
)
break
# since we get the obj from context we should
...
...
@@ -932,6 +990,123 @@ class BusinessItem(Implicit, Persistent):
XMLExportImport
.
exportXML
(
obj
.
_p_jar
,
obj
.
_p_oid
,
f
)
bma
.
addObject
(
f
,
key
,
path
=
path
)
def
importFile
(
self
,
bma
,
parent
,
**
kw
):
bma
.
importFiles
(
self
,
parent
)
def
_importFile
(
self
,
file_name
,
file_obj
,
parent
):
obj_key
,
file_ext
=
os
.
path
.
splitext
(
file_name
)
# id() for installing several bt5 in the same transaction
transactional_variable_obj_key
=
"%s-%s"
%
(
id
(
self
),
obj_key
)
if
file_ext
!=
'.xml'
:
# For ZODB Components: if .xml have been processed before, set the
# source code property, otherwise store it in a transactional variable
# so that it can be set once the .xml has been processed
data
=
file_obj
.
read
()
try
:
obj
=
self
.
_objects
[
obj_key
]
except
KeyError
:
getTransactionalVariable
()[
transactional_variable_obj_key
]
=
data
else
:
self
.
_restoreSeparatelyExportedProperty
(
obj
,
data
)
else
:
connection
=
self
.
getConnection
(
parent
)
__traceback_info__
=
'Importing %s'
%
file_name
if
hasattr
(
cache_database
,
'db'
)
and
isinstance
(
file_obj
,
file
):
obj
=
connection
.
importFile
(
self
.
_compileXML
(
file_obj
))
else
:
# FIXME: Why not use the importXML function directly? Are there any BT5s
# with actual .zexp files on the wild?
obj
=
connection
.
importFile
(
file_obj
,
customImporters
=
customImporters
)
self
.
_value
=
obj
data
=
getTransactionalVariable
().
get
(
transactional_variable_obj_key
)
if
data
is
not
None
:
self
.
_restoreSeparatelyExportedProperty
(
obj
,
data
)
def
_restoreSeparatelyExportedProperty
(
self
,
obj
,
data
):
unicode_data
,
property_name
=
SEPARATELY_EXPORTED_PROPERTY_DICT
[
obj
.
__class__
.
__name__
][
1
:]
if
unicode_data
:
data
=
data
.
decode
(
obj
.
output_encoding
)
try
:
setattr
(
obj
,
property_name
,
data
)
except
BrokenModified
:
obj
.
__Broken_state__
[
property_name
]
=
data
obj
.
_p_changed
=
1
else
:
# Revert any work done by __setstate__.
# XXX: This is enough for all objects we currently split in 2 files,
# but __setstate__ could behave badly with the missing attribute
# and newly added types may require more than this.
self
.
removeProperties
(
obj
,
1
,
keep_workflow_history
=
True
)
def
getConnection
(
self
,
obj
):
while
True
:
connection
=
obj
.
_p_jar
if
connection
is
not
None
:
return
connection
obj
=
obj
.
aq_parent
def
_compileXML
(
self
,
file
):
# This method converts XML to ZEXP. Because the conversion
# is quite heavy, a persistent cache database is used to
# store ZEXP, so the second run wouldn't have to re-generate
# identical data again.
#
# For now, a pair of the path to an XML file and its modification time
# are used as a unique key. In theory, a checksum of the content could
# be used instead, and it could be more reliable, as modification time
# might not be updated in some insane filesystems correctly. However,
# in practice, checksums consume a lot of CPU time, so when the cache
# does not hit, the increased overhead is significant. In addition, it
# does rarely happen that two XML files in Business Manager contain
# the same data, so it may not be expected to have more cache hits
# with this approach.
#
# The disadvantage is that this wouldn't work with the archive format,
# because each entry in an archive does not have a mtime in itself.
# However, the plan is to have an archive to retain ZEXP directly
# instead of XML, so the idea of caching would be completely useless
# with the archive format.
name
=
file
.
name
mtime
=
os
.
path
.
getmtime
(
file
.
name
)
key
=
'%s:%s'
%
(
name
,
mtime
)
try
:
return
StringIO
(
cache_database
.
db
[
key
])
except
:
pass
from
Shared.DC.xml
import
ppml
from
OFS.XMLExportImport
import
start_zopedata
,
save_record
,
save_zopedata
import
xml.parsers.expat
outfile
=
StringIO
()
try
:
data
=
file
.
read
()
F
=
ppml
.
xmlPickler
()
F
.
end_handlers
[
'record'
]
=
save_record
F
.
end_handlers
[
'ZopeData'
]
=
save_zopedata
F
.
start_handlers
[
'ZopeData'
]
=
start_zopedata
F
.
binary
=
1
F
.
file
=
outfile
p
=
xml
.
parsers
.
expat
.
ParserCreate
(
'utf-8'
)
p
.
returns_unicode
=
False
p
.
CharacterDataHandler
=
F
.
handle_data
p
.
StartElementHandler
=
F
.
unknown_starttag
p
.
EndElementHandler
=
F
.
unknown_endtag
p
.
Parse
(
data
)
try
:
cache_database
.
db
[
key
]
=
outfile
.
getvalue
()
except
:
pass
outfile
.
seek
(
0
)
return
outfile
except
:
outfile
.
close
()
raise
def
getBusinessPath
(
self
):
return
self
.
_path
...
...
@@ -956,7 +1131,7 @@ class BusinessItem(Implicit, Persistent):
class
BusinessManagerArchive
(
object
):
"""
This is the base class for all Business
Template
archives
This is the base class for all Business
Manager
archives
"""
def
__init__
(
self
,
path
,
**
kw
):
...
...
@@ -989,7 +1164,7 @@ class BusinessManagerArchive(object):
class
BusinessManagerFolder
(
BusinessManagerArchive
):
"""
Class archiving business
template
into a folder tree
Class archiving business
manager
into a folder tree
"""
def
_writeString
(
self
,
obj
,
path
):
...
...
@@ -1002,11 +1177,10 @@ class BusinessManagerFolder(BusinessManagerArchive):
finally
:
f
.
close
()
def
importFiles
(
self
,
item
):
def
importFiles
(
self
,
item
,
parent
):
"""
Import file from a local folder
"""
join
=
os
.
path
.
join
item_name
=
item
.
__class__
.
__name__
root
=
join
(
os
.
path
.
normpath
(
self
.
path
),
item_name
,
''
)
...
...
@@ -1028,7 +1202,7 @@ class BusinessManagerFolder(BusinessManagerArchive):
continue
# self.revision.hash(item_name + '/' + file_name, f.read())
f
.
seek
(
0
)
item
.
_importFile
(
file_name
,
f
)
item
.
_importFile
(
file_name
,
f
,
parent
)
finally
:
if
hasattr
(
cache_database
,
'db'
):
cache_database
.
db
.
close
()
...
...
@@ -1070,7 +1244,7 @@ class BusinessManagerTarball(BusinessManagerArchive):
self
.
tar
.
close
()
return
self
.
fobj
def
importFiles
(
self
,
item
):
def
importFiles
(
self
,
item
,
parent
):
"""
Import all file from the archive to the site
"""
...
...
@@ -1084,15 +1258,15 @@ class BusinessManagerTarball(BusinessManagerArchive):
f
=
extractfile
(
info
)
self
.
revision
.
hash
(
item_name
+
'/'
+
file_name
,
f
.
read
())
f
.
seek
(
0
)
item
.
_importFile
(
file_name
,
f
)
item
.
_importFile
(
file_name
,
f
,
parent
)
class
bm
(
dict
):
"""
Fake 'bm' item to read b
p
/* files through BusinessManagerArchive
Fake 'bm' item to read b
m
/* files through BusinessManagerArchive
"""
def
_importFile
(
self
,
file_name
,
file
):
def
_importFile
(
self
,
file_name
,
file
,
parent
):
self
[
file_name
]
=
file
.
read
()
#InitializeClass(BusinessManager)
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