[CMF-checkins] SVN: CMF/branches/2.0/CMFCore/exportimport/ * no
longer delete all content that isn't explicitly in .preserve
unless the
Rob Miller
ra at burningman.com
Tue Apr 4 16:13:37 EDT 2006
Log message for revision 66442:
* no longer delete all content that isn't explicitly in .preserve unless the
content is to be reimported
* add '.delete' file support
Changed:
U CMF/branches/2.0/CMFCore/exportimport/content.py
U CMF/branches/2.0/CMFCore/exportimport/tests/test_content.py
-=-
Modified: CMF/branches/2.0/CMFCore/exportimport/content.py
===================================================================
--- CMF/branches/2.0/CMFCore/exportimport/content.py 2006-04-04 20:13:35 UTC (rev 66441)
+++ CMF/branches/2.0/CMFCore/exportimport/content.py 2006-04-04 20:13:36 UTC (rev 66442)
@@ -14,6 +14,10 @@
$Id$
"""
+try:
+ set = set
+except NameError:
+ from sets import Set as set
from csv import reader
from csv import register_dialect
@@ -58,6 +62,17 @@
Subobjects themselves are represented as individual files or
subdirectories within the parent's directory.
+ If the import step finds that any objects specified to be created by the
+ 'structure' directory setup already exist, these objects will be deleted
+ and then recreated by the profile. The existence of a '.preserve' file
+ within the 'structure' hierarchy allows specification of objects that
+ should not be deleted. '.preserve' files should contain one preserve
+ rule per line, with shell-style globbing supported (i.e. 'b*' will match
+ all objects w/ id starting w/ 'b'.
+
+ Similarly, a '.delete' file can be used to specify the deletion of any
+ objects that exist in the site but are NOT in the 'structure' hierarchy,
+ and thus will not be recreated during the import process.
"""
implements(IFilesystemExporter, IFilesystemImporter)
@@ -115,19 +130,6 @@
if not root:
subdir = '%s/%s' % (subdir, context.getId())
- preserve = import_context.readDataFile('.preserve', subdir)
-
- prior = context.contentIds()
-
- if not preserve:
- preserve = []
- else:
- preserve = _globtest(preserve, prior)
-
- for id in prior:
- if id not in preserve:
- context._delObject(id)
-
objects = import_context.readDataFile('.objects', subdir)
if objects is None:
return
@@ -136,10 +138,35 @@
stream = StringIO(objects)
rowiter = reader(stream, dialect)
+ ours = tuple(rowiter)
+ our_ids = set([item[0] for item in ours])
+ prior = set(context.contentIds())
+
+ preserve = import_context.readDataFile('.preserve', subdir)
+ if not preserve:
+ preserve = set()
+ else:
+ preservable = prior.intersection(our_ids)
+ preserve = set(_globtest(preserve, preservable))
+
+ delete = import_context.readDataFile('.delete', subdir)
+ if not delete:
+ delete= set()
+ else:
+ deletable = prior.difference(our_ids)
+ delete = set(_globtest(delete, deletable))
+
+ # if it's in our_ids and NOT in preserve, or if it's not in
+ # our_ids but IS in delete, we're gonna delete it
+ delete = our_ids.difference(preserve).union(delete)
+
+ for id in prior.intersection(delete):
+ context._delObject(id)
+
existing = context.objectIds()
- for object_id, portal_type in rowiter:
+ for object_id, portal_type in ours:
if object_id not in existing:
object = self._makeInstance(object_id, portal_type,
Modified: CMF/branches/2.0/CMFCore/exportimport/tests/test_content.py
===================================================================
--- CMF/branches/2.0/CMFCore/exportimport/tests/test_content.py 2006-04-04 20:13:35 UTC (rev 66441)
+++ CMF/branches/2.0/CMFCore/exportimport/tests/test_content.py 2006-04-04 20:13:36 UTC (rev 66442)
@@ -435,7 +435,7 @@
self.assertEqual(component, 'SFWA')
self.failUnless(message.startswith("Couldn't make"))
- def test_import_site_with_subitems_and_no_preserve(self):
+ def test_reimport_no_structure_no_delete(self):
self._setUpAdapters()
ITEM_IDS = ('foo', 'bar', 'baz')
@@ -444,25 +444,59 @@
site._setObject(id, _makeItem(id))
context = DummyImportContext(site)
- # We want to add 'baz' to 'foo', without losing 'bar'
+ # no defined structure => no deletion
context._files['structure/.objects'] = ''
importer = self._getImporter()
importer(context)
- self.assertEqual(len(site.objectIds()), 0)
+ self.assertEqual(len(site.objectIds()), len(ITEM_IDS))
- def test_import_site_with_subitemss_and_preserve(self):
+ def test_reimport_with_structure_does_delete(self):
self._setUpAdapters()
ITEM_IDS = ('foo', 'bar', 'baz')
site = _makeFolder('site', site_folder=True)
for id in ITEM_IDS:
site._setObject(id, _makeItem(id))
+ site._getOb(id).before = True
context = DummyImportContext(site)
- # We want to add 'baz' to 'foo', without losing 'bar'
- context._files['structure/.objects'] = ''
+ # defined structure => object deleted and recreated
+ context._files['structure/.objects'] = '\n'.join(
+ ['%s,%s' % (x, TEST_INI_AWARE) for x in ITEM_IDS])
+ for index in range(len(ITEM_IDS)):
+ id = ITEM_IDS[index]
+ context._files[
+ 'structure/%s.ini' % id] = KNOWN_INI % ('Title: %s' % id,
+ 'xyzzy',
+ )
+
+ importer = self._getImporter()
+ importer(context)
+
+ self.assertEqual(len(site.objectIds()), len(ITEM_IDS))
+ for obj in site.objectValues():
+ self.failIf(hasattr(obj, 'before'))
+
+ def test_reimport_with_structure_and_preserve(self):
+ self._setUpAdapters()
+ ITEM_IDS = ('foo', 'bar', 'baz')
+
+ site = _makeFolder('site', site_folder=True)
+ for id in ITEM_IDS:
+ site._setObject(id, _makeINIAware(id))
+ site._getOb(id).before = True
+
+ context = DummyImportContext(site)
+ context._files['structure/.objects'] = '\n'.join(
+ ['%s,%s' % (x, TEST_INI_AWARE) for x in ITEM_IDS])
+ for index in range(len(ITEM_IDS)):
+ id = ITEM_IDS[index]
+ context._files[
+ 'structure/%s.ini' % id] = KNOWN_INI % ('Title: %s' % id,
+ 'xyzzy',
+ )
context._files['structure/.preserve'] = '*'
importer = self._getImporter()
@@ -472,27 +506,69 @@
self.assertEqual(len(after), len(ITEM_IDS))
for i in range(len(ITEM_IDS)):
self.assertEqual(after[i], ITEM_IDS[i])
+ self.assertEqual(getattr(site._getOb(after[i]), 'before', None),
+ True)
- def test_import_site_with_subitemss_and_preserve_partial(self):
+ def test_reimport_with_structure_and_preserve_partial(self):
self._setUpAdapters()
ITEM_IDS = ('foo', 'bar', 'baz')
site = _makeFolder('site', site_folder=True)
for id in ITEM_IDS:
- site._setObject(id, _makeItem(id))
+ site._setObject(id, _makeINIAware(id))
+ site._getOb(id).before = True
context = DummyImportContext(site)
- # We want to add 'baz' to 'foo', without losing 'bar'
- context._files['structure/.objects'] = ''
+ context._files['structure/.objects'] = '\n'.join(
+ ['%s,%s' % (x, TEST_INI_AWARE) for x in ITEM_IDS])
+ for index in range(len(ITEM_IDS)):
+ id = ITEM_IDS[index]
+ context._files[
+ 'structure/%s.ini' % id] = KNOWN_INI % ('Title: %s' % id,
+ 'xyzzy',
+ )
context._files['structure/.preserve'] = 'b*'
importer = self._getImporter()
importer(context)
+ after = site.objectValues()
+ self.assertEqual(len(after), len(ITEM_IDS))
+ for obj in after:
+ if obj.getId().startswith('b'):
+ self.assertEqual(getattr(obj, 'before', None), True)
+ else:
+ self.assertEqual(getattr(obj, 'before', None), None)
+
+ def test_reimport_with_structure_partial_preserve_and_delete(self):
+ self._setUpAdapters()
+ ITEM_IDS = ('foo', 'bar', 'baz')
+
+ site = _makeFolder('site', site_folder=True)
+ for id in ITEM_IDS:
+ site._setObject(id, _makeINIAware(id))
+ site._getOb(id).before = True
+
+ context = DummyImportContext(site)
+ context._files['structure/.objects'] = '\n'.join(
+ ['%s,%s' % (x, TEST_INI_AWARE) for x in ITEM_IDS[:-1]])
+ for index in range(len(ITEM_IDS)):
+ id = ITEM_IDS[index]
+ context._files[
+ 'structure/%s.ini' % id] = KNOWN_INI % ('Title: %s' % id,
+ 'xyzzy',
+ )
+ context._files['structure/.preserve'] = 'foo'
+ context._files['structure/.delete'] = 'baz'
+
+ importer = self._getImporter()
+ importer(context)
+
after = site.objectIds()
- self.assertEqual(len(after), 2)
- self.assertEqual(after[0], 'bar')
- self.assertEqual(after[1], 'baz')
+ self.assertEqual(len(after), len(ITEM_IDS) - 1)
+ self.failIf('baz' in after)
+ self.assertEqual(getattr(site.foo, 'before', None), True)
+ self.failIf(hasattr(site.bar, 'before'))
def test_import_site_with_subfolders_and_preserve(self):
self._setUpAdapters()
More information about the CMF-checkins
mailing list