##// END OF EJS Templates
move ipython command line logic to one place...
Paul Ivanov -
Show More
@@ -1,171 +1,178 b''
1 """
1 """
2 Contains base test class for nbconvert
2 Contains base test class for nbconvert
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 #Copyright (c) 2013, the IPython Development Team.
5 #Copyright (c) 2013, the IPython Development Team.
6 #
6 #
7 #Distributed under the terms of the Modified BSD License.
7 #Distributed under the terms of the Modified BSD License.
8 #
8 #
9 #The full license is in the file COPYING.txt, distributed with this software.
9 #The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 import os
16 import os
17 import glob
17 import glob
18 import shutil
18 import shutil
19
19
20 import IPython
20 import IPython
21 from IPython.utils.tempdir import TemporaryDirectory
21 from IPython.utils.tempdir import TemporaryDirectory
22 from IPython.utils.process import get_output_error_code
22 from IPython.utils.process import get_output_error_code
23 from IPython.utils import py3compat
24
25 # Define ipython command line name
26 if py3compat.PY3:
27 ipy_cmd = 'ipython3 '
28 else:
29 ipy_cmd = 'ipython '
23
30
24 #-----------------------------------------------------------------------------
31 #-----------------------------------------------------------------------------
25 # Classes and functions
32 # Classes and functions
26 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
27
34
28 class TemporaryWorkingDirectory(TemporaryDirectory):
35 class TemporaryWorkingDirectory(TemporaryDirectory):
29 """
36 """
30 Creates a temporary directory and sets the cwd to that directory.
37 Creates a temporary directory and sets the cwd to that directory.
31 Automatically reverts to previous cwd upon cleanup.
38 Automatically reverts to previous cwd upon cleanup.
32 Usage example:
39 Usage example:
33
40
34 with TemporaryWorakingDirectory() as tmpdir:
41 with TemporaryWorakingDirectory() as tmpdir:
35 ...
42 ...
36 """
43 """
37
44
38 def __init__(self, **kw):
45 def __init__(self, **kw):
39 """
46 """
40 Constructor
47 Constructor
41 """
48 """
42 super(TemporaryWorkingDirectory, self).__init__(**kw)
49 super(TemporaryWorkingDirectory, self).__init__(**kw)
43
50
44 #Change cwd to new temp dir. Remember old cwd.
51 #Change cwd to new temp dir. Remember old cwd.
45 self.old_wd = os.getcwd()
52 self.old_wd = os.getcwd()
46 os.chdir(self.name)
53 os.chdir(self.name)
47
54
48
55
49 def cleanup(self):
56 def cleanup(self):
50 """
57 """
51 Destructor
58 Destructor
52 """
59 """
53
60
54 #Revert to old cwd.
61 #Revert to old cwd.
55 os.chdir(self.old_wd)
62 os.chdir(self.old_wd)
56
63
57 #Cleanup
64 #Cleanup
58 super(TemporaryWorkingDirectory, self).cleanup()
65 super(TemporaryWorkingDirectory, self).cleanup()
59
66
60
67
61 class TestsBase(object):
68 class TestsBase(object):
62 """Base tests class. Contains usefull fuzzy comparison and nbconvert
69 """Base tests class. Contains usefull fuzzy comparison and nbconvert
63 functions."""
70 functions."""
64
71
65
72
66 def fuzzy_compare(self, a, b, newlines_are_spaces=True, tabs_are_spaces=True,
73 def fuzzy_compare(self, a, b, newlines_are_spaces=True, tabs_are_spaces=True,
67 fuzzy_spacing=True, ignore_spaces=False,
74 fuzzy_spacing=True, ignore_spaces=False,
68 ignore_newlines=False, case_sensitive=False):
75 ignore_newlines=False, case_sensitive=False):
69 """
76 """
70 Performs a fuzzy comparison of two strings. A fuzzy comparison is a
77 Performs a fuzzy comparison of two strings. A fuzzy comparison is a
71 comparison that ignores insignificant differences in the two comparands.
78 comparison that ignores insignificant differences in the two comparands.
72 The significance of certain differences can be specified via the keyword
79 The significance of certain differences can be specified via the keyword
73 parameters of this method.
80 parameters of this method.
74 """
81 """
75
82
76 if newlines_are_spaces:
83 if newlines_are_spaces:
77 a = a.replace('\n', ' ')
84 a = a.replace('\n', ' ')
78 b = b.replace('\n', ' ')
85 b = b.replace('\n', ' ')
79
86
80 if tabs_are_spaces:
87 if tabs_are_spaces:
81 a = a.replace('\t', ' ')
88 a = a.replace('\t', ' ')
82 b = b.replace('\t', ' ')
89 b = b.replace('\t', ' ')
83
90
84 if ignore_spaces:
91 if ignore_spaces:
85 a = a.replace(' ', '')
92 a = a.replace(' ', '')
86 b = b.replace(' ', '')
93 b = b.replace(' ', '')
87
94
88 if fuzzy_spacing:
95 if fuzzy_spacing:
89 a = self.recursive_replace(a, ' ', ' ')
96 a = self.recursive_replace(a, ' ', ' ')
90 b = self.recursive_replace(b, ' ', ' ')
97 b = self.recursive_replace(b, ' ', ' ')
91
98
92 if ignore_newlines:
99 if ignore_newlines:
93 a = a.replace('\n', '')
100 a = a.replace('\n', '')
94 b = b.replace('\n', '')
101 b = b.replace('\n', '')
95
102
96 if not case_sensitive:
103 if not case_sensitive:
97 a = a.lower()
104 a = a.lower()
98 b = b.lower()
105 b = b.lower()
99
106
100 return a == b
107 return a == b
101
108
102
109
103 def recursive_replace(self, text, search, replacement):
110 def recursive_replace(self, text, search, replacement):
104 """
111 """
105 Performs a recursive replacement operation. Replaces all instances
112 Performs a recursive replacement operation. Replaces all instances
106 of a search string in a text string with a replacement string until
113 of a search string in a text string with a replacement string until
107 the search string no longer exists. Recursion is needed because the
114 the search string no longer exists. Recursion is needed because the
108 replacement string may generate additional search strings.
115 replacement string may generate additional search strings.
109
116
110 For example:
117 For example:
111 Replace "ii" with "i" in the string "Hiiii" yields "Hii"
118 Replace "ii" with "i" in the string "Hiiii" yields "Hii"
112 Another replacement yields "Hi" (the desired output)
119 Another replacement yields "Hi" (the desired output)
113
120
114 Parameters:
121 Parameters:
115 -----------
122 -----------
116 text : string
123 text : string
117 Text to replace in.
124 Text to replace in.
118 search : string
125 search : string
119 String to search for within "text"
126 String to search for within "text"
120 replacement : string
127 replacement : string
121 String to replace "search" with
128 String to replace "search" with
122 """
129 """
123 while search in text:
130 while search in text:
124 text = text.replace(search, replacement)
131 text = text.replace(search, replacement)
125 return text
132 return text
126
133
127
134
128 def create_temp_cwd(self, copy_filenames=None):
135 def create_temp_cwd(self, copy_filenames=None):
129 temp_dir = TemporaryWorkingDirectory()
136 temp_dir = TemporaryWorkingDirectory()
130
137
131 #Copy the files if requested.
138 #Copy the files if requested.
132 if not copy_filenames is None:
139 if not copy_filenames is None:
133 self.copy_files_to(copy_filenames)
140 self.copy_files_to(copy_filenames)
134
141
135 #Return directory handler
142 #Return directory handler
136 return temp_dir
143 return temp_dir
137
144
138
145
139 def copy_files_to(self, copy_filenames=None, destination=None):
146 def copy_files_to(self, copy_filenames=None, destination=None):
140
147
141 #Copy test files into the destination directory.
148 #Copy test files into the destination directory.
142 if copy_filenames:
149 if copy_filenames:
143 for pattern in copy_filenames:
150 for pattern in copy_filenames:
144 for match in glob.glob(os.path.join(self._get_files_path(), pattern)):
151 for match in glob.glob(os.path.join(self._get_files_path(), pattern)):
145 if destination is None:
152 if destination is None:
146 shutil.copyfile(match, os.path.basename(match))
153 shutil.copyfile(match, os.path.basename(match))
147 else:
154 else:
148 if not os.path.isdir(destination):
155 if not os.path.isdir(destination):
149 os.makedirs(destination)
156 os.makedirs(destination)
150 shutil.copyfile(match, os.path.join(destination, os.path.basename(match)))
157 shutil.copyfile(match, os.path.join(destination, os.path.basename(match)))
151
158
152
159
153 def _get_files_path(self):
160 def _get_files_path(self):
154
161
155 #Get the relative path to this module in the IPython directory.
162 #Get the relative path to this module in the IPython directory.
156 names = self.__module__.split('.')[1:-1]
163 names = self.__module__.split('.')[1:-1]
157 names.append('files')
164 names.append('files')
158
165
159 #Build a path using the IPython directory and the relative path we just
166 #Build a path using the IPython directory and the relative path we just
160 #found.
167 #found.
161 path = IPython.__path__[0]
168 path = IPython.__path__[0]
162 for name in names:
169 for name in names:
163 path = os.path.join(path, name)
170 path = os.path.join(path, name)
164 return path
171 return path
165
172
166
173
167 def call(self, parameters, raise_on_error=True):
174 def call(self, parameters, raise_on_error=True):
168 stdout, stderr, retcode = get_output_error_code(parameters)
175 stdout, stderr, retcode = get_output_error_code(ipy_cmd + parameters)
169 if retcode != 0 and raise_on_error:
176 if retcode != 0 and raise_on_error:
170 raise OSError(stderr)
177 raise OSError(stderr)
171 return stdout, stderr
178 return stdout, stderr
@@ -1,154 +1,144 b''
1 """
1 """
2 Contains tests for the nbconvertapp
2 Contains tests for the nbconvertapp
3 """
3 """
4 #-----------------------------------------------------------------------------
4 #-----------------------------------------------------------------------------
5 #Copyright (c) 2013, the IPython Development Team.
5 #Copyright (c) 2013, the IPython Development Team.
6 #
6 #
7 #Distributed under the terms of the Modified BSD License.
7 #Distributed under the terms of the Modified BSD License.
8 #
8 #
9 #The full license is in the file COPYING.txt, distributed with this software.
9 #The full license is in the file COPYING.txt, distributed with this software.
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11
11
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13 # Imports
13 # Imports
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15
15
16 import os
16 import os
17 from .base import TestsBase
17 from .base import TestsBase
18
18
19 from IPython.utils import py3compat
20 from IPython.testing import decorators as dec
19 from IPython.testing import decorators as dec
21
20
22
21
23 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
24 # Constants
23 # Constants
25 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
26
25
27 # Define ipython commandline name
28 if py3compat.PY3:
29 IPYTHON = 'ipython3'
30 else:
31 IPYTHON = 'ipython'
32
33
26
34 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
35 # Classes and functions
28 # Classes and functions
36 #-----------------------------------------------------------------------------
29 #-----------------------------------------------------------------------------
37
30
38 class TestNbConvertApp(TestsBase):
31 class TestNbConvertApp(TestsBase):
39 """Collection of NbConvertApp tests"""
32 """Collection of NbConvertApp tests"""
40
33
41
34
42 def test_notebook_help(self):
35 def test_notebook_help(self):
43 """
36 """
44 Will help show if no notebooks are specified?
37 Will help show if no notebooks are specified?
45 """
38 """
46 with self.create_temp_cwd():
39 with self.create_temp_cwd():
47 out, err = self.call(IPYTHON + ' nbconvert', raise_on_error=False)
40 out, err = self.call('nbconvert', raise_on_error=False)
48 assert "see '--help-all'" in out
41 assert "see '--help-all'" in out
49
42
50
43
51 def test_glob(self):
44 def test_glob(self):
52 """
45 """
53 Do search patterns work for notebook names?
46 Do search patterns work for notebook names?
54 """
47 """
55 with self.create_temp_cwd(['notebook*.ipynb']):
48 with self.create_temp_cwd(['notebook*.ipynb']):
56 self.call(IPYTHON + ' nbconvert --to="python"'
49 self.call('nbconvert --to="python" --notebooks=*.ipynb')
57 ' --notebooks=*.ipynb')
58 assert os.path.isfile('notebook1.py')
50 assert os.path.isfile('notebook1.py')
59 assert os.path.isfile('notebook2.py')
51 assert os.path.isfile('notebook2.py')
60
52
61
53
62 def test_glob_subdir(self):
54 def test_glob_subdir(self):
63 """
55 """
64 Do search patterns work for subdirectory notebook names?
56 Do search patterns work for subdirectory notebook names?
65 """
57 """
66 with self.create_temp_cwd():
58 with self.create_temp_cwd():
67 self.copy_files_to(['notebook*.ipynb'], 'subdir/')
59 self.copy_files_to(['notebook*.ipynb'], 'subdir/')
68 self.call(IPYTHON + ' nbconvert --to="python"'
60 self.call('nbconvert --to="python"'
69 ' --notebooks=%s' % os.path.join('subdir', '*.ipynb'))
61 ' --notebooks=%s' % os.path.join('subdir', '*.ipynb'))
70 assert os.path.isfile('notebook1.py')
62 assert os.path.isfile('notebook1.py')
71 assert os.path.isfile('notebook2.py')
63 assert os.path.isfile('notebook2.py')
72
64
73
65
74 def test_explicit(self):
66 def test_explicit(self):
75 """
67 """
76 Do explicit notebook names work?
68 Do explicit notebook names work?
77 """
69 """
78 with self.create_temp_cwd(['notebook*.ipynb']):
70 with self.create_temp_cwd(['notebook*.ipynb']):
79 self.call(IPYTHON + ' nbconvert --to="python"'
71 self.call('nbconvert --to="python" --notebooks=notebook2.ipynb')
80 ' --notebooks=notebook2.ipynb')
81 assert not os.path.isfile('notebook1.py')
72 assert not os.path.isfile('notebook1.py')
82 assert os.path.isfile('notebook2.py')
73 assert os.path.isfile('notebook2.py')
83
74
84
75
85 @dec.onlyif_cmds_exist('pdflatex')
76 @dec.onlyif_cmds_exist('pdflatex')
86 @dec.onlyif_cmds_exist('pandoc')
77 @dec.onlyif_cmds_exist('pandoc')
87 def test_post_processor(self):
78 def test_post_processor(self):
88 """
79 """
89 Do post processors work?
80 Do post processors work?
90 """
81 """
91 with self.create_temp_cwd(['notebook1.ipynb']):
82 with self.create_temp_cwd(['notebook1.ipynb']):
92 self.call(IPYTHON + ' nbconvert --to="latex" notebook1'
83 self.call('nbconvert --to="latex" notebook1'
93 ' --post="PDF" --PDFPostProcessor.verbose=True')
84 ' --post="PDF" --PDFPostProcessor.verbose=True')
94 assert os.path.isfile('notebook1.tex')
85 assert os.path.isfile('notebook1.tex')
95 print("\n\n\t" + "\n\t".join([f for f in os.listdir('.') if os.path.isfile(f)]) + "\n\n")
86 print("\n\n\t" + "\n\t".join([f for f in os.listdir('.') if os.path.isfile(f)]) + "\n\n")
96 assert os.path.isfile('notebook1.pdf')
87 assert os.path.isfile('notebook1.pdf')
97
88
98
89
99 @dec.onlyif_cmds_exist('pandoc')
90 @dec.onlyif_cmds_exist('pandoc')
100 def test_template(self):
91 def test_template(self):
101 """
92 """
102 Do export templates work?
93 Do export templates work?
103 """
94 """
104 with self.create_temp_cwd(['notebook2.ipynb']):
95 with self.create_temp_cwd(['notebook2.ipynb']):
105 self.call(IPYTHON + ' nbconvert --to=slides'
96 self.call('nbconvert --to=slides --notebooks=notebook2.ipynb'
106 ' --notebooks=notebook2.ipynb'
97 ' --template=reveal')
107 ' --template=reveal')
108 assert os.path.isfile('notebook2.slides.html')
98 assert os.path.isfile('notebook2.slides.html')
109 with open('notebook2.slides.html') as f:
99 with open('notebook2.slides.html') as f:
110 assert '/reveal.css' in f.read()
100 assert '/reveal.css' in f.read()
111
101
112
102
113 def test_glob_explicit(self):
103 def test_glob_explicit(self):
114 """
104 """
115 Can a search pattern be used along with matching explicit notebook names?
105 Can a search pattern be used along with matching explicit notebook names?
116 """
106 """
117 with self.create_temp_cwd(['notebook*.ipynb']):
107 with self.create_temp_cwd(['notebook*.ipynb']):
118 self.call(IPYTHON + ' nbconvert --to="python" --notebooks='
108 self.call('nbconvert --to="python" --notebooks='
119 '*.ipynb,notebook1.ipynb,notebook2.ipynb')
109 '*.ipynb,notebook1.ipynb,notebook2.ipynb')
120 assert os.path.isfile('notebook1.py')
110 assert os.path.isfile('notebook1.py')
121 assert os.path.isfile('notebook2.py')
111 assert os.path.isfile('notebook2.py')
122
112
123
113
124 def test_explicit_glob(self):
114 def test_explicit_glob(self):
125 """
115 """
126 Can explicit notebook names be used and then a matching search pattern?
116 Can explicit notebook names be used and then a matching search pattern?
127 """
117 """
128 with self.create_temp_cwd(['notebook*.ipynb']):
118 with self.create_temp_cwd(['notebook*.ipynb']):
129 self.call(IPYTHON + ' nbconvert --to="python" --notebooks='
119 self.call('nbconvert --to="python" --notebooks='
130 'notebook1.ipynb,notebook2.ipynb,*.ipynb')
120 'notebook1.ipynb,notebook2.ipynb,*.ipynb')
131 assert os.path.isfile('notebook1.py')
121 assert os.path.isfile('notebook1.py')
132 assert os.path.isfile('notebook2.py')
122 assert os.path.isfile('notebook2.py')
133
123
134
124
135 def test_default_config(self):
125 def test_default_config(self):
136 """
126 """
137 Does the default config work?
127 Does the default config work?
138 """
128 """
139 with self.create_temp_cwd(['notebook*.ipynb', 'ipython_nbconvert_config.py']):
129 with self.create_temp_cwd(['notebook*.ipynb', 'ipython_nbconvert_config.py']):
140 self.call(IPYTHON + ' nbconvert')
130 self.call('nbconvert')
141 assert os.path.isfile('notebook1.py')
131 assert os.path.isfile('notebook1.py')
142 assert not os.path.isfile('notebook2.py')
132 assert not os.path.isfile('notebook2.py')
143
133
144
134
145 def test_override_config(self):
135 def test_override_config(self):
146 """
136 """
147 Can the default config be overriden?
137 Can the default config be overriden?
148 """
138 """
149 with self.create_temp_cwd(['notebook*.ipynb',
139 with self.create_temp_cwd(['notebook*.ipynb',
150 'ipython_nbconvert_config.py',
140 'ipython_nbconvert_config.py',
151 'override.py']):
141 'override.py']):
152 self.call(IPYTHON + ' nbconvert --config="override.py"')
142 self.call('nbconvert --config="override.py"')
153 assert not os.path.isfile('notebook1.py')
143 assert not os.path.isfile('notebook1.py')
154 assert os.path.isfile('notebook2.py')
144 assert os.path.isfile('notebook2.py')
General Comments 0
You need to be logged in to leave comments. Login now