#!/usr/bin/env python """ Contains base test class for nbconvert """ #----------------------------------------------------------------------------- #Copyright (c) 2013, the IPython Development Team. # #Distributed under the terms of the Modified BSD License. # #The full license is in the file COPYING.txt, distributed with this software. #----------------------------------------------------------------------------- #----------------------------------------------------------------------------- # Imports #----------------------------------------------------------------------------- import subprocess import os import glob import shutil import sys import IPython from IPython.utils.tempdir import TemporaryDirectory #----------------------------------------------------------------------------- # Classes and functions #----------------------------------------------------------------------------- class TemporaryWorkingDirectory(TemporaryDirectory): """ Creates a temporary directory and sets the cwd to that directory. Automatically reverts to previous cwd upon cleanup. Usage example: with TemporaryWorakingDirectory() as tmpdir: ... """ def __init__(self, **kw): """ Constructor """ super(TemporaryWorkingDirectory, self).__init__(**kw) #Change cwd to new temp dir. Remember old cwd. self.old_wd = os.getcwd() os.chdir(self.name) def cleanup(self): """ Destructor """ #Revert to old cwd. os.chdir(self.old_wd) #Cleanup super(TemporaryWorkingDirectory, self).cleanup() class TestsBase(object): """Base tests class. Contains usefull fuzzy comparison and nbconvert functions.""" def fuzzy_compare(self, a, b, newlines_are_spaces=True, tabs_are_spaces=True, fuzzy_spacing=True, ignore_spaces=False, ignore_newlines=False, case_sensitive=False): """ Performs a fuzzy comparison of two strings. A fuzzy comparison is a comparison that ignores insignificant differences in the two comparands. The significance of certain differences can be specified via the keyword parameters of this method. """ if newlines_are_spaces: a = a.replace('\n', ' ') b = b.replace('\n', ' ') if tabs_are_spaces: a = a.replace('\t', ' ') b = b.replace('\t', ' ') if ignore_spaces: a = a.replace(' ', '') b = b.replace(' ', '') if fuzzy_spacing: a = self.recursive_replace(a, ' ', ' ') b = self.recursive_replace(b, ' ', ' ') if ignore_newlines: a = a.replace('\n', '') b = b.replace('\n', '') if not case_sensitive: a = a.lower() b = b.lower() return a == b def recursive_replace(self, text, search, replacement): """ Performs a recursive replacement operation. Replaces all instances of a search string in a text string with a replacement string until the search string no longer exists. Recursion is needed because the replacement string may generate additional search strings. For example: Replace "ii" with "i" in the string "Hiiii" yields "Hii" Another replacement yields "Hi" (the desired output) Parameters: ----------- text : string Text to replace in. search : string String to search for within "text" replacement : string String to replace "search" with """ while search in text: text = text.replace(search, replacement) return text def create_temp_cwd(self, copy_filenames=None): temp_dir = TemporaryWorkingDirectory() #Copy the files if requested. if not copy_filenames is None: self.copy_files_to(copy_filenames) #Return directory handler return temp_dir def copy_files_to(self, copy_filenames=None, destination=None): #Copy test files into the destination directory. if copy_filenames: for pattern in copy_filenames: for match in glob.glob(os.path.join(self._get_files_path(), pattern)): if destination is None: shutil.copyfile(match, os.path.basename(match)) else: if not os.path.isdir(destination): os.makedirs(destination) shutil.copyfile(match, os.path.join(destination, os.path.basename(match))) def _get_files_path(self): #Get the relative path to this module in the IPython directory. names = self.__module__.split('.')[1:-1] names.append('files') #Build a path using the IPython directory and the relative path we just #found. path = IPython.__path__[0] for name in names: path = os.path.join(path, name) return path def call(self, parameters): return subprocess.Popen(parameters, stdout=subprocess.PIPE).communicate()[0]