From c3b571bf9b6eb2a1c9db8dc160542398e12bf48d Mon Sep 17 00:00:00 2001 From: Ned Batchelder Date: Thu, 21 Feb 2013 11:38:45 -0500 Subject: [PATCH] Make sure temp directories are properly cleaned up so running tests doesn't leave them behind. --- .../contentstore/tests/test_contentstore.py | 4 ++-- cms/djangoapps/contentstore/tests/tests.py | 1 - cms/envs/common.py | 4 ++-- common/djangoapps/mitxmako/makoloader.py | 3 ++- common/djangoapps/mitxmako/middleware.py | 4 ++-- .../management/commands/tests/test_pearson.py | 20 ++++++++----------- common/lib/tempdir.py | 17 ++++++++++++++++ .../lib/xmodule/xmodule/tests/test_export.py | 8 +++++--- lms/envs/common.py | 4 ++-- 9 files changed, 40 insertions(+), 25 deletions(-) create mode 100644 common/lib/tempdir.py diff --git a/cms/djangoapps/contentstore/tests/test_contentstore.py b/cms/djangoapps/contentstore/tests/test_contentstore.py index b79d86b52f..487c6d3a76 100644 --- a/cms/djangoapps/contentstore/tests/test_contentstore.py +++ b/cms/djangoapps/contentstore/tests/test_contentstore.py @@ -5,7 +5,7 @@ from django.test.utils import override_settings from django.conf import settings from django.core.urlresolvers import reverse from path import path -from tempfile import mkdtemp +from tempdir import mkdtemp_clean import json from fs.osfs import OSFS import copy @@ -194,7 +194,7 @@ class ContentStoreToyCourseTest(ModuleStoreTestCase): import_from_xml(ms, 'common/test/data/', ['full']) location = CourseDescriptor.id_to_location('edX/full/6.002_Spring_2012') - root_dir = path(mkdtemp()) + root_dir = path(mkdtemp_clean()) print 'Exporting to tempdir = {0}'.format(root_dir) diff --git a/cms/djangoapps/contentstore/tests/tests.py b/cms/djangoapps/contentstore/tests/tests.py index 166982e35f..c4a46459e2 100644 --- a/cms/djangoapps/contentstore/tests/tests.py +++ b/cms/djangoapps/contentstore/tests/tests.py @@ -4,7 +4,6 @@ from django.test.client import Client from django.conf import settings from django.core.urlresolvers import reverse from path import path -from tempfile import mkdtemp import json from fs.osfs import OSFS import copy diff --git a/cms/envs/common.py b/cms/envs/common.py index 281dd97f20..50f237c374 100644 --- a/cms/envs/common.py +++ b/cms/envs/common.py @@ -20,7 +20,6 @@ Longer TODO: """ import sys -import tempfile import os.path import os import lms.envs.common @@ -59,7 +58,8 @@ sys.path.append(COMMON_ROOT / 'lib') ############################# WEB CONFIGURATION ############################# # This is where we stick our compiled template files. -MAKO_MODULE_DIR = tempfile.mkdtemp('mako') +from tempdir import mkdtemp_clean +MAKO_MODULE_DIR = mkdtemp_clean('mako') MAKO_TEMPLATES = {} MAKO_TEMPLATES['main'] = [ PROJECT_ROOT / 'templates', diff --git a/common/djangoapps/mitxmako/makoloader.py b/common/djangoapps/mitxmako/makoloader.py index 29184299b6..d623e8bcff 100644 --- a/common/djangoapps/mitxmako/makoloader.py +++ b/common/djangoapps/mitxmako/makoloader.py @@ -9,6 +9,7 @@ from django.template.loaders.app_directories import Loader as AppDirectoriesLoad from mitxmako.template import Template import mitxmako.middleware +import tempdir log = logging.getLogger(__name__) @@ -30,7 +31,7 @@ class MakoLoader(object): if module_directory is None: log.warning("For more caching of mako templates, set the MAKO_MODULE_DIR in settings!") - module_directory = tempfile.mkdtemp() + module_directory = tempdir.mkdtemp_clean() self.module_directory = module_directory diff --git a/common/djangoapps/mitxmako/middleware.py b/common/djangoapps/mitxmako/middleware.py index 64cb2e5415..3f66f8cc48 100644 --- a/common/djangoapps/mitxmako/middleware.py +++ b/common/djangoapps/mitxmako/middleware.py @@ -13,7 +13,7 @@ # limitations under the License. from mako.lookup import TemplateLookup -import tempfile +import tempdir from django.template import RequestContext from django.conf import settings @@ -29,7 +29,7 @@ class MakoMiddleware(object): module_directory = getattr(settings, 'MAKO_MODULE_DIR', None) if module_directory is None: - module_directory = tempfile.mkdtemp() + module_directory = tempdir.mkdtemp_clean() for location in template_locations: lookup[location] = TemplateLookup(directories=template_locations[location], diff --git a/common/djangoapps/student/management/commands/tests/test_pearson.py b/common/djangoapps/student/management/commands/tests/test_pearson.py index 12969405de..65d628fba0 100644 --- a/common/djangoapps/student/management/commands/tests/test_pearson.py +++ b/common/djangoapps/student/management/commands/tests/test_pearson.py @@ -7,6 +7,7 @@ import logging import os from tempfile import mkdtemp import cStringIO +import shutil import sys from django.test import TestCase @@ -143,23 +144,18 @@ class PearsonTestCase(TestCase): ''' Base class for tests running Pearson-related commands ''' - import_dir = mkdtemp(prefix="import") - export_dir = mkdtemp(prefix="export") def assertErrorContains(self, error_message, expected): self.assertTrue(error_message.find(expected) >= 0, 'error message "{}" did not contain "{}"'.format(error_message, expected)) + def setUp(self): + self.import_dir = mkdtemp(prefix="import") + self.addCleanup(shutil.rmtree, self.import_dir) + self.export_dir = mkdtemp(prefix="export") + self.addCleanup(shutil.rmtree, self.export_dir) + def tearDown(self): - def delete_temp_dir(dirname): - if os.path.exists(dirname): - for filename in os.listdir(dirname): - os.remove(os.path.join(dirname, filename)) - os.rmdir(dirname) - - # clean up after any test data was dumped to temp directory - delete_temp_dir(self.import_dir) - delete_temp_dir(self.export_dir) - + pass # and clean up the database: # TestCenterUser.objects.all().delete() # TestCenterRegistration.objects.all().delete() diff --git a/common/lib/tempdir.py b/common/lib/tempdir.py new file mode 100644 index 0000000000..0acd92ba33 --- /dev/null +++ b/common/lib/tempdir.py @@ -0,0 +1,17 @@ +"""Make temporary directories nicely.""" + +import atexit +import os.path +import shutil +import tempfile + +def mkdtemp_clean(suffix="", prefix="tmp", dir=None): + """Just like mkdtemp, but the directory will be deleted when the process ends.""" + the_dir = tempfile.mkdtemp(suffix=suffix, prefix=prefix, dir=dir) + atexit.register(cleanup_tempdir, the_dir) + return the_dir + +def cleanup_tempdir(the_dir): + """Called on process exit to remove a temp directory.""" + if os.path.exists(the_dir): + shutil.rmtree(the_dir) diff --git a/common/lib/xmodule/xmodule/tests/test_export.py b/common/lib/xmodule/xmodule/tests/test_export.py index da1b04bd94..e9fb89e9f6 100644 --- a/common/lib/xmodule/xmodule/tests/test_export.py +++ b/common/lib/xmodule/xmodule/tests/test_export.py @@ -4,7 +4,7 @@ from fs.osfs import OSFS from nose.tools import assert_equals, assert_true from path import path from tempfile import mkdtemp -from shutil import copytree +import shutil from xmodule.modulestore.xml import XMLModuleStore @@ -46,11 +46,11 @@ class RoundTripTestCase(unittest.TestCase): Thus we make sure that export and import work properly. ''' def check_export_roundtrip(self, data_dir, course_dir): - root_dir = path(mkdtemp()) + root_dir = path(self.temp_dir) print "Copying test course to temp dir {0}".format(root_dir) data_dir = path(data_dir) - copytree(data_dir / course_dir, root_dir / course_dir) + shutil.copytree(data_dir / course_dir, root_dir / course_dir) print "Starting import" initial_import = XMLModuleStore(root_dir, course_dirs=[course_dir]) @@ -108,6 +108,8 @@ class RoundTripTestCase(unittest.TestCase): def setUp(self): self.maxDiff = None + self.temp_dir = mkdtemp() + self.addCleanup(shutil.rmtree, self.temp_dir) def test_toy_roundtrip(self): self.check_export_roundtrip(DATA_DIR, "toy") diff --git a/lms/envs/common.py b/lms/envs/common.py index 71e93024d2..9b0afeef3a 100644 --- a/lms/envs/common.py +++ b/lms/envs/common.py @@ -20,7 +20,6 @@ Longer TODO: """ import sys import os -import tempfile from xmodule.static_content import write_module_styles, write_module_js from path import path @@ -133,7 +132,8 @@ OPENID_PROVIDER_TRUSTED_ROOTS = ['cs50.net', '*.cs50.net'] ################################## MITXWEB ##################################### # This is where we stick our compiled template files. Most of the app uses Mako # templates -MAKO_MODULE_DIR = tempfile.mkdtemp('mako') +from tempdir import mkdtemp_clean +MAKO_MODULE_DIR = mkdtemp_clean('mako') MAKO_TEMPLATES = {} MAKO_TEMPLATES['main'] = [PROJECT_ROOT / 'templates', COMMON_ROOT / 'templates',