##// END OF EJS Templates
move the pandoc_available(...) call inside get_pandoc_version(...) as it also tested for availability
Daniel B. Vasquez -
Show More
@@ -1,158 +1,156 b''
1 """Utility for calling pandoc"""
1 """Utility for calling pandoc"""
2 #-----------------------------------------------------------------------------
2 #-----------------------------------------------------------------------------
3 # Copyright (c) 2013 the IPython Development Team.
3 # Copyright (c) 2013 the IPython Development Team.
4 #
4 #
5 # Distributed under the terms of the Modified BSD License.
5 # Distributed under the terms of the Modified BSD License.
6 #
6 #
7 # The full license is in the file COPYING.txt, distributed with this software.
7 # The full license is in the file COPYING.txt, distributed with this software.
8 #-----------------------------------------------------------------------------
8 #-----------------------------------------------------------------------------
9
9
10 #-----------------------------------------------------------------------------
10 #-----------------------------------------------------------------------------
11 # Imports
11 # Imports
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 from __future__ import print_function
14 from __future__ import print_function
15
15
16 # Stdlib imports
16 # Stdlib imports
17 import subprocess
17 import subprocess
18 import re
18 import re
19 import warnings
19 import warnings
20 from io import TextIOWrapper, BytesIO
20 from io import TextIOWrapper, BytesIO
21
21
22 # IPython imports
22 # IPython imports
23 from IPython.utils.py3compat import cast_bytes
23 from IPython.utils.py3compat import cast_bytes
24 from IPython.utils.version import check_version
24 from IPython.utils.version import check_version
25
25
26
26
27 from .exceptions import ConversionException
27 from .exceptions import ConversionException
28
28
29
29
30 #----------------------------------------------------------------------------
30 #----------------------------------------------------------------------------
31 # Preliminary checks.
31 # Preliminary checks.
32 # Not finding Pandoc is not always fatal so only a warning is issued at the
32 # Not finding Pandoc is not always fatal so only a warning is issued at the
33 # module root level so that the import of this module is not fatal.
33 # module root level so that the import of this module is not fatal.
34 #----------------------------------------------------------------------------
34 #----------------------------------------------------------------------------
35
35
36 class PandocMissing(ConversionException):
36 class PandocMissing(ConversionException):
37 """Exception raised when Pandoc is missing. """
37 """Exception raised when Pandoc is missing. """
38 def __init__(self, cmd, exc, *args, **kwargs):
38 def __init__(self, cmd, exc, *args, **kwargs):
39 super(PandocMissing, self).__init__( "The command '%s' returned an error: %s.\n" %(" ".join(cmd), exc) +
39 super(PandocMissing, self).__init__( "The command '%s' returned an error: %s.\n" %(" ".join(cmd), exc) +
40 "Please check that pandoc is installed:\n" +
40 "Please check that pandoc is installed:\n" +
41 "http://johnmacfarlane.net/pandoc/installing.html" )
41 "http://johnmacfarlane.net/pandoc/installing.html" )
42
42
43 def pandoc_available(failmode="return", warn=False, alt=None):
43 def pandoc_available(failmode="return", warn=False, alt=None):
44 """Is pandoc available. Only tries to call Pandoc
44 """Is pandoc available. Only tries to call Pandoc
45 and inform you that it succeeded or failed.
45 and inform you that it succeeded or failed.
46
46
47 Parameters
47 Parameters
48 ----------
48 ----------
49 - failmode : string
49 - failmode : string
50 either "return" or "raise". If "return" and pandoc
50 either "return" or "raise". If "return" and pandoc
51 is not available, will return (False, e) where e is
51 is not available, will return (False, e) where e is
52 the exception returned by subprocess.check_call.
52 the exception returned by subprocess.check_call.
53 - warn : bool
53 - warn : bool
54 issue a user warning if pandoc is not available.
54 issue a user warning if pandoc is not available.
55 - alt: list of strings
55 - alt: list of strings
56 command to print in the error (not used as actual call)
56 command to print in the error (not used as actual call)
57
57
58 Return
58 Return
59 ------
59 ------
60 out : (Bool, Exception)
60 out : (Bool, Exception)
61 On success will return (True, None). On failure and failmode=="return"
61 On success will return (True, None). On failure and failmode=="return"
62 will return (False, OSError instance)
62 will return (False, OSError instance)
63 """
63 """
64
64
65 cmd = ["pandoc", "-v"]
65 cmd = ["pandoc", "-v"]
66
66
67 try:
67 try:
68 out = subprocess.check_output(cmd, universal_newlines=True)
68 out = subprocess.check_output(cmd, universal_newlines=True)
69 return True, None
69 return True, None
70 except OSError as e:
70 except OSError as e:
71 if warn:
71 if warn:
72 warnings.warn(
72 warnings.warn(
73 "Pandoc cannot be found (calling %s failed).\n" % " ".join(alt or cmd) +
73 "Pandoc cannot be found (calling %s failed).\n" % " ".join(alt or cmd) +
74 "Please check that pandoc is installed:\n" +
74 "Please check that pandoc is installed:\n" +
75 "http://johnmacfarlane.net/pandoc/installing.html"
75 "http://johnmacfarlane.net/pandoc/installing.html"
76 )
76 )
77
77
78 if failmode == "return":
78 if failmode == "return":
79 return False, e
79 return False, e
80 else:
80 else:
81 raise PandocMissing(alt or cmd, e)
81 raise PandocMissing(alt or cmd, e)
82
82
83
83
84 #-----------------------------------------------------------------------------
84 #-----------------------------------------------------------------------------
85 # Classes and functions
85 # Classes and functions
86 #-----------------------------------------------------------------------------
86 #-----------------------------------------------------------------------------
87
87
88
88
89 minimal_version = "1.12.1"
89 minimal_version = "1.12.1"
90 minimal_version_ok = False
90 minimal_version_ok = False
91
91
92 def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):
92 def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):
93 """Convert an input string in format `from` to format `to` via pandoc.
93 """Convert an input string in format `from` to format `to` via pandoc.
94
94
95 This function will raise PandocMissing if pandoc is not installed.
95 This function will raise PandocMissing if pandoc is not installed.
96 Any error messages generated by pandoc are printed to stderr.
96 Any error messages generated by pandoc are printed to stderr.
97
97
98 Parameters
98 Parameters
99 ----------
99 ----------
100 source : string
100 source : string
101 Input string, assumed to be valid format `from`.
101 Input string, assumed to be valid format `from`.
102 fmt : string
102 fmt : string
103 The name of the input format (markdown, etc.)
103 The name of the input format (markdown, etc.)
104 to : string
104 to : string
105 The name of the output format (html, etc.)
105 The name of the output format (html, etc.)
106
106
107 Returns
107 Returns
108 -------
108 -------
109 out : unicode
109 out : unicode
110 Output as returned by pandoc.
110 Output as returned by pandoc.
111 """
111 """
112 cmd = ['pandoc', '-f', fmt, '-t', to]
112 cmd = ['pandoc', '-f', fmt, '-t', to]
113 if extra_args:
113 if extra_args:
114 cmd.extend(extra_args)
114 cmd.extend(extra_args)
115
115
116 # if pandoc is missing let the exception bubble us out of here
116 # this will raise an exception that will pop us out of here
117 pandoc_available(failmode="raise", alt=cmd)
118 check_pandoc_version()
117 check_pandoc_version()
119
118
120 # we can safely continue
119 # we can safely continue
121 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
120 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
122 out, _ = p.communicate(cast_bytes(source, encoding))
121 out, _ = p.communicate(cast_bytes(source, encoding))
123 out = TextIOWrapper(BytesIO(out), encoding, 'replace').read()
122 out = TextIOWrapper(BytesIO(out), encoding, 'replace').read()
124 return out.rstrip('\n')
123 return out.rstrip('\n')
125
124
126
125
127 def get_pandoc_version():
126 def get_pandoc_version():
128 """Gets the Pandoc version if Pandoc is installed.
127 """Gets the Pandoc version if Pandoc is installed.
129 PandocMissing will be raised if pandoc is unavailable.
128 PandocMissing will be raised if pandoc is unavailable.
130 """
129 """
131 try:
130 try:
132 if not minimal_version_ok:
131 if not minimal_version_ok:
133 raise AttributeError()
132 raise AttributeError()
134 else:
133 else:
135 return pandoc.version
134 return pandoc.version
136 except AttributeError:
135 except AttributeError:
136 # if pandoc is missing let the exception bubble us out of here
137 pandoc_available(failmode="raise")
137 cmd = ["pandoc", "-v"]
138 cmd = ["pandoc", "-v"]
138 try:
139 out = subprocess.check_output(cmd, universal_newlines=True)
139 out = subprocess.check_output(cmd, universal_newlines=True)
140 except OSError as e:
141 raise PandocMissing(cmd, e)
142 pv_re = re.compile(r'(\d{0,3}\.\d{0,3}\.\d{0,3})')
140 pv_re = re.compile(r'(\d{0,3}\.\d{0,3}\.\d{0,3})')
143 pandoc.version = pv_re.search(out).group(0)
141 pandoc.version = pv_re.search(out).group(0)
144 return pandoc.version
142 return pandoc.version
145
143
146 def check_pandoc_version():
144 def check_pandoc_version():
147 """Returns True if minimal pandoc version is met.
145 """Returns True if minimal pandoc version is met.
148 PandocMissing will be raised if pandoc is unavailable.
146 PandocMissing will be raised if pandoc is unavailable.
149 """
147 """
150 global minimal_version_ok
148 global minimal_version_ok
151 if not minimal_version_ok:
149 if not minimal_version_ok:
152 minimal_version_ok = check_version( get_pandoc_version(), minimal_version )
150 minimal_version_ok = check_version( get_pandoc_version(), minimal_version )
153 if not minimal_version_ok:
151 if not minimal_version_ok:
154 warnings.warn( "You are using an old version of pandoc (%s)\n" % pandoc.version +
152 warnings.warn( "You are using an old version of pandoc (%s)\n" % pandoc.version +
155 "Recommended version is %s.\nTry updating." % minimal_version +
153 "Recommended version is %s.\nTry updating." % minimal_version +
156 "http://johnmacfarlane.net/pandoc/installing.html.\nContinuing with doubts...",
154 "http://johnmacfarlane.net/pandoc/installing.html.\nContinuing with doubts...",
157 RuntimeWarning, stacklevel=2)
155 RuntimeWarning, stacklevel=2)
158 return minimal_version_ok
156 return minimal_version_ok
General Comments 0
You need to be logged in to leave comments. Login now