Commit d9ce0e27 authored by Hanno Schlichting's avatar Hanno Schlichting

Removed ZMI export/import feature.

parent 97a13e65
......@@ -28,6 +28,8 @@ Features Added
Restructuring
+++++++++++++
- Removed ZMI export/import feature.
- Drop ZopeUndo dependency and move undo management to the control panel.
- Simplify ZMI control panel and globally available management screens.
......
......@@ -14,7 +14,6 @@
"""
from cgi import escape
from cStringIO import StringIO
from logging import getLogger
import copy
import fnmatch
......@@ -32,7 +31,6 @@ from AccessControl.Permissions import view_management_screens
from AccessControl.Permissions import access_contents_information
from AccessControl.Permissions import delete_objects
from AccessControl.Permissions import ftp_access
from AccessControl.Permissions import import_export_objects
from AccessControl import getSecurityManager
from AccessControl.ZopeSecurityPolicy import getRoles
from Acquisition import aq_base, aq_parent
......@@ -62,9 +60,6 @@ from OFS.event import ObjectWillBeAddedEvent
from OFS.event import ObjectWillBeRemovedEvent
from OFS.Lockable import LockableItem
from OFS.subscribers import compatibilityCall
from OFS.XMLExportImport import importXML
from OFS.XMLExportImport import exportXML
from OFS.XMLExportImport import magic
if bbb.HAS_ZSERVER:
from webdav.Collection import Collection
......@@ -85,10 +80,8 @@ LOG = getLogger('ObjectManager')
# the name BadRequestException is relied upon by 3rd-party code
BadRequestException = BadRequest
customImporters={magic: importXML,
}
bad_id = re.compile(r'[^a-zA-Z0-9-_~,.$\(\)# @]').search
bad_id=re.compile(r'[^a-zA-Z0-9-_~,.$\(\)# @]').search
def checkValidId(self, id, allow_dup=0):
# If allow_dup is false, an error will be raised if an object
......@@ -583,92 +576,6 @@ class ObjectManager(CopyContainer,
r.append(o)
return r
security.declareProtected(import_export_objects, 'manage_exportObject')
def manage_exportObject(self, id='', download=None, toxml=None,
RESPONSE=None,REQUEST=None):
"""Exports an object to a file and returns that file."""
if not id:
# can't use getId() here (breaks on "old" exported objects)
id=self.id
if hasattr(id, 'im_func'): id=id()
ob=self
else: ob=self._getOb(id)
suffix=toxml and 'xml' or 'zexp'
if download:
f=StringIO()
if toxml:
exportXML(ob._p_jar, ob._p_oid, f)
else:
ob._p_jar.exportFile(ob._p_oid, f)
if RESPONSE is not None:
RESPONSE.setHeader('Content-type','application/data')
RESPONSE.setHeader('Content-Disposition',
'inline;filename=%s.%s' % (id, suffix))
return f.getvalue()
cfg = getConfiguration()
f = os.path.join(cfg.clienthome, '%s.%s' % (id, suffix))
if toxml:
exportXML(ob._p_jar, ob._p_oid, f)
else:
ob._p_jar.exportFile(ob._p_oid, f)
if REQUEST is not None:
return self.manage_main(self, REQUEST,
manage_tabs_message=
'<em>%s</em> successfully exported to <em>%s</em>' % (id,f),
title = 'Object exported')
security.declareProtected(import_export_objects, 'manage_importExportForm')
manage_importExportForm=DTMLFile('dtml/importExport',globals())
security.declareProtected(import_export_objects, 'manage_importObject')
def manage_importObject(self, file, REQUEST=None, set_owner=1):
"""Import an object from a file"""
dirname, file=os.path.split(file)
if dirname:
raise BadRequest, 'Invalid file name %s' % escape(file)
for impath in self._getImportPaths():
filepath = os.path.join(impath, 'import', file)
if os.path.exists(filepath):
break
else:
raise BadRequest, 'File does not exist: %s' % escape(file)
self._importObjectFromFile(filepath, verify=not not REQUEST,
set_owner=set_owner)
if REQUEST is not None:
return self.manage_main(
self, REQUEST,
manage_tabs_message='<em>%s</em> successfully imported' % id,
title='Object imported',
update_menu=1)
def _importObjectFromFile(self, filepath, verify=1, set_owner=1):
# locate a valid connection
connection=self._p_jar
obj=self
while connection is None:
obj=obj.aq_parent
connection=obj._p_jar
ob=connection.importFile(
filepath, customImporters=customImporters)
if verify: self._verifyObjectPaste(ob, validate_src=0)
id=ob.id
if hasattr(id, 'im_func'): id=id()
self._setObject(id, ob, set_owner=set_owner)
# try to make ownership implicit if possible in the context
# that the object was imported into.
ob=self._getOb(id)
ob.manage_changeOwnershipType(explicit=0)
def _getImportPaths(self):
cfg = getConfiguration()
paths = []
......
##############################################################################
#
# Copyright (c) 2002 Zope Foundation and Contributors.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
from base64 import encodestring
from cStringIO import StringIO
from ZODB.serialize import referencesf
from ZODB.ExportImport import TemporaryFile, export_end_marker
from ZODB.utils import p64
from ZODB.utils import u64
from Shared.DC.xml import ppml
magic='<?xm' # importXML(jar, file, clue)}
def XMLrecord(oid, len, p):
q=ppml.ToXMLUnpickler
f=StringIO(p)
u=q(f)
id=u64(oid)
aka=encodestring(oid)[:-1]
u.idprefix=str(id)+'.'
p=u.load().__str__(4)
if f.tell() < len:
p=p+u.load().__str__(4)
String=' <record id="%s" aka="%s">\n%s </record>\n' % (id, aka, p)
return String
def exportXML(jar, oid, file=None):
if file is None: file=TemporaryFile()
elif type(file) is str: file=open(file,'w+b')
write=file.write
write('<?xml version="1.0"?>\012<ZopeData>\012')
ref=referencesf
oids=[oid]
done_oids={}
done=done_oids.has_key
load=jar._storage.load
while oids:
oid=oids[0]
del oids[0]
if done(oid): continue
done_oids[oid]=1
try:
try:
p, serial = load(oid)
except TypeError:
# Some places inside the ZODB 3.9 still want a version
# argument, for example TmpStore from Connection.py
p, serial = load(oid, None)
except:
pass # Ick, a broken reference
else:
ref(p, oids)
write(XMLrecord(oid,len(p),p))
write('</ZopeData>\n')
return file
class zopedata:
def __init__(self, parser, tag, attrs):
self.file=parser.file
write=self.file.write
write('ZEXP')
def append(self, data):
file=self.file
write=file.write
pos=file.tell()
file.seek(pos)
write(data)
def start_zopedata(parser, tag, data):
return zopedata(parser, tag, data)
def save_zopedata(parser, tag, data):
file=parser.file
write=file.write
pos=file.tell()
file.seek(pos)
write(export_end_marker)
def save_record(parser, tag, data):
file=parser.file
write=file.write
pos=file.tell()
file.seek(pos)
a=data[1]
if a.has_key('id'): oid=a['id']
oid=p64(int(oid))
v=''
for x in data[2:]:
v=v+x
l=p64(len(v))
v=oid+l+v
return v
def importXML(jar, file, clue=''):
import xml.parsers.expat
if type(file) is str:
file=open(file, 'rb')
outfile=TemporaryFile()
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()
p.CharacterDataHandler=F.handle_data
p.StartElementHandler=F.unknown_starttag
p.EndElementHandler=F.unknown_endtag
r=p.Parse(data)
outfile.seek(0)
return jar.importFile(outfile,clue)
<dtml-var manage_page_header>
<dtml-var "manage_tabs(this(), _, )">
<p class="form-help">
You can export Zope objects to a file in order to transfer
them to a different Zope installation. You can either choose
to download the export file to your local machine, or save it
in the &quot;var&quot; directory of your Zope installation
on the server.
<br/>
<br/>
<b>Note:</b>
Zope can export/import objects in two different formats: a binary format (called
ZEXP) and as XML. The ZEXP format is the officially supported export/import
format for moving data between <u>identical</u> Zope installations (it is not a migration tool).
</p>
<form action="manage_exportObject" method="post">
<table cellspacing="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Export object id
</div>
</td>
<td align="left" valign="top">
<input type="text" name="id" size="25" value="<dtml-if ids><dtml-var "ids[0]" html_quote></dtml-if>" class="form-element"/>
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Export to
</div>
</td>
<td align="left" valign="top">
<div class="form-text">
<label for="download_local">
<input type="radio" name="download:int" value="1" id="download_local" />
Download to local machine
</label>
<br />
<label for="download_server">
<input type="radio" name="download:int" value="0" id="download_server" checked />
Save to file on server
</label>
</div>
</td>
</tr>
<tr>
<td align="left" valign="top">
&nbsp;
</td>
<td align="left" valign="top">
<div class="form-text">
<label for="toxml">
<input type="checkbox" id="toxml" name="toxml" value="Y" />
XML format?
</label>
<em>(unsupported, see above)</em>
</div>
</td>
</tr>
<tr>
<td></td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit" value="Export" />
</div>
</td>
</tr>
</table>
</form>
<hr />
<p class="form-help">
You may import Zope objects which have been previously
exported to a file, by placing the file in the &quot;import&quot;
directory of your Zope installation on the server. You should create
the &quot;import&quot; directory in the root of your Zope installation
if it does not yet exist.
</p>
<p class="form-help">
Note that by default, you will become the owner of the objects
that you are importing. If you wish the imported objects to retain
their existing ownership information, select "retain existing
ownership information".
</p>
<form action="manage_importObject" method="post">
<table cellspacing="2" border="0">
<tr>
<td align="left" valign="top">
<div class="form-label">
Import file name
</div>
</td>
<td align="left" valign="top">
<select name="file">
<dtml-in "list_imports()">
<option value="<dtml-var sequence-item>"><dtml-var sequence-item></option>
</dtml-in>
</select>
</td>
</tr>
<tr>
<td align="left" valign="top">
<div class="form-label">
Ownership
</div>
</td>
<td align="left" valign="top">
<div class="form-text">
<label for="owner_take">
<input type="radio" name="set_owner:int" value="1" id="owner_take" checked />
Take ownership of imported objects
</label>
<br />
<label for="owner_retain">
<input type="radio" name="set_owner:int" value="0" id="owner_retain" />
Retain existing ownership information
</label>
</div>
</td>
</tr>
<tr>
<td></td>
<td align="left" valign="top">
<div class="form-element">
<input class="form-element" type="submit" name="submit" value="Import" />
</div>
</td>
</tr>
</table>
</form>
<dtml-var manage_page_footer>
......@@ -190,11 +190,6 @@ function toggleSelect() {
<input class="form-element" type="submit" name="manage_delObjects:method"
value="Delete" />
</dtml-if>
<dtml-if "_.SecurityCheckPermission('Import/Export objects', this())">
<input class="form-element" type="submit"
name="manage_importExportForm:method"
value="Import/Export" />
</dtml-if>
<script type="text/javascript">
<!--
if (document.forms[0]) {
......@@ -261,10 +256,6 @@ There are currently no items in <em>&dtml-title_or_id;</em>
</div>
</dtml-if>
</dtml-unless>
<dtml-if "_.SecurityCheckPermission('Import/Export objects', this())">
<input class="form-element" type="submit"
name="manage_importExportForm:method" value="Import/Export" />
</dtml-if>
</td>
</tr>
</table>
......
......@@ -682,7 +682,6 @@ class IObjectManager(IZopeObject, ICopyContainer, INavigation, IManageable,
manage_main = Attribute(""" """)
manage_index_main = Attribute(""" """)
manage_addProduct = Attribute(""" """)
manage_importExportForm = Attribute(""" """)
def all_meta_types(interfaces=None):
"""
......@@ -761,17 +760,6 @@ class IObjectManager(IZopeObject, ICopyContainer, INavigation, IManageable,
"""Return a list of subobjects, used by tree tag.
"""
def manage_exportObject(id='', download=None, toxml=None,
RESPONSE=None, REQUEST=None):
"""Exports an object to a file and returns that file."""
def manage_importObject(file, REQUEST=None, set_owner=1):
"""Import an object from a file"""
def _importObjectFromFile(filepath, verify=1, set_owner=1):
"""
"""
class IFindSupport(Interface):
"""Find support for Zope Folders"""
......
# -*- coding: iso8859-1 -*-
##############################################################################
#
# Copyright (c) 2006 Zope Foundation and Contributors.
#
# This software is subject to the provisions of the Zope Public License,
# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
# FOR A PARTICULAR PURPOSE
#
##############################################################################
import unittest
import os
import tempfile
import transaction
from StringIO import StringIO
try:
here = os.path.dirname(os.path.abspath(__file__))
except:
here = os.path.dirname(os.path.abspath(sys.argv[0]))
imagedata = os.path.join(here, 'test.gif')
xmldata = os.path.join(here, 'export.xml')
_LONG_DTML = ''.join([('<dtml-var foo%d' % x) for x in xrange(1000)])
class XMLExportImportTests(unittest.TestCase):
def _makeJarAndRoot(self):
import ZODB
from OFS.Folder import Folder
from ZODB.DemoStorage import DemoStorage
CACHESIZE = 5 # something tiny
LOOPCOUNT = CACHESIZE * 10
storage = DemoStorage("Test")
db = ZODB.DB(storage, cache_size=CACHESIZE)
connection = db.open()
root = connection.root()
app = Folder('app')
root['app'] = app
return connection, app
def test_export_import_as_string_idempotent(self):
from OFS.DTMLMethod import DTMLMethod
from OFS.XMLExportImport import exportXML
from OFS.XMLExportImport import importXML
connection, app = self._makeJarAndRoot()
dm = DTMLMethod('test')
dm.munge(_LONG_DTML)
app._setObject('test', dm)
transaction.savepoint(optimistic=True) # need an OID!
oid = dm._p_oid
stream = StringIO()
data = exportXML(connection, oid, stream)
stream.seek(0)
newobj = importXML(connection, stream)
self.assertTrue(isinstance(newobj, DTMLMethod))
self.assertEqual(newobj.read(), dm.read())
def test_export_import_as_file_idempotent(self):
from OFS.DTMLMethod import DTMLMethod
from OFS.XMLExportImport import exportXML
from OFS.XMLExportImport import importXML
connection, app = self._makeJarAndRoot()
dm = DTMLMethod('test')
dm.munge(_LONG_DTML)
app._setObject('test', dm)
transaction.savepoint(optimistic=True) # need an OID!
oid = dm._p_oid
handle, path = tempfile.mkstemp(suffix='.xml')
try:
ostream = os.fdopen(handle,'wb')
data = exportXML(connection, oid, ostream)
ostream.close()
newobj = importXML(connection, path)
self.assertTrue(isinstance(newobj, DTMLMethod))
self.assertEqual(newobj.read(), dm.read())
finally:
# if this operaiton fails with a 'Permission Denied' error,
# then comment it out as it's probably masking a failure in
# the block above.
os.remove(path)
def test_OFS_ObjectManager__importObjectFromFile_xml(self):
from OFS.DTMLMethod import DTMLMethod
from OFS.Folder import Folder
from OFS.XMLExportImport import exportXML
connection, app = self._makeJarAndRoot()
dm = DTMLMethod('test')
dm._setId('test')
dm.munge(_LONG_DTML)
app._setObject('test', dm)
sub = Folder('sub')
app._setObject('sub', sub)
transaction.savepoint(optimistic=True) # need an OID!
oid = dm._p_oid
sub = app._getOb('sub')
handle, path = tempfile.mkstemp(suffix='.xml')
try:
ostream = os.fdopen(handle,'wb')
data = exportXML(connection, oid, ostream)
ostream.close()
sub._importObjectFromFile(path, 0, 0)
finally:
# if this operaiton fails with a 'Permission Denied' error,
# then comment it out as it's probably masking a failure in
# the block above.
os.remove(path)
def test_exportXML(self):
from OFS.Folder import Folder
from OFS.Image import Image
from OFS.XMLExportImport import exportXML
connection, app = self._makeJarAndRoot()
data = open(imagedata, 'rb')
sub = Folder('sub')
app._setObject('sub', sub)
img = Image('image', '', data, 'image/gif')
sub._setObject('image', img)
img._setProperty('prop1', 3.14159265359, 'float')
img._setProperty('prop2', 1, 'int')
img._setProperty('prop3', 2L**31-1, 'long')
img._setProperty('prop4', 'xxx', 'string')
img._setProperty('prop5', ['xxx', 'zzz'], 'lines')
img._setProperty('prop6', u'xxx', 'unicode')
img._setProperty('prop7', [u'xxx', u'zzz'], 'ulines')
img._setProperty('prop8', '<&>', 'string')
img._setProperty('prop9', u'<&>', 'unicode')
img._setProperty('prop10', '<]]>', 'string')
img._setProperty('prop11', u'<]]>', 'unicode')
img._setProperty('prop12', u'', 'unicode')
transaction.savepoint(optimistic=True)
oid = sub._p_oid
handle, path = tempfile.mkstemp(suffix='.xml')
try:
ostream = os.fdopen(handle,'wb')
data = exportXML(connection, oid, ostream)
ostream.close()
finally:
os.remove(path)
def test_importXML(self):
from OFS.XMLExportImport import importXML
connection, app = self._makeJarAndRoot()
newobj = importXML(connection, xmldata)
img = newobj._getOb('image')
data = open(imagedata, 'rb').read()
self.assertEqual(img.data, data)
self.assertEqual(repr(img.getProperty('prop1')),
repr(3.14159265359))
self.assertEqual(repr(img.getProperty('prop2')),
repr(1))
self.assertEqual(repr(img.getProperty('prop3')),
repr(2L**31-1))
self.assertEqual(repr(img.getProperty('prop4')),
repr('xxx'))
self.assertEqual(repr(img.getProperty('prop5')),
repr(('xxx', 'zzz')))
self.assertEqual(repr(img.getProperty('prop6')),
repr(u'xxx'))
self.assertEqual(repr(img.getProperty('prop7')),
repr((u'xxx', u'zzz')))
self.assertEqual(repr(img.getProperty('prop8')),
repr('<&>'))
self.assertEqual(repr(img.getProperty('prop9')),
repr(u'<&>'))
self.assertEqual(repr(img.getProperty('prop10')),
repr('<]]>'))
self.assertEqual(repr(img.getProperty('prop11')),
repr(u'<]]>'))
self.assertEqual(repr(img.getProperty('prop12')),
repr(u''))
def test_suite():
return unittest.TestSuite((
unittest.makeSuite(XMLExportImportTests),
))
This diff is collapsed.
"""Yet another XML parser
This is meant to be very simple:
- stack based
- The parser has a table of start handlers and end handlers.
- start tag handlers are called with the parser instance, tag names
and attributes. The result is placed on the stack. The default
handler places a special object on the stack (uh, a list, with the
tag name and attributes as the first two elements. ;)
- end tag handlers are called with the object on the parser, the tag
name, and top of the stack right after it has been removed. The
result is appended to the object on the top of the stack.
Note that namespace attributes should recieve some special handling.
Oh well.
"""
import string
import xml.parsers.expat
class xyap:
start_handlers = {}
end_handlers = {}
def __init__(self):
top = []
self._stack = _stack = [top]
self.push = _stack.append
self.append = top.append
def handle_data(self, data):
self.append(data)
def unknown_starttag(self, tag, attrs):
if isinstance(attrs, list):
attrs = dict(attrs)
start = self.start_handlers
if tag in start:
tag = start[tag](self, tag, attrs)
else:
tag = [tag, attrs]
self.push(tag)
self.append = tag.append
def unknown_endtag(self, tag):
_stack = self._stack
top = _stack.pop()
append = self.append = _stack[-1].append
end = self.end_handlers
if tag in end:
top = end[tag](self, tag, top)
append(top)
class NoBlanks:
def handle_data(self, data):
if data.strip():
self.append(data)
def struct(self, tag, data):
r = {}
for k, v in data[2:]:
r[k] = v
return r
_nulljoin = "".join
def name(self, tag, data):
return _nulljoin(data[2:]).strip()
def tuplef(self, tag, data):
return tuple(data[2:])
class XYap(xyap):
def __init__(self):
self._parser = xml.parsers.expat.ParserCreate()
self._parser.StartElementHandler = self.unknown_starttag
self._parser.EndElementHandler = self.unknown_endtag
self._parser.CharacterDataHandler = self.handle_data
xyap.__init__(self)
class xmlrpc(NoBlanks, XYap):
end_handlers = {
'methodCall': tuplef,
'methodName': name,
'params': tuplef,
'param': lambda self, tag, data: data[2],
'value': lambda self, tag, data: data[2],
'i4':
lambda self, tag, data, atoi=string.atoi, name=name:
atoi(name(self, tag, data)),
'int':
lambda self, tag, data, atoi=string.atoi, name=name:
atoi(name(self, tag, data)),
'boolean':
lambda self, tag, data, atoi=string.atoi, name=name:
atoi(name(self, tag, data)),
'string': lambda self, tag, data, join=string.join:
join(data[2:], ''),
'double':
lambda self, tag, data, atof=string.atof, name=name:
atof(name(self, tag, data)),
'float':
lambda self, tag, data, atof=string.atof, name=name:
atof(name(self, tag, data)),
'struct': struct,
'member': tuplef,
'name': name,
'array': lambda self, tag, data: data[2],
'data': lambda self, tag, data: data[2:],
}
......@@ -16,8 +16,6 @@ Demonstrates that cut/copy/paste/clone/rename and import/export
work if a savepoint is made before performing the respective operation.
"""
import os
from Testing import ZopeTestCase
from Testing.ZopeTestCase import layer
......@@ -27,7 +25,6 @@ from Testing.ZopeTestCase import transaction
from AccessControl.Permissions import add_documents_images_and_files
from AccessControl.Permissions import delete_objects
from OFS.SimpleItem import SimpleItem
import tempfile
folder_name = ZopeTestCase.folder_name
cutpaste_permissions = [add_documents_images_and_files, delete_objects]
......@@ -92,73 +89,6 @@ class TestCopyPaste(ZopeTestCase.ZopeTestCase):
self.assertTrue(hasattr(self.folder, 'new_doc'))
class TestImportExport(ZopeTestCase.ZopeTestCase):
def afterSetUp(self):
self.setupLocalEnvironment()
self.folder.addDTMLMethod('doc', file='foo')
# _p_oids are None until we create a savepoint
self.assertEqual(self.folder._p_oid, None)
transaction.savepoint(optimistic=True)
self.assertNotEqual(self.folder._p_oid, None)
def testExport(self):
self.folder.manage_exportObject('doc')
self.assertTrue(os.path.exists(self.zexp_file))
def testImport(self):
self.folder.manage_exportObject('doc')
self.folder._delObject('doc')
self.folder.manage_importObject('doc.zexp')
self.assertTrue(hasattr(self.folder, 'doc'))
# To make export and import happy, we have to provide a file-
# system 'import' directory and adapt the configuration a bit:
local_home = tempfile.gettempdir()
import_dir = os.path.join(local_home, 'import')
zexp_file = os.path.join(import_dir, 'doc.zexp')
def setupLocalEnvironment(self):
# Create the 'import' directory
os.mkdir(self.import_dir)
import App.config
config = App.config.getConfiguration()
self._ih = config.instancehome
config.instancehome = self.local_home
self._ch = config.clienthome
config.clienthome = self.import_dir
App.config.setConfiguration(config)
def afterClear(self):
# Remove external resources
try:
os.remove(self.zexp_file)
except OSError:
pass
try:
os.rmdir(self.import_dir)
except OSError:
pass
try:
import App.config
except ImportError:
# Restore builtins
builtins = getattr(__builtins__, '__dict__', __builtins__)
if hasattr(self, '_ih'):
builtins['INSTANCE_HOME'] = self._ih
if hasattr(self, '_ch'):
builtins['CLIENT_HOME'] = self._ch
else:
# Zope >= 2.7
config = App.config.getConfiguration()
if hasattr(self, '_ih'):
config.instancehome = self._ih
if hasattr(self, '_ch'):
config.clienthome = self._ch
App.config.setConfiguration(config)
class TestAttributesOfCleanObjects(ZopeTestCase.ZopeTestCase):
'''This testcase shows that _v_ and _p_ attributes are NOT bothered
by transaction boundaries, if the respective object is otherwise
......@@ -312,7 +242,6 @@ def test_suite():
from unittest import TestSuite, makeSuite
suite = TestSuite()
suite.addTest(makeSuite(TestCopyPaste))
suite.addTest(makeSuite(TestImportExport))
suite.addTest(makeSuite(TestAttributesOfCleanObjects))
suite.addTest(makeSuite(TestAttributesOfDirtyObjects))
suite.addTest(makeSuite(TestTransactionAbort))
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment