Show More
@@ -0,0 +1,65 b'' | |||||
|
1 | """Test Pandoc module""" | |||
|
2 | ||||
|
3 | #----------------------------------------------------------------------------- | |||
|
4 | # Copyright (C) 2013 The IPython Development Team | |||
|
5 | # | |||
|
6 | # Distributed under the terms of the BSD License. The full license is in | |||
|
7 | # the file COPYING, distributed as part of this software. | |||
|
8 | #----------------------------------------------------------------------------- | |||
|
9 | ||||
|
10 | #----------------------------------------------------------------------------- | |||
|
11 | # Imports | |||
|
12 | #----------------------------------------------------------------------------- | |||
|
13 | ||||
|
14 | import os | |||
|
15 | ||||
|
16 | from .base import TestsBase | |||
|
17 | from ..utils import pandoc | |||
|
18 | ||||
|
19 | from IPython.testing import decorators as dec | |||
|
20 | ||||
|
21 | #----------------------------------------------------------------------------- | |||
|
22 | # Constants | |||
|
23 | #----------------------------------------------------------------------------- | |||
|
24 | ||||
|
25 | ||||
|
26 | #----------------------------------------------------------------------------- | |||
|
27 | # Classes and functions | |||
|
28 | #----------------------------------------------------------------------------- | |||
|
29 | ||||
|
30 | class TestPandoc(TestsBase): | |||
|
31 | """Collection of Pandoc tests""" | |||
|
32 | ||||
|
33 | def __init__(self, *args, **kwargs): | |||
|
34 | super(TestPandoc, self).__init__(*args, **kwargs) | |||
|
35 | self.original_env = os.environ.copy() | |||
|
36 | ||||
|
37 | @dec.onlyif_cmds_exist('pandoc') | |||
|
38 | def test_pandoc_available(self): | |||
|
39 | """ Test behaviour of pandoc_available() """ | |||
|
40 | os.environ["PATH"] = "" | |||
|
41 | assert not pandoc.pandoc_available() | |||
|
42 | try: | |||
|
43 | pandoc.pandoc_available(failmode="raise") | |||
|
44 | except pandoc.PandocMissing: | |||
|
45 | assert True | |||
|
46 | ||||
|
47 | os.environ["PATH"] = self.original_env["PATH"] | |||
|
48 | assert pandoc.pandoc_available() | |||
|
49 | try: | |||
|
50 | pandoc.pandoc_available(failmode="raise") | |||
|
51 | except pandoc.PandocMissing: | |||
|
52 | assert False | |||
|
53 | ||||
|
54 | @dec.onlyif_cmds_exist('pandoc') | |||
|
55 | def test_minimal_version(self): | |||
|
56 | original_minversion = pandoc.minimal_version | |||
|
57 | ||||
|
58 | pandoc.minimal_version = "120.0" | |||
|
59 | assert not pandoc.check_pandoc_version() | |||
|
60 | ||||
|
61 | pandoc.minimal_version = pandoc.get_pandoc_version() | |||
|
62 | assert pandoc.check_pandoc_version() | |||
|
63 | ||||
|
64 | ||||
|
65 |
@@ -22,6 +22,7 b' from io import TextIOWrapper, BytesIO' | |||||
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 | from IPython.utils.process import find_cmd, FindCmdError | |||
25 |
|
26 | |||
26 |
|
27 | |||
27 | from .exceptions import ConversionException |
|
28 | from .exceptions import ConversionException | |
@@ -33,14 +34,25 b' from .exceptions import ConversionException' | |||||
33 | # module root level so that the import of this module is not fatal. |
|
34 | # module root level so that the import of this module is not fatal. | |
34 | #---------------------------------------------------------------------------- |
|
35 | #---------------------------------------------------------------------------- | |
35 |
|
36 | |||
|
37 | # command line to make pandoc print it's version. It is also the | |||
|
38 | # easiest way to make pandoc return at all. | |||
|
39 | __pandoc_version_call = ['pandoc', '-v'] | |||
|
40 | ||||
36 | class PandocMissing(ConversionException): |
|
41 | class PandocMissing(ConversionException): | |
37 | """Exception raised when Pandoc is missing. """ |
|
42 | """Exception raised when Pandoc is missing. """ | |
38 | def __init__(self, cmd, exc, *args, **kwargs): |
|
43 | def __init__(self, cmd, exc, *args, **kwargs): | |
39 | super(PandocMissing, self).__init__( "The command '%s' returned an error: %s.\n" %(" ".join(cmd), exc) + |
|
44 | super(PandocMissing, self).__init__( "The command '%s' returned an error: %s.\n" %(" ".join(cmd), exc) + | |
40 | "Please check that pandoc is installed:\n" + |
|
45 | "Please check that pandoc is installed:\n" + | |
41 | "http://johnmacfarlane.net/pandoc/installing.html" ) |
|
46 | "http://johnmacfarlane.net/pandoc/installing.html" ) | |
|
47 | self.exc = exc | |||
|
48 | ||||
|
49 | def __bool__(self): | |||
|
50 | return False | |||
|
51 | ||||
|
52 | __nonzero__ = __bool__ | |||
|
53 | ||||
42 |
|
54 | |||
43 |
def pandoc_available(failmode="return", warn=False |
|
55 | def pandoc_available(failmode="return", warn=False): | |
44 | """Is pandoc available. Only tries to call Pandoc |
|
56 | """Is pandoc available. Only tries to call Pandoc | |
45 | and inform you that it succeeded or failed. |
|
57 | and inform you that it succeeded or failed. | |
46 |
|
58 | |||
@@ -52,49 +64,57 b' def pandoc_available(failmode="return", warn=False, alt=None):' | |||||
52 | the exception returned by subprocess.check_call. |
|
64 | the exception returned by subprocess.check_call. | |
53 | - warn : bool |
|
65 | - warn : bool | |
54 | issue a user warning if pandoc is not available. |
|
66 | issue a user warning if pandoc is not available. | |
55 | - alt: list of strings |
|
|||
56 | command to print in the error (not used as actual call) |
|
|||
57 |
|
67 | |||
58 | Return |
|
68 | Return | |
59 | ------ |
|
69 | ------ | |
60 | out : (Bool, Exception) |
|
70 | out : (Bool, Exception) | |
61 |
On success will return |
|
71 | On success will return True. On failure and failmode=="return" | |
62 |
will return |
|
72 | will return False-valued PandocMissing instance | |
63 | """ |
|
73 | """ | |
64 |
|
74 | |||
65 | cmd = ["pandoc", "-v"] |
|
|||
66 |
|
||||
67 | try: |
|
75 | try: | |
68 | out = subprocess.check_output(cmd, universal_newlines=True) |
|
76 | find_cmd("pandoc") | |
69 |
return True |
|
77 | return True | |
70 |
except |
|
78 | except FindCmdError as e: | |
71 | if warn: |
|
79 | if warn: | |
72 | warnings.warn( |
|
80 | warnings.warn( | |
73 |
"Pandoc cannot be found (calling %s failed).\n" % " ".join(alt or |
|
81 | "Pandoc cannot be found (calling %s failed).\n" % " ".join(alt or __pandoc_version_call) + | |
74 | "Please check that pandoc is installed:\n" + |
|
82 | "Please check that pandoc is installed:\n" + | |
75 | "http://johnmacfarlane.net/pandoc/installing.html" |
|
83 | "http://johnmacfarlane.net/pandoc/installing.html" | |
76 | ) |
|
84 | ) | |
77 |
|
85 | |||
|
86 | exc = PandocMissing("pandoc", e) | |||
78 | if failmode == "return": |
|
87 | if failmode == "return": | |
79 |
return |
|
88 | return exc | |
80 | else: |
|
89 | else: | |
81 | raise PandocMissing(alt or cmd, e) |
|
90 | raise exc | |
82 |
|
91 | |||
83 |
|
92 | |||
84 | #----------------------------------------------------------------------------- |
|
93 | #----------------------------------------------------------------------------- | |
85 | # Classes and functions |
|
94 | # Classes and functions | |
86 | #----------------------------------------------------------------------------- |
|
95 | #----------------------------------------------------------------------------- | |
|
96 | minimal_version = "1.12.1" | |||
87 |
|
97 | |||
|
98 | # The following holds cached values about the pandoc executable. | |||
|
99 | def clean_cache(new=False): | |||
|
100 | if new: | |||
|
101 | global __cache | |||
|
102 | cache = {} | |||
|
103 | __cache = cache | |||
|
104 | else: | |||
|
105 | cache = __cache | |||
|
106 | cache.clear() | |||
|
107 | ||||
|
108 | cache['version_ok'] = False | |||
|
109 | cache['version'] = None | |||
|
110 | return cache | |||
|
111 | ||||
|
112 | __cache = clean_cache(new=True) | |||
88 |
|
113 | |||
89 | minimal_version = "1.12.1" |
|
|||
90 | minimal_version_ok = False |
|
|||
91 |
|
114 | |||
92 | def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'): |
|
115 | def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'): | |
93 | """Convert an input string in format `from` to format `to` via pandoc. |
|
116 | """Convert an input string in format `from` to format `to` via pandoc. | |
94 |
|
117 | |||
95 | This function will raise PandocMissing if pandoc is not installed. |
|
|||
96 | Any error messages generated by pandoc are printed to stderr. |
|
|||
97 |
|
||||
98 | Parameters |
|
118 | Parameters | |
99 | ---------- |
|
119 | ---------- | |
100 | source : string |
|
120 | source : string | |
@@ -108,6 +128,12 b" def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):" | |||||
108 | ------- |
|
128 | ------- | |
109 | out : unicode |
|
129 | out : unicode | |
110 | Output as returned by pandoc. |
|
130 | Output as returned by pandoc. | |
|
131 | ||||
|
132 | Exceptions | |||
|
133 | ---------- | |||
|
134 | This function will raise PandocMissing if pandoc is not installed. | |||
|
135 | Any error messages generated by pandoc are printed to stderr. | |||
|
136 | ||||
111 | """ |
|
137 | """ | |
112 | cmd = ['pandoc', '-f', fmt, '-t', to] |
|
138 | cmd = ['pandoc', '-f', fmt, '-t', to] | |
113 | if extra_args: |
|
139 | if extra_args: | |
@@ -125,32 +151,43 b" def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):" | |||||
125 |
|
151 | |||
126 | def get_pandoc_version(): |
|
152 | def get_pandoc_version(): | |
127 | """Gets the Pandoc version if Pandoc is installed. |
|
153 | """Gets the Pandoc version if Pandoc is installed. | |
|
154 | ||||
|
155 | Return | |||
|
156 | ------ | |||
|
157 | If the minimal version is not met, it will probe Pandoc for its version, cache it and return that value. | |||
|
158 | If the minimal version is met, it will return the cached version and stop probing Pandoc | |||
|
159 | (unless `clean_cache()` is called). | |||
|
160 | ||||
|
161 | Exceptions | |||
|
162 | ---------- | |||
128 | PandocMissing will be raised if pandoc is unavailable. |
|
163 | PandocMissing will be raised if pandoc is unavailable. | |
129 | """ |
|
164 | """ | |
130 | try: |
|
165 | ||
131 | if not minimal_version_ok: |
|
166 | if __cache['version_ok'] and __cache['version']: | |
132 | raise AttributeError() |
|
167 | return __cache['version'] | |
133 |
|
|
168 | else: | |
134 | return pandoc.version |
|
169 | pandoc_available(failmode="raise") | |
135 | except AttributeError: |
|
170 | out = subprocess.check_output(__pandoc_version_call, universal_newlines=True) | |
136 | # if pandoc is missing let the exception bubble us out of here |
|
|||
137 | pandoc_available(failmode="raise") |
|
|||
138 | cmd = ["pandoc", "-v"] |
|
|||
139 | out = subprocess.check_output(cmd, universal_newlines=True) |
|
|||
140 | pv_re = re.compile(r'(\d{0,3}\.\d{0,3}\.\d{0,3})') |
|
171 | pv_re = re.compile(r'(\d{0,3}\.\d{0,3}\.\d{0,3})') | |
141 |
|
|
172 | __cache['version'] = version = pv_re.search(out).group(0) | |
142 |
return |
|
173 | return version | |
|
174 | ||||
143 |
|
175 | |||
144 | def check_pandoc_version(): |
|
176 | def check_pandoc_version(): | |
145 | """Returns True if minimal pandoc version is met. |
|
177 | """Returns True if minimal pandoc version is met. | |
|
178 | ||||
|
179 | Exceptions | |||
|
180 | ---------- | |||
146 | PandocMissing will be raised if pandoc is unavailable. |
|
181 | PandocMissing will be raised if pandoc is unavailable. | |
147 | """ |
|
182 | """ | |
148 | global minimal_version_ok |
|
183 | ok = __cache['version_ok'] | |
149 |
if not |
|
184 | if not ok: | |
150 |
|
|
185 | __cache['version_ok'] = ok = check_version( get_pandoc_version(), minimal_version ) | |
151 |
if not |
|
186 | if not ok: | |
152 |
warnings.warn( "You are using an old version of pandoc (%s)\n" % |
|
187 | warnings.warn( "You are using an old version of pandoc (%s)\n" % __cache['version'] + | |
153 | "Recommended version is %s.\nTry updating." % minimal_version + |
|
188 | "Recommended version is %s.\nTry updating." % minimal_version + | |
154 | "http://johnmacfarlane.net/pandoc/installing.html.\nContinuing with doubts...", |
|
189 | "http://johnmacfarlane.net/pandoc/installing.html.\nContinuing with doubts...", | |
155 | RuntimeWarning, stacklevel=2) |
|
190 | RuntimeWarning, stacklevel=2) | |
156 |
return |
|
191 | return __cache['version_ok'] | |
|
192 | ||||
|
193 |
General Comments 0
You need to be logged in to leave comments.
Login now