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