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
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
Iliya Manolov
erp5
Commits
4c03bfef
Commit
4c03bfef
authored
Jan 20, 2012
by
Arnaud Fontaine
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Make migration code of ZODB Property sheets for Business Template more generic and add Components.
parent
ad765939
Changes
1
Show whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
179 additions
and
128 deletions
+179
-128
product/ERP5/Document/BusinessTemplate.py
product/ERP5/Document/BusinessTemplate.py
+179
-128
No files found.
product/ERP5/Document/BusinessTemplate.py
View file @
4c03bfef
...
@@ -3478,67 +3478,56 @@ class DocumentTemplateItem(BaseTemplateItem):
...
@@ -3478,67 +3478,56 @@ class DocumentTemplateItem(BaseTemplateItem):
text
=
file
.
read
()
text
=
file
.
read
()
self
.
_objects
[
file_name
[:
-
3
]]
=
text
self
.
_objects
[
file_name
[:
-
3
]]
=
text
class
PropertySheet
TemplateItem
(
DocumentTemplateItem
,
class
FilesystemToZodb
TemplateItem
(
DocumentTemplateItem
,
ObjectTemplateItem
):
ObjectTemplateItem
):
"""
"""
Property Sheets are now stored in ZODB, rather than the filesystem.
Abstract class to allow migration from DocumentTemplateItem to
However, Some Business Template may still have filesystem Property
ObjectTemplateItem, this is useful for migration from filesystem to ZODB for
Sheets, which need to be migrated to the ZODB.
PropertySheets and Components
This migration is performed in two steps:
1/ Specify explicitly in the web user interface that the Property
Sheets should be migrated.
2/ The Property Sheets will all be migrated when installing the
Business Template.
Therefore, this is an all or nothing migration, meaning that only
methods of DocumentTemplateItem will be called before the migration
has been performed, then ObjectTemplateItem methods afterwards.
"""
"""
# If set to False, then the migration of Property Sheets will never
# If set to False, then the migration from filesystem to ZODB will be
# be performed, required until the code of ZODB Property Sheets is
# performed, meaningful only until the code is stable
# stable and completely documented
_perform_migration
=
True
_perform_migration
=
True
# Only meaningful for filesystem Property Sheets
_tool_id
=
None
local_file_reader_name
=
staticmethod
(
readLocalPropertySheet
)
local_file_writer_name
=
staticmethod
(
writeLocalPropertySheet
)
@
staticmethod
local_file_importer_name
=
staticmethod
(
importLocalPropertySheet
)
def
_getZodbObjectId
(
id
):
local_file_remover_name
=
staticmethod
(
removeLocalPropertySheet
)
return
id
def
__init__
(
self
,
id_list
,
tool_id
=
None
,
context
=
None
,
**
kw
):
if
tool_id
is
None
:
tool_id
=
self
.
_tool_id
def
__init__
(
self
,
id_list
,
tool_id
=
'portal_property_sheets'
,
context
=
None
,
**
kw
):
tool
=
None
tool
=
None
if
context
is
not
None
and
len
(
id_list
):
if
context
is
not
None
and
len
(
id_list
):
# XXX looking up a tool early in the install process might
# XXX looking up a tool early in the install process might
# cause issues. If it does, we'll have to consider moving this
# cause issues. If it does, we'll have to consider moving this
# to build()
# to build()
tool
=
getattr
(
context
.
getPortalObject
(),
tool_id
,
None
)
tool
=
getattr
(
context
.
getPortalObject
(),
self
.
_
tool_id
,
None
)
if
tool
is
not
None
:
if
tool
is
not
None
:
existing_
property_sheet_
set
=
set
(
tool
.
objectIds
())
existing_set
=
set
(
tool
.
objectIds
())
for
i
,
id
in
enumerate
(
id_list
):
for
i
,
id
in
enumerate
(
id_list
):
if
id
in
existing_
property_sheet_
set
:
if
id
in
existing_set
:
# if the
property shee
t is on ZODB, use it.
# if the
objec
t is on ZODB, use it.
id_list
[
i
]
=
"%s/%s"
%
(
tool_id
,
id
)
id_list
[
i
]
=
"%s/%s"
%
(
self
.
_tool_id
,
self
.
_getZodbObjectId
(
id
)
)
BaseTemplateItem
.
__init__
(
self
,
id_list
,
**
kw
)
BaseTemplateItem
.
__init__
(
self
,
id_list
,
**
kw
)
@
staticmethod
def
_is_already_migrated
(
self
,
object_key_list
):
def
_is_already_migrated
(
object_key_list
):
"""
"""
The Property Sheets have already been migrated if any keys withi
n
Objects have already been migrated if any keys within the give
n
the given object_key_list (either '_objects.keys()' or
object_key_list (either '_objects.keys()' or '_archive.keys()') contains a
'_archive.keys()') contains a key starting by 'portal_property_sheets
/'
key starting by 'tool_id
/'
"""
"""
return
len
(
object_key_list
)
!=
0
and
\
return
len
(
object_key_list
)
!=
0
and
\
object_key_list
[
0
].
startswith
(
'portal_property_sheets
/'
)
object_key_list
[
0
].
startswith
(
self
.
_tool_id
+
'
/'
)
def
_filesystemCompatibilityWrapper
(
method_name
,
object_dict_name
):
def
_filesystemCompatibilityWrapper
(
method_name
,
object_dict_name
):
"""
"""
Call ObjectTemplateItem method when the
Property Sheets have
Call ObjectTemplateItem method when the
objects have already been
already been migrated, otherwise fallback on DocumentTemplateItem
migrated, otherwise fallback on DocumentTemplateItem method for
method for
backward-compatibility
backward-compatibility
"""
"""
def
inner
(
self
,
*
args
,
**
kw
):
def
inner
(
self
,
*
args
,
**
kw
):
if
self
.
_is_already_migrated
(
getattr
(
self
,
object_dict_name
).
keys
()):
if
self
.
_is_already_migrated
(
getattr
(
self
,
object_dict_name
).
keys
()):
...
@@ -3548,7 +3537,7 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
...
@@ -3548,7 +3537,7 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
if
method_name
==
'preinstall'
:
if
method_name
==
'preinstall'
:
old_result
=
result
.
copy
()
old_result
=
result
.
copy
()
for
k
,
v
in
old_result
.
iteritems
():
for
k
,
v
in
old_result
.
iteritems
():
if
not
k
.
startswith
(
'portal_property_sheets
/'
):
if
not
k
.
startswith
(
self
.
_tool_id
+
'
/'
):
result
.
pop
(
k
)
result
.
pop
(
k
)
# Magical way to have unique path in case of not yet migrated property
# Magical way to have unique path in case of not yet migrated property
# sheets available on preinstall list
# sheets available on preinstall list
...
@@ -3581,49 +3570,27 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
...
@@ -3581,49 +3570,27 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
else
:
else
:
return
DocumentTemplateItem
.
uninstall
(
self
,
*
args
,
**
kw
)
return
DocumentTemplateItem
.
uninstall
(
self
,
*
args
,
**
kw
)
@
staticmethod
def
remove
(
self
,
context
,
**
kw
):
def
_getFilesystemPropertySheetPath
(
class_id
):
"""
"""
From the given class identifier, return the complete path of the
Conversion of magically uniqued paths to real ones
filesystem Property Sheet class. Only meaningful when the Business
Template has already been installed previously, otherwise the
"""
"""
from
App.config
import
getConfiguration
remove_object_dict
=
kw
.
get
(
'remove_object_dict'
,
{})
return
os
.
path
.
join
(
getConfiguration
().
instancehome
,
new_remove_dict
=
dict
()
"PropertySheet"
,
for
k
,
v
in
remove_object_dict
.
iteritems
():
"%s.py"
%
class_id
)
if
k
.
startswith
(
self
.
getTemplateTypeName
()
+
'/'
):
new_remove_dict
[
self
.
_getPath
(
k
)]
=
v
kw
[
'remove_object_dict'
]
=
new_remove_dict
ObjectTemplateItem
.
remove
(
self
,
context
,
**
kw
)
@
staticmethod
@
staticmethod
def
_migrateFilesystemPropertySheet
(
property_sheet_tool
,
def
_getFilesystemPath
(
class_id
):
filesystem_property_sheet_path
,
raise
NotImplementedError
filesystem_property_sheet_file
,
class_id
):
"""
Migration of a filesystem Property Sheet involves loading the
class from 'instancehome/PropertySheet/<class_id>', then create
the ZODB Property Sheets in portal_property_sheets from its
filesystem definition
"""
# The first parameter of 'load_source' is the module name where
# the class will be stored, thus don't only use the class name as
# it may clash with already loaded module, such as
# BusinessTemplate.
module
=
imp
.
load_source
(
'Migrate%sFilesystemPropertySheet'
%
class_id
,
filesystem_property_sheet_path
,
filesystem_property_sheet_file
)
try
:
klass
=
getattr
(
module
,
class_id
)
except
AttributeError
:
raise
AttributeError
(
"filesystem Property Sheet '%s' should "
\
"contain a class with the same name"
%
\
class_id
)
return
PropertySheetDocument
.
importFromFilesystemDefinition
(
@
staticmethod
property_sheet_tool
,
klass
)
def
_migrateFromFilesystem
(
tool
,
filesystem_path
,
filesystem_file
,
class_id
):
raise
NotImplementedError
def
_migrateAllF
ilesystemPropertySheets
(
self
,
def
_migrateAllF
romFilesystem
(
self
,
context
,
context
,
migrate_object_dict
,
migrate_object_dict
,
object_dict
,
object_dict
,
...
@@ -3635,10 +3602,9 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
...
@@ -3635,10 +3602,9 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
the latter '_archive'), and finally removing the useless Property
the latter '_archive'), and finally removing the useless Property
Sheet on the filesystem
Sheet on the filesystem
"""
"""
# Migrate all the filesystem Property Sheets of the Business
# Migrate all the filesystem classes of the Business Template if any
# Template if any
tool
=
getattr
(
context
.
getPortalObject
(),
self
.
_tool_id
)
property_sheet_tool
=
context
.
getPortalObject
().
portal_property_sheets
id_set
=
set
(
tool
.
objectIds
())
property_sheet_id_set
=
set
(
property_sheet_tool
.
objectIds
())
# careful, that dictionary will change
# careful, that dictionary will change
class_id_list
=
migrate_object_dict
.
keys
()
class_id_list
=
migrate_object_dict
.
keys
()
...
@@ -3646,48 +3612,44 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
...
@@ -3646,48 +3612,44 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
# If the Property Sheet already exists in ZODB, then skip it,
# If the Property Sheet already exists in ZODB, then skip it,
# otherwise it should not be needed anymore once the deletion
# otherwise it should not be needed anymore once the deletion
# code of the filesystem Property Sheets is enabled
# code of the filesystem Property Sheets is enabled
if
class_id
in
property_sheet_
id_set
:
if
class_id
in
id_set
:
# XXX a Conduit must be able to merge modifications
# XXX a Conduit must be able to merge modifications
# from FS PropertySheets into ZODB PropertySheets
# from FS PropertySheets into ZODB PropertySheets
warn
(
'Conflict when migrating
Property Sheet %s: '
\
warn
(
'Conflict when migrating
classes %s: already exists in %s and '
\
'already exists in portal_property_sheets and '
\
'cannot be updated automatically for now.'
%
(
class_id
,
'cannot be updated automatically for now. '
%
class_id
,
self
.
_tool_id
)
,
UserWarning
)
UserWarning
)
del
migrate_object_dict
[
class_id
]
del
migrate_object_dict
[
class_id
]
if
class_id
in
object_dict
:
if
class_id
in
object_dict
:
del
object_dict
[
class_id
]
del
object_dict
[
class_id
]
continue
continue
filesystem_property_sheet_path
=
\
filesystem_path
=
self
.
_getFilesystemPath
(
class_id
)
self
.
_getFilesystemPropertySheetPath
(
class_id
)
# A filesystem Property Sheet may already exist in the instance
# A filesystem Property Sheet may already exist in the instance
# home if the Business Template has been previously installed,
# home if the Business Template has been previously installed,
# otherwise it is created
# otherwise it is created
if
os
.
path
.
exists
(
filesystem_p
roperty_sheet_p
ath
):
if
os
.
path
.
exists
(
filesystem_path
):
filesystem_
property_sheet_file
=
open
(
filesystem_property_sheet
_path
)
filesystem_
file
=
open
(
filesystem
_path
)
else
:
else
:
filesystem_property_sheet_file
=
open
(
filesystem_property_sheet_path
,
filesystem__file
=
open
(
filesystem_path
,
'w+'
)
'w+'
)
filesystem_file
.
write
(
migrate_object_dict
[
class_id
])
filesystem_file
.
seek
(
0
)
filesystem_property_sheet_file
.
write
(
migrate_object_dict
[
class_id
])
filesystem_property_sheet_file
.
seek
(
0
)
try
:
try
:
new_property_sheet
=
self
.
_migrateFilesystemPropertySheet
(
migrated_object
=
self
.
_migrateFromFilesystem
(
tool
,
property_sheet_tool
,
filesystem_path
,
filesystem_property_sheet_path
,
filesystem_file
,
filesystem_property_sheet_file
,
class_id
).
aq_base
class_id
)
finally
:
finally
:
filesystem_
property_sheet_
file
.
close
()
filesystem_file
.
close
()
os
.
remove
(
filesystem_p
roperty_sheet_p
ath
)
os
.
remove
(
filesystem_path
)
# Update 'migrate_object_dict' with the new path
# Update 'migrate_object_dict' with the new path
key
=
'
portal_property_sheets/%s'
%
class_id
key
=
'
%s/%s'
%
(
self
.
_tool_id
,
migrated_object
.
getId
())
migrate_object_dict
[
key
]
=
new_property_sheet
.
aq_base
migrate_object_dict
[
key
]
=
migrated_object
del
migrate_object_dict
[
class_id
]
del
migrate_object_dict
[
class_id
]
# Remove old reference in 'object_dict' as it does not make
# Remove old reference in 'object_dict' as it does not make
...
@@ -3700,16 +3662,6 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
...
@@ -3700,16 +3662,6 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
# migrated
# migrated
update_parameter_dict
[
key
]
=
'migrate'
update_parameter_dict
[
key
]
=
'migrate'
def
remove
(
self
,
context
,
**
kw
):
"""Conversion of magically uniqued paths to real ones"""
remove_object_dict
=
kw
.
get
(
'remove_object_dict'
,
{})
new_remove_dict
=
dict
()
for
k
,
v
in
remove_object_dict
.
iteritems
():
if
k
.
startswith
(
self
.
getTemplateTypeName
()
+
'/'
):
new_remove_dict
[
self
.
_getPath
(
k
)]
=
v
kw
[
'remove_object_dict'
]
=
new_remove_dict
ObjectTemplateItem
.
remove
(
self
,
context
,
**
kw
)
def
install
(
self
,
context
,
**
kw
):
def
install
(
self
,
context
,
**
kw
):
if
not
self
.
_perform_migration
:
if
not
self
.
_perform_migration
:
return
DocumentTemplateItem
.
install
(
self
,
context
,
**
kw
)
return
DocumentTemplateItem
.
install
(
self
,
context
,
**
kw
)
...
@@ -3721,32 +3673,131 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
...
@@ -3721,32 +3673,131 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
if
bt_format_version
==
0
and
\
if
bt_format_version
==
0
and
\
not
self
.
_is_already_migrated
(
self
.
_archive
.
keys
()):
not
self
.
_is_already_migrated
(
self
.
_archive
.
keys
()):
self
.
_migrateAllF
ilesystemPropertySheets
(
context
,
self
.
_migrateAllF
romFilesystem
(
context
,
self
.
_archive
,
self
.
_archive
,
self
.
_objects
,
self
.
_objects
,
kw
.
get
(
'object_to_update'
))
kw
.
get
(
'object_to_update'
))
elif
bt_format_version
==
1
and
\
elif
bt_format_version
==
1
and
\
not
self
.
_is_already_migrated
(
self
.
_objects
.
keys
()):
not
self
.
_is_already_migrated
(
self
.
_objects
.
keys
()):
self
.
_migrateAllF
ilesystemPropertySheets
(
context
,
self
.
_migrateAllF
romFilesystem
(
context
,
self
.
_objects
,
self
.
_objects
,
self
.
_archive
,
self
.
_archive
,
kw
.
get
(
'object_to_update'
))
kw
.
get
(
'object_to_update'
))
return
ObjectTemplateItem
.
install
(
self
,
context
,
**
kw
)
return
ObjectTemplateItem
.
install
(
self
,
context
,
**
kw
)
class
PropertySheetTemplateItem
(
FilesystemToZodbTemplateItem
):
"""
Property Sheets are now stored in ZODB rather than the filesystem.
However, some Business Templates may still have filesystem Property
Sheets, which need to be migrated to the ZODB.
This migration is performed in two steps:
1/ Specify explicitly in the web user interface that the Property
Sheets should be migrated.
2/ The Property Sheets will all be migrated when installing the
Business Template.
Therefore, this is an all or nothing migration, meaning that only
methods of DocumentTemplateItem will be called before the migration
has been performed, then ObjectTemplateItem methods afterwards.
"""
# Only meaningful for filesystem Property Sheets
local_file_reader_name
=
staticmethod
(
readLocalPropertySheet
)
local_file_writer_name
=
staticmethod
(
writeLocalPropertySheet
)
local_file_importer_name
=
staticmethod
(
importLocalPropertySheet
)
local_file_remover_name
=
staticmethod
(
removeLocalPropertySheet
)
_tool_id
=
'portal_property_sheets'
@
staticmethod
def
_getFilesystemPath
(
class_id
):
"""
From the given class identifier, return the complete path of the
filesystem Property Sheet class. Only meaningful when the Business
Template has already been installed previously, otherwise the
"""
from
App.config
import
getConfiguration
return
os
.
path
.
join
(
getConfiguration
().
instancehome
,
"PropertySheet"
,
"%s.py"
%
class_id
)
@
staticmethod
def
_migrateFromFilesystem
(
tool
,
filesystem_path
,
filesystem_file
,
class_id
):
"""
Migration of a filesystem Property Sheet involves loading the
class from 'instancehome/PropertySheet/<class_id>', then create
the ZODB Property Sheets in portal_property_sheets from its
filesystem definition
"""
# The first parameter of 'load_source' is the module name where
# the class will be stored, thus don't only use the class name as
# it may clash with already loaded module, such as
# BusinessTemplate.
module
=
imp
.
load_source
(
'Migrate%sFilesystemPropertySheet'
%
class_id
,
filesystem_path
,
filesystem_file
)
try
:
klass
=
getattr
(
module
,
class_id
)
except
AttributeError
:
raise
AttributeError
(
"filesystem Property Sheet '%s' should "
\
"contain a class with the same name"
%
\
class_id
)
return
PropertySheetDocument
.
importFromFilesystemDefinition
(
tool
,
klass
)
class
ConstraintTemplateItem
(
DocumentTemplateItem
):
class
ConstraintTemplateItem
(
DocumentTemplateItem
):
local_file_reader_name
=
staticmethod
(
readLocalConstraint
)
local_file_reader_name
=
staticmethod
(
readLocalConstraint
)
local_file_writer_name
=
staticmethod
(
writeLocalConstraint
)
local_file_writer_name
=
staticmethod
(
writeLocalConstraint
)
local_file_importer_name
=
staticmethod
(
importLocalConstraint
)
local_file_importer_name
=
staticmethod
(
importLocalConstraint
)
local_file_remover_name
=
staticmethod
(
removeLocalConstraint
)
local_file_remover_name
=
staticmethod
(
removeLocalConstraint
)
class
ExtensionTemplateItem
(
DocumentTemplateItem
):
from
Products.ERP5Type.Core.ExtensionComponent
import
ExtensionComponent
as
\
ExtensionComponentDocument
class
ExtensionTemplateItem
(
FilesystemToZodbTemplateItem
):
"""
Extensions are now stored in ZODB rather than on the filesystem. However,
some Business Templates may still have filesystem Extensions which need to
be migrated to the ZODB.
"""
# XXX-arnau: the code is far from being stable
_perform_migration
=
False
_tool_id
=
'portal_components'
# Only meaningful for filesystem Extensions
local_file_reader_name
=
staticmethod
(
readLocalExtension
)
local_file_reader_name
=
staticmethod
(
readLocalExtension
)
local_file_writer_name
=
staticmethod
(
writeLocalExtension
)
local_file_writer_name
=
staticmethod
(
writeLocalExtension
)
# Extension needs no import
# Extension needs no import
local_file_importer_name
=
None
local_file_importer_name
=
None
local_file_remover_name
=
staticmethod
(
removeLocalExtension
)
local_file_remover_name
=
staticmethod
(
removeLocalExtension
)
@
staticmethod
def
_getZodbObjectId
(
id
):
return
'erp5.component.extension.%s'
%
id
@
staticmethod
def
_getFilesystemPath
(
class_id
):
from
App.config
import
getConfiguration
return
os
.
path
.
join
(
getConfiguration
().
instancehome
,
"Extensions"
,
"%s.py"
%
class_id
)
@
staticmethod
def
_migrateFromFilesystem
(
tool
,
filesystem_path
,
filesystem_file
,
class_id
):
return
ExtensionComponentDocument
.
importFromFilesystem
(
tool
,
filesystem_path
)
class
TestTemplateItem
(
DocumentTemplateItem
):
class
TestTemplateItem
(
DocumentTemplateItem
):
local_file_reader_name
=
staticmethod
(
readLocalTest
)
local_file_reader_name
=
staticmethod
(
readLocalTest
)
local_file_writer_name
=
staticmethod
(
writeLocalTest
)
local_file_writer_name
=
staticmethod
(
writeLocalTest
)
...
...
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