base.py
151 lines
| 4.9 KiB
| text/x-python
|
PythonLexer
Jonathan Frederic
|
r11477 | """ | ||
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 | ||||
#----------------------------------------------------------------------------- | ||||
Jonathan Frederic
|
r11478 | import os | ||
import glob | ||||
import shutil | ||||
Jonathan Frederic
|
r11910 | from nose.tools import assert_equal | ||
Jonathan Frederic
|
r11478 | import IPython | ||
Paul Ivanov
|
r11873 | from IPython.utils.tempdir import TemporaryWorkingDirectory | ||
Paul Ivanov
|
r11828 | from IPython.utils.process import get_output_error_code | ||
Paul Ivanov
|
r11862 | from IPython.testing.tools import get_ipython_cmd | ||
Paul Ivanov
|
r11834 | |||
Paul Ivanov
|
r11862 | # a trailing space allows for simpler concatenation with the other arguments | ||
ipy_cmd = get_ipython_cmd(as_string=True) + " " | ||||
Jonathan Frederic
|
r11477 | |||
#----------------------------------------------------------------------------- | ||||
# Classes and functions | ||||
#----------------------------------------------------------------------------- | ||||
Jonathan Frederic
|
r11478 | |||
Jonathan Frederic
|
r11477 | class TestsBase(object): | ||
Paul Ivanov
|
r11878 | """Base tests class. Contains useful fuzzy comparison and nbconvert | ||
Jonathan Frederic
|
r11477 | functions.""" | ||
Jonathan Frederic
|
r11931 | def __init__(self): | ||
# We need to manually add assert_equal to the class instead of inheriting | ||||
# from unittest.TestCase because if we inherit from unittest.TestCase | ||||
# support for test generators is lost (a known 'feature' of nose). | ||||
self.assert_equal = assert_equal | ||||
Jonathan Frederic
|
r11477 | def fuzzy_compare(self, a, b, newlines_are_spaces=True, tabs_are_spaces=True, | ||
fuzzy_spacing=True, ignore_spaces=False, | ||||
Jonathan Frederic
|
r11905 | ignore_newlines=False, case_sensitive=False, leave_padding=False): | ||
Jonathan Frederic
|
r11477 | """ | ||
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. | ||||
""" | ||||
Jonathan Frederic
|
r11905 | if not leave_padding: | ||
a = a.strip() | ||||
b = b.strip() | ||||
Jonathan Frederic
|
r11904 | if ignore_newlines: | ||
a = a.replace('\n', '') | ||||
b = b.replace('\n', '') | ||||
Jonathan Frederic
|
r11477 | 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, ' ', ' ') | ||||
Jonathan Frederic
|
r11482 | if not case_sensitive: | ||
Jonathan Frederic
|
r11477 | a = a.lower() | ||
b = b.lower() | ||||
Jonathan Frederic
|
r11910 | |||
Jonathan Frederic
|
r11931 | self.assert_equal(a, b) | ||
Jonathan Frederic
|
r11477 | |||
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 | ||||
Jonathan Frederic
|
r11478 | |||
def create_temp_cwd(self, copy_filenames=None): | ||||
temp_dir = TemporaryWorkingDirectory() | ||||
#Copy the files if requested. | ||||
Paul Ivanov
|
r11878 | if copy_filenames is not None: | ||
Jonathan Frederic
|
r11478 | self.copy_files_to(copy_filenames) | ||
#Return directory handler | ||||
return temp_dir | ||||
Paul Ivanov
|
r11877 | def copy_files_to(self, copy_filenames, dest='.'): | ||
"Copy test files into the destination directory" | ||||
if not os.path.isdir(dest): | ||||
os.makedirs(dest) | ||||
files_path = self._get_files_path() | ||||
for pattern in copy_filenames: | ||||
for match in glob.glob(os.path.join(files_path, pattern)): | ||||
shutil.copyfile(match, os.path.join(dest, os.path.basename(match))) | ||||
Jonathan Frederic
|
r11478 | |||
def _get_files_path(self): | ||||
Jonathan Frederic
|
r11479 | |||
#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 | ||||
Jonathan Frederic
|
r11478 | |||
Paul Ivanov
|
r11828 | def call(self, parameters, raise_on_error=True): | ||
Paul Ivanov
|
r11834 | stdout, stderr, retcode = get_output_error_code(ipy_cmd + parameters) | ||
Paul Ivanov
|
r11828 | if retcode != 0 and raise_on_error: | ||
raise OSError(stderr) | ||||
return stdout, stderr | ||||