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