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
139
Merge Requests
139
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
Jobs
Commits
Open sidebar
nexedi
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
Hide 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):
text
=
file
.
read
()
self
.
_objects
[
file_name
[:
-
3
]]
=
text
class
PropertySheet
TemplateItem
(
DocumentTemplateItem
,
ObjectTemplateItem
):
class
FilesystemToZodb
TemplateItem
(
DocumentTemplateItem
,
ObjectTemplateItem
):
"""
Property Sheets are now stored in ZODB, rather than the filesystem.
However, Some Business Template 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.
Abstract class to allow migration from DocumentTemplateItem to
ObjectTemplateItem, this is useful for migration from filesystem to ZODB for
PropertySheets and Components
"""
# If set to False, then the migration of Property Sheets will never
# be performed, required until the code of ZODB Property Sheets is
# stable and completely documented
# If set to False, then the migration from filesystem to ZODB will be
# performed, meaningful only until the code is stable
_perform_migration
=
True
# 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
=
None
@
staticmethod
def
_getZodbObjectId
(
id
):
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
if
context
is
not
None
and
len
(
id_list
):
# XXX looking up a tool early in the install process might
# cause issues. If it does, we'll have to consider moving this
# to build()
tool
=
getattr
(
context
.
getPortalObject
(),
tool_id
,
None
)
tool
=
getattr
(
context
.
getPortalObject
(),
self
.
_
tool_id
,
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
):
if
id
in
existing_
property_sheet_
set
:
# if the
property shee
t is on ZODB, use it.
id_list
[
i
]
=
"%s/%s"
%
(
tool_id
,
id
)
if
id
in
existing_set
:
# if the
objec
t is on ZODB, use it.
id_list
[
i
]
=
"%s/%s"
%
(
self
.
_tool_id
,
self
.
_getZodbObjectId
(
id
)
)
BaseTemplateItem
.
__init__
(
self
,
id_list
,
**
kw
)
@
staticmethod
def
_is_already_migrated
(
object_key_list
):
def
_is_already_migrated
(
self
,
object_key_list
):
"""
The Property Sheets have already been migrated if any keys withi
n
the given object_key_list (either '_objects.keys()' or
'_archive.keys()') contains a key starting by 'portal_property_sheets
/'
Objects have already been migrated if any keys within the give
n
object_key_list (either '_objects.keys()' or '_archive.keys()') contains a
key starting by 'tool_id
/'
"""
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
):
"""
Call ObjectTemplateItem method when the
Property Sheets have
already been migrated, otherwise fallback on DocumentTemplateItem
method for
backward-compatibility
Call ObjectTemplateItem method when the
objects have already been
migrated, otherwise fallback on DocumentTemplateItem method for
backward-compatibility
"""
def
inner
(
self
,
*
args
,
**
kw
):
if
self
.
_is_already_migrated
(
getattr
(
self
,
object_dict_name
).
keys
()):
...
...
@@ -3548,7 +3537,7 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
if
method_name
==
'preinstall'
:
old_result
=
result
.
copy
()
for
k
,
v
in
old_result
.
iteritems
():
if
not
k
.
startswith
(
'portal_property_sheets
/'
):
if
not
k
.
startswith
(
self
.
_tool_id
+
'
/'
):
result
.
pop
(
k
)
# Magical way to have unique path in case of not yet migrated property
# sheets available on preinstall list
...
...
@@ -3581,53 +3570,31 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
else
:
return
DocumentTemplateItem
.
uninstall
(
self
,
*
args
,
**
kw
)
@
staticmethod
def
_getFilesystemPropertySheetPath
(
class_id
):
def
remove
(
self
,
context
,
**
kw
):
"""
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
Conversion of magically uniqued paths to real ones
"""
from
App.config
import
getConfiguration
return
os
.
path
.
join
(
getConfiguration
().
instancehome
,
"PropertySheet"
,
"%s.py"
%
class_id
)
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
)
@
staticmethod
def
_migrateFilesystemPropertySheet
(
property_sheet_tool
,
filesystem_property_sheet_path
,
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
(
property_sheet_tool
,
klass
)
def
_getFilesystemPath
(
class_id
):
raise
NotImplementedError
def
_migrateAllFilesystemPropertySheets
(
self
,
context
,
migrate_object_dict
,
object_dict
,
update_parameter_dict
):
@
staticmethod
def
_migrateFromFilesystem
(
tool
,
filesystem_path
,
filesystem_file
,
class_id
):
raise
NotImplementedError
def
_migrateAllFromFilesystem
(
self
,
context
,
migrate_object_dict
,
object_dict
,
update_parameter_dict
):
"""
Migrate all Property Sheets from 'migrate_object_dict' and, if
necessary, remove old references in 'object_dict' too (with format
...
...
@@ -3635,10 +3602,9 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
the latter '_archive'), and finally removing the useless Property
Sheet on the filesystem
"""
# Migrate all the filesystem Property Sheets of the Business
# Template if any
property_sheet_tool
=
context
.
getPortalObject
().
portal_property_sheets
property_sheet_id_set
=
set
(
property_sheet_tool
.
objectIds
())
# Migrate all the filesystem classes of the Business Template if any
tool
=
getattr
(
context
.
getPortalObject
(),
self
.
_tool_id
)
id_set
=
set
(
tool
.
objectIds
())
# careful, that dictionary will change
class_id_list
=
migrate_object_dict
.
keys
()
...
...
@@ -3646,48 +3612,44 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
# If the Property Sheet already exists in ZODB, then skip it,
# otherwise it should not be needed anymore once the deletion
# 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
# from FS PropertySheets into ZODB PropertySheets
warn
(
'Conflict when migrating
Property Sheet %s: '
\
'already exists in portal_property_sheets and '
\
'cannot be updated automatically for now. '
%
class_id
,
warn
(
'Conflict when migrating
classes %s: already exists in %s and '
\
'cannot be updated automatically for now.'
%
(
class_id
,
self
.
_tool_id
)
,
UserWarning
)
del
migrate_object_dict
[
class_id
]
if
class_id
in
object_dict
:
del
object_dict
[
class_id
]
continue
filesystem_property_sheet_path
=
\
self
.
_getFilesystemPropertySheetPath
(
class_id
)
filesystem_path
=
self
.
_getFilesystemPath
(
class_id
)
# A filesystem Property Sheet may already exist in the instance
# home if the Business Template has been previously installed,
# otherwise it is created
if
os
.
path
.
exists
(
filesystem_p
roperty_sheet_p
ath
):
filesystem_
property_sheet_file
=
open
(
filesystem_property_sheet
_path
)
if
os
.
path
.
exists
(
filesystem_path
):
filesystem_
file
=
open
(
filesystem
_path
)
else
:
filesystem_property_sheet_file
=
open
(
filesystem_property_sheet_path
,
'w+'
)
filesystem_property_sheet_file
.
write
(
migrate_object_dict
[
class_id
])
filesystem_property_sheet_file
.
seek
(
0
)
filesystem__file
=
open
(
filesystem_path
,
'w+'
)
filesystem_file
.
write
(
migrate_object_dict
[
class_id
])
filesystem_file
.
seek
(
0
)
try
:
new_property_sheet
=
self
.
_migrateFilesystemPropertySheet
(
property_sheet_tool
,
filesystem_property_sheet_path
,
filesystem_property_sheet_file
,
class_id
)
migrated_object
=
self
.
_migrateFromFilesystem
(
tool
,
filesystem_path
,
filesystem_file
,
class_id
).
aq_base
finally
:
filesystem_
property_sheet_
file
.
close
()
os
.
remove
(
filesystem_p
roperty_sheet_p
ath
)
filesystem_file
.
close
()
os
.
remove
(
filesystem_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
]
# Remove old reference in 'object_dict' as it does not make
...
...
@@ -3700,16 +3662,6 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
# migrated
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
):
if
not
self
.
_perform_migration
:
return
DocumentTemplateItem
.
install
(
self
,
context
,
**
kw
)
...
...
@@ -3721,32 +3673,131 @@ class PropertySheetTemplateItem(DocumentTemplateItem,
if
bt_format_version
==
0
and
\
not
self
.
_is_already_migrated
(
self
.
_archive
.
keys
()):
self
.
_migrateAllF
ilesystemPropertySheets
(
context
,
self
.
_archive
,
self
.
_objects
,
kw
.
get
(
'object_to_update'
))
self
.
_migrateAllF
romFilesystem
(
context
,
self
.
_archive
,
self
.
_objects
,
kw
.
get
(
'object_to_update'
))
elif
bt_format_version
==
1
and
\
not
self
.
_is_already_migrated
(
self
.
_objects
.
keys
()):
self
.
_migrateAllF
ilesystemPropertySheets
(
context
,
self
.
_objects
,
self
.
_archive
,
kw
.
get
(
'object_to_update'
))
self
.
_migrateAllF
romFilesystem
(
context
,
self
.
_objects
,
self
.
_archive
,
kw
.
get
(
'object_to_update'
))
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
):
local_file_reader_name
=
staticmethod
(
readLocalConstraint
)
local_file_writer_name
=
staticmethod
(
writeLocalConstraint
)
local_file_importer_name
=
staticmethod
(
importLocalConstraint
)
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_writer_name
=
staticmethod
(
writeLocalExtension
)
# Extension needs no import
local_file_importer_name
=
None
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
):
local_file_reader_name
=
staticmethod
(
readLocalTest
)
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