##// END OF EJS Templates
Revised pandoc version detection.
cel -
Show More
@@ -1,131 +1,141 b''
1 """Utility for calling pandoc"""
1 """Utility for calling pandoc"""
2 #-----------------------------------------------------------------------------
2 #-----------------------------------------------------------------------------
3 # Copyright (c) 2014 the IPython Development Team.
3 # Copyright (c) 2014 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 from __future__ import print_function
13 from __future__ import print_function
14
14
15 # Stdlib imports
15 # Stdlib imports
16 import subprocess
16 import subprocess
17 import warnings
17 import warnings
18 import re
18 from io import TextIOWrapper, BytesIO
19 from io import TextIOWrapper, BytesIO
19
20
20 # IPython imports
21 # IPython imports
21 from IPython.utils.py3compat import cast_bytes
22 from IPython.utils.py3compat import cast_bytes
22 from IPython.utils.version import check_version
23 from IPython.utils.version import check_version
23 from IPython.utils.process import is_cmd_found, FindCmdError
24 from IPython.utils.process import is_cmd_found, FindCmdError
24
25
25 from .exceptions import ConversionException
26 from .exceptions import ConversionException
26
27
27 #-----------------------------------------------------------------------------
28 #-----------------------------------------------------------------------------
28 # Classes and functions
29 # Classes and functions
29 #-----------------------------------------------------------------------------
30 #-----------------------------------------------------------------------------
30 _minimal_version = "1.12.1"
31 _minimal_version = "1.12.1"
31
32
32 def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):
33 def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):
33 """Convert an input string in format `from` to format `to` via pandoc.
34 """Convert an input string in format `from` to format `to` via pandoc.
34
35
35 Parameters
36 Parameters
36 ----------
37 ----------
37 source : string
38 source : string
38 Input string, assumed to be valid format `from`.
39 Input string, assumed to be valid format `from`.
39 fmt : string
40 fmt : string
40 The name of the input format (markdown, etc.)
41 The name of the input format (markdown, etc.)
41 to : string
42 to : string
42 The name of the output format (html, etc.)
43 The name of the output format (html, etc.)
43
44
44 Returns
45 Returns
45 -------
46 -------
46 out : unicode
47 out : unicode
47 Output as returned by pandoc.
48 Output as returned by pandoc.
48
49
49 Raises
50 Raises
50 ------
51 ------
51 PandocMissing
52 PandocMissing
52 If pandoc is not installed.
53 If pandoc is not installed.
53
54
54 Any error messages generated by pandoc are printed to stderr.
55 Any error messages generated by pandoc are printed to stderr.
55
56
56 """
57 """
57 cmd = ['pandoc', '-f', fmt, '-t', to]
58 cmd = ['pandoc', '-f', fmt, '-t', to]
58 if extra_args:
59 if extra_args:
59 cmd.extend(extra_args)
60 cmd.extend(extra_args)
60
61
61 # this will raise an exception that will pop us out of here
62 # this will raise an exception that will pop us out of here
62 check_pandoc_version()
63 check_pandoc_version()
63
64
64 # we can safely continue
65 # we can safely continue
65 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
66 p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
66 out, _ = p.communicate(cast_bytes(source, encoding))
67 out, _ = p.communicate(cast_bytes(source, encoding))
67 out = TextIOWrapper(BytesIO(out), encoding, 'replace').read()
68 out = TextIOWrapper(BytesIO(out), encoding, 'replace').read()
68 return out.rstrip('\n')
69 return out.rstrip('\n')
69
70
70
71
71 def get_pandoc_version():
72 def get_pandoc_version():
72 """Gets the Pandoc version if Pandoc is installed.
73 """Gets the Pandoc version if Pandoc is installed.
73
74
74 If the minimal version is not met, it will probe Pandoc for its version, cache it and return that value.
75 If the minimal version is not met, it will probe Pandoc for its version, cache it and return that value.
75 If the minimal version is met, it will return the cached version and stop probing Pandoc
76 If the minimal version is met, it will return the cached version and stop probing Pandoc
76 (unless :func:`clean_cache()` is called).
77 (unless :func:`clean_cache()` is called).
77
78
78 Raises
79 Raises
79 ------
80 ------
80 PandocMissing
81 PandocMissing
81 If pandoc is unavailable.
82 If pandoc is unavailable.
82 """
83 """
83 global __version
84 global __version
84
85
85 if __version is None:
86 if __version is None:
86 if not is_cmd_found('pandoc'):
87 if not is_cmd_found('pandoc'):
87 raise PandocMissing()
88 raise PandocMissing()
88
89
89 out = subprocess.check_output(['pandoc', '-v'],
90 out = subprocess.check_output(['pandoc', '-v'],
90 universal_newlines=True)
91 universal_newlines=True)
91 out_lines = out.splitlines()
92 out_lines = out.splitlines()
92 pandoc_line = out_lines[0]
93 version_pattern = re.compile(r"^\d+(\.\d+){1,}$")
93 __version = pandoc_line.lstrip("pandoc ")
94 for tok in out_lines[0].split():
95 if version_pattern.match(tok):
96 __version = tok
97 break
94 return __version
98 return __version
95
99
96
100
97 def check_pandoc_version():
101 def check_pandoc_version():
98 """Returns True if minimal pandoc version is met.
102 """Returns True if minimal pandoc version is met.
99
103
100 Raises
104 Raises
101 ------
105 ------
102 PandocMissing
106 PandocMissing
103 If pandoc is unavailable.
107 If pandoc is unavailable.
104 """
108 """
105 v = get_pandoc_version()
109 v = get_pandoc_version()
110 if v is None:
111 warnings.warn("Sorry, we cannot determine the version of pandoc.\n"
112 "Please consider reporting this issue and include the"
113 "output of pandoc --version.\nContinuing...",
114 RuntimeWarning, stacklevel=2)
115 return False
106 ok = check_version(v , _minimal_version )
116 ok = check_version(v , _minimal_version )
107 if not ok:
117 if not ok:
108 warnings.warn( "You are using an old version of pandoc (%s)\n" % v +
118 warnings.warn( "You are using an old version of pandoc (%s)\n" % v +
109 "Recommended version is %s.\nTry updating." % _minimal_version +
119 "Recommended version is %s.\nTry updating." % _minimal_version +
110 "http://johnmacfarlane.net/pandoc/installing.html.\nContinuing with doubts...",
120 "http://johnmacfarlane.net/pandoc/installing.html.\nContinuing with doubts...",
111 RuntimeWarning, stacklevel=2)
121 RuntimeWarning, stacklevel=2)
112 return ok
122 return ok
113
123
114 #-----------------------------------------------------------------------------
124 #-----------------------------------------------------------------------------
115 # Exception handling
125 # Exception handling
116 #-----------------------------------------------------------------------------
126 #-----------------------------------------------------------------------------
117 class PandocMissing(ConversionException):
127 class PandocMissing(ConversionException):
118 """Exception raised when Pandoc is missing. """
128 """Exception raised when Pandoc is missing. """
119 def __init__(self, *args, **kwargs):
129 def __init__(self, *args, **kwargs):
120 super(PandocMissing, self).__init__( "Pandoc wasn't found.\n" +
130 super(PandocMissing, self).__init__( "Pandoc wasn't found.\n" +
121 "Please check that pandoc is installed:\n" +
131 "Please check that pandoc is installed:\n" +
122 "http://johnmacfarlane.net/pandoc/installing.html" )
132 "http://johnmacfarlane.net/pandoc/installing.html" )
123
133
124 #-----------------------------------------------------------------------------
134 #-----------------------------------------------------------------------------
125 # Internal state management
135 # Internal state management
126 #-----------------------------------------------------------------------------
136 #-----------------------------------------------------------------------------
127 def clean_cache():
137 def clean_cache():
128 global __version
138 global __version
129 __version = None
139 __version = None
130
140
131 __version = None
141 __version = None
General Comments 0
You need to be logged in to leave comments. Login now