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