base.py
171 lines
| 5.5 KiB
| text/x-python
|
PythonLexer
|
r18580 | """Base test class for nbconvert""" | ||
# Copyright (c) IPython Development Team. | ||||
# Distributed under the terms of the Modified BSD License. | ||||
|
r11477 | |||
|
r14961 | import io | ||
|
r11478 | import os | ||
import glob | ||||
|
r21148 | import shlex | ||
|
r11478 | import shutil | ||
|
r21148 | import sys | ||
|
r12373 | import unittest | ||
|
r21153 | from subprocess import Popen, PIPE | ||
|
r11478 | |||
|
r21150 | import nose.tools as nt | ||
|
r18605 | from IPython.nbformat import v4, write | ||
|
r11873 | from IPython.utils.tempdir import TemporaryWorkingDirectory | ||
|
r21153 | |||
from IPython.utils.py3compat import string_types, bytes_to_str | ||||
|
r11478 | |||
|
r12373 | class TestsBase(unittest.TestCase): | ||
|
r11878 | """Base tests class. Contains useful fuzzy comparison and nbconvert | ||
|
r11477 | functions.""" | ||
def fuzzy_compare(self, a, b, newlines_are_spaces=True, tabs_are_spaces=True, | ||||
fuzzy_spacing=True, ignore_spaces=False, | ||||
|
r11905 | ignore_newlines=False, case_sensitive=False, leave_padding=False): | ||
|
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. | ||||
""" | ||||
|
r11905 | if not leave_padding: | ||
a = a.strip() | ||||
b = b.strip() | ||||
|
r11904 | if ignore_newlines: | ||
a = a.replace('\n', '') | ||||
b = b.replace('\n', '') | ||||
|
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, ' ', ' ') | ||||
|
r11482 | if not case_sensitive: | ||
|
r11477 | a = a.lower() | ||
b = b.lower() | ||||
|
r11910 | |||
|
r11936 | self.assertEqual(a, b) | ||
|
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" | ||||
|
r12373 | Another replacement cds "Hi" (the desired output) | ||
|
r11477 | |||
|
r13587 | Parameters | ||
---------- | ||||
|
r11477 | 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 | ||||
|
r11478 | |||
def create_temp_cwd(self, copy_filenames=None): | ||||
temp_dir = TemporaryWorkingDirectory() | ||||
#Copy the files if requested. | ||||
|
r11878 | if copy_filenames is not None: | ||
|
r15360 | self.copy_files_to(copy_filenames, dest=temp_dir.name) | ||
|
r11478 | |||
#Return directory handler | ||||
return temp_dir | ||||
|
r14961 | |||
def create_empty_notebook(self, path): | ||||
|
r18605 | nb = v4.new_notebook() | ||
|
r14961 | with io.open(path, 'w', encoding='utf-8') as f: | ||
|
r18613 | write(nb, f, 4) | ||
|
r11478 | |||
|
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))) | ||||
|
r11478 | |||
def _get_files_path(self): | ||||
|
r11479 | |||
#Get the relative path to this module in the IPython directory. | ||||
names = self.__module__.split('.')[1:-1] | ||||
names.append('files') | ||||
|
r20909 | #Build a path using the nbconvert directory and the relative path we just | ||
|
r11479 | #found. | ||
|
r20909 | import jupyter_nbconvert | ||
path = os.path.dirname(jupyter_nbconvert.__file__) | ||||
return os.path.join(path, *names) | ||||
|
r11478 | |||
|
r21148 | def nbconvert(self, parameters, ignore_return_code=False): | ||
|
r12133 | """ | ||
|
r21148 | Run nbconvert a, IPython shell command, listening for both Errors and non-zero | ||
|
r12133 | return codes. | ||
|
r13587 | Parameters | ||
---------- | ||||
|
r21148 | parameters : str, list(str) | ||
|
r12133 | List of parameters to pass to IPython. | ||
ignore_return_code : optional bool (default False) | ||||
Throw an OSError if the return code | ||||
""" | ||||
|
r21148 | if isinstance(parameters, string_types): | ||
parameters = shlex.split(parameters) | ||||
cmd = [sys.executable, '-m', 'jupyter_nbconvert'] + parameters | ||||
|
r21153 | p = Popen(cmd, stdout=PIPE, stderr=PIPE) | ||
stdout, stderr = p.communicate() | ||||
if not (p.returncode == 0 or ignore_return_code): | ||||
raise OSError(bytes_to_str(stderr)) | ||||
return stdout.decode('utf8', 'replace'), stderr.decode('utf8', 'replace') | ||||
|
r21150 | def assert_big_text_equal(a, b, chunk_size=80): | ||
"""assert that large strings are equal | ||||
Zooms in on first chunk that differs, | ||||
to give better info than vanilla assertEqual for large text blobs. | ||||
""" | ||||
for i in range(0, len(a), chunk_size): | ||||
chunk_a = a[i:i + chunk_size] | ||||
chunk_b = b[i:i + chunk_size] | ||||
nt.assert_equal(chunk_a, chunk_b, "[offset: %i]\n%r != \n%r" % ( | ||||
i, chunk_a, chunk_b)) | ||||
if len(a) > len(b): | ||||
nt.fail("Length doesn't match (%i > %i). Extra text:\n%r" % ( | ||||
len(a), len(b), a[len(b):] | ||||
)) | ||||
elif len(a) < len(b): | ||||
nt.fail("Length doesn't match (%i < %i). Extra text:\n%r" % ( | ||||
len(a), len(b), b[len(a):] | ||||
)) | ||||