##// END OF EJS Templates
big cleanup of nbconvert.utils.pandoc module. Remove useless functions, less cached values.
Daniel B. Vasquez -
Show More
@@ -1,65 +1,75 b''
1 1 """Test Pandoc module"""
2 2
3 3 #-----------------------------------------------------------------------------
4 4 # Copyright (C) 2013 The IPython Development Team
5 5 #
6 6 # Distributed under the terms of the BSD License. The full license is in
7 7 # the file COPYING, distributed as part of this software.
8 8 #-----------------------------------------------------------------------------
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13
14 14 import os
15 15
16 16 from .base import TestsBase
17 17 from ..utils import pandoc
18 18
19 19 from IPython.testing import decorators as dec
20 20
21 21 #-----------------------------------------------------------------------------
22 22 # Constants
23 23 #-----------------------------------------------------------------------------
24 24
25 25
26 26 #-----------------------------------------------------------------------------
27 27 # Classes and functions
28 28 #-----------------------------------------------------------------------------
29 29
30
30 31 class TestPandoc(TestsBase):
31 32 """Collection of Pandoc tests"""
32 33
33 34 def __init__(self, *args, **kwargs):
34 35 super(TestPandoc, self).__init__(*args, **kwargs)
35 36 self.original_env = os.environ.copy()
36 37
37 38 @dec.onlyif_cmds_exist('pandoc')
38 39 def test_pandoc_available(self):
39 """ Test behaviour of pandoc_available() """
40 """ Test behaviour that pandoc functions raise PandocMissing as documented """
41 pandoc.clean_cache()
42
40 43 os.environ["PATH"] = ""
41 assert not pandoc.pandoc_available()
42 try:
43 pandoc.pandoc_available(failmode="raise")
44 except pandoc.PandocMissing:
45 assert True
44 assert pandoc_function_raised_missing(pandoc.get_pandoc_version) == True
45 assert pandoc_function_raised_missing(pandoc.check_pandoc_version) == True
46 assert pandoc_function_raised_missing(pandoc.pandoc, "", "markdown", "html") == True
46 47
48 # original_env["PATH"] should contain pandoc
47 49 os.environ["PATH"] = self.original_env["PATH"]
48 assert pandoc.pandoc_available()
49 try:
50 pandoc.pandoc_available(failmode="raise")
51 except pandoc.PandocMissing:
52 assert False
50 assert pandoc_function_raised_missing(pandoc.get_pandoc_version) == False
51 assert pandoc_function_raised_missing(pandoc.check_pandoc_version) == False
52 assert pandoc_function_raised_missing(pandoc.pandoc, "", "markdown", "html") == False
53
53 54
54 55 @dec.onlyif_cmds_exist('pandoc')
55 56 def test_minimal_version(self):
56 original_minversion = pandoc.minimal_version
57 original_minversion = pandoc._minimal_version
57 58
58 pandoc.minimal_version = "120.0"
59 pandoc._minimal_version = "120.0"
59 60 assert not pandoc.check_pandoc_version()
60 61
61 pandoc.minimal_version = pandoc.get_pandoc_version()
62 pandoc._minimal_version = pandoc.get_pandoc_version()
62 63 assert pandoc.check_pandoc_version()
63 64
64 65
65 66
67
68 def pandoc_function_raised_missing(f, *args, **kwargs):
69 try:
70 f(*args, **kwargs)
71 except pandoc.PandocMissing as e:
72 print e
73 return True
74 else:
75 return False
@@ -1,192 +1,135 b''
1 1 """Utility for calling pandoc"""
2 2 #-----------------------------------------------------------------------------
3 3 # Copyright (c) 2013 the IPython Development Team.
4 4 #
5 5 # Distributed under the terms of the Modified BSD License.
6 6 #
7 7 # The full license is in the file COPYING.txt, distributed with this software.
8 8 #-----------------------------------------------------------------------------
9 9
10 10 #-----------------------------------------------------------------------------
11 11 # Imports
12 12 #-----------------------------------------------------------------------------
13 13
14 14 from __future__ import print_function
15 15
16 16 # Stdlib imports
17 17 import subprocess
18 18 import re
19 19 import warnings
20 20 from io import TextIOWrapper, BytesIO
21 21
22 22 # IPython imports
23 23 from IPython.utils.py3compat import cast_bytes
24 24 from IPython.utils.version import check_version
25 from IPython.utils.process import find_cmd, FindCmdError
25 from IPython.utils.process import is_cmd_found, FindCmdError
26 26
27 27
28 28 from .exceptions import ConversionException
29 29
30 30 #-----------------------------------------------------------------------------
31 31 # Classes and functions
32 32 #-----------------------------------------------------------------------------
33 minimal_version = "1.12.1"
34
35 # command line to make pandoc print it's version. It is also the
36 # easiest way to make pandoc return at all.
37 __pandoc_version_call = ['pandoc', '-v']
38
33 _minimal_version = "1.12.1"
39 34
40 35 def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):
41 36 """Convert an input string in format `from` to format `to` via pandoc.
42 37
43 38 Parameters
44 39 ----------
45 40 source : string
46 41 Input string, assumed to be valid format `from`.
47 42 fmt : string
48 43 The name of the input format (markdown, etc.)
49 44 to : string
50 45 The name of the output format (html, etc.)
51 46
52 47 Returns
53 48 -------
54 49 out : unicode
55 50 Output as returned by pandoc.
56 51
57 52 Exceptions
58 53 ----------
59 54 This function will raise PandocMissing if pandoc is not installed.
60 55 Any error messages generated by pandoc are printed to stderr.
61 56
62 57 """
63 58 cmd = ['pandoc', '-f', fmt, '-t', to]
64 59 if extra_args:
65 60 cmd.extend(extra_args)
66 61
67 62 # this will raise an exception that will pop us out of here
68 63 check_pandoc_version()
69 64
70 65 # we can safely continue
71 66 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
72 67 out, _ = p.communicate(cast_bytes(source, encoding))
73 68 out = TextIOWrapper(BytesIO(out), encoding, 'replace').read()
74 69 return out.rstrip('\n')
75 70
76 71
77 def pandoc_available(failmode="return", warn=False):
78 """Is pandoc available. Relies on `IPython.utils.process.find_cmd`.
79
80 Parameters
81 ----------
82 - failmode : string
83 either "return" or "raise". See below.
84 - warn : bool
85 issue a user warning if pandoc is not available.
86
87 Return
88 ------
89 out : (Bool, Exception)
90 On success will return True. On failure and failmode=="return"
91 will return False-valued PandocMissing instance. If failmode is
92 anything else, the function will not return but raise PandocMissing.
93 """
94
95 try:
96 find_cmd("pandoc")
97 return True
98 except FindCmdError as e:
99 if warn:
100 warnings.warn(
101 "Pandoc cannot be found (find_cmd('pandoc') failed).\n"+
102 "Please check that pandoc is installed:\n" +
103 "http://johnmacfarlane.net/pandoc/installing.html"
104 )
105
106 exc = PandocMissing("pandoc", e)
107 if failmode == "return":
108 return exc
109 else:
110 raise exc
111
112
113 72 def get_pandoc_version():
114 73 """Gets the Pandoc version if Pandoc is installed.
115 74
116 75 Return
117 76 ------
118 77 If the minimal version is not met, it will probe Pandoc for its version, cache it and return that value.
119 78 If the minimal version is met, it will return the cached version and stop probing Pandoc
120 79 (unless `clean_cache()` is called).
121 80
122 81 Exceptions
123 82 ----------
124 83 PandocMissing will be raised if pandoc is unavailable.
125 84 """
85 global __version
126 86
127 if __cache['version_ok'] and __cache['version']:
128 return __cache['version']
87 if __version is not None:
88 return __version
129 89 else:
130 pandoc_available(failmode="raise")
131 out = subprocess.check_output(__pandoc_version_call, universal_newlines=True)
90 if not is_cmd_found('pandoc'):
91 raise PandocMissing()
92
93 out = subprocess.check_output( ['pandoc', '-v'], universal_newlines=True)
132 94 pv_re = re.compile(r'(\d{0,3}\.\d{0,3}\.\d{0,3})')
133 __cache['version'] = version = pv_re.search(out).group(0)
134 return version
95 __version = pv_re.search(out).group(0)
96 return __version
135 97
136 98
137 99 def check_pandoc_version():
138 100 """Returns True if minimal pandoc version is met.
139 101
140 102 Exceptions
141 103 ----------
142 104 PandocMissing will be raised if pandoc is unavailable.
143 105 """
144 ok = __cache['version_ok']
145 if not ok:
146 __cache['version_ok'] = ok = check_version( get_pandoc_version(), minimal_version )
106 v = get_pandoc_version()
107 ok = check_version(v , _minimal_version )
147 108 if not ok:
148 warnings.warn( "You are using an old version of pandoc (%s)\n" % __cache['version'] +
149 "Recommended version is %s.\nTry updating." % minimal_version +
109 warnings.warn( "You are using an old version of pandoc (%s)\n" % v +
110 "Recommended version is %s.\nTry updating." % _minimal_version +
150 111 "http://johnmacfarlane.net/pandoc/installing.html.\nContinuing with doubts...",
151 112 RuntimeWarning, stacklevel=2)
152 return __cache['version_ok']
113 return ok
153 114
154 115 #-----------------------------------------------------------------------------
155 116 # Exception handling
156 117 #-----------------------------------------------------------------------------
157 118 class PandocMissing(ConversionException):
158 119 """Exception raised when Pandoc is missing. """
159 def __init__(self, cmd, exc, *args, **kwargs):
160 super(PandocMissing, self).__init__( "The command '%s' returned an error: %s.\n" %(" ".join(cmd), exc) +
120 def __init__(self, *args, **kwargs):
121 super(PandocMissing, self).__init__( "Pandoc wasn't found.\n" +
161 122 "Please check that pandoc is installed:\n" +
162 123 "http://johnmacfarlane.net/pandoc/installing.html" )
163 self.exc = exc
164
165 def __bool__(self):
166 return False
167
168 __nonzero__ = __bool__
169
170 124
171 125 #-----------------------------------------------------------------------------
172 126 # Internal state management
173 127 #-----------------------------------------------------------------------------
174 def clean_cache(new=False):
175 if new:
176 global __cache
177 cache = {}
178 __cache = cache
179 else:
180 cache = __cache
181 cache.clear()
182
183 cache['version_ok'] = False
184 cache['version'] = None
185 return cache
186
187 # The following holds cache values about the pandoc executable.
188 __cache = clean_cache(new=True)
128 def clean_cache():
129 global __version
130 __version = None
189 131
132 __version = None
190 133
191 134
192 135
General Comments 0
You need to be logged in to leave comments. Login now