##// END OF EJS Templates
pandoc version is now checked at each call to pandoc.pandoc(...). Version is tested with IPython.utils.version.version_check
pandoc version is now checked at each call to pandoc.pandoc(...). Version is tested with IPython.utils.version.version_check

File last commit:

r14763:42e936d6
r14763:42e936d6
Show More
pandoc.py
158 lines | 5.5 KiB | text/x-python | PythonLexer
"""Utility for calling pandoc"""
#-----------------------------------------------------------------------------
# Copyright (c) 2013 the IPython Development Team.
#
# Distributed under the terms of the Modified BSD License.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
#-----------------------------------------------------------------------------
# Imports
#-----------------------------------------------------------------------------
from __future__ import print_function
# Stdlib imports
import subprocess
import re
import warnings
from io import TextIOWrapper, BytesIO
# IPython imports
from IPython.utils.py3compat import cast_bytes
from IPython.utils.version import check_version
from .exceptions import ConversionException
#----------------------------------------------------------------------------
# Preliminary checks.
# Not finding Pandoc is not always fatal so only a warning is issued at the
# module root level so that the import of this module is not fatal.
#----------------------------------------------------------------------------
class PandocMissing(ConversionException):
"""Exception raised when Pandoc is missing. """
def __init__(self, cmd, exc, *args, **kwargs):
super(PandocMissing, self).__init__( "The command '%s' returned an error: %s.\n" %(" ".join(cmd), exc) +
"Please check that pandoc is installed:\n" +
"http://johnmacfarlane.net/pandoc/installing.html" )
def pandoc_available(failmode="return", warn=False, alt=None):
"""Is pandoc available. Only tries to call Pandoc
and inform you that it succeeded or failed.
Parameters
----------
- failmode : string
either "return" or "raise". If "return" and pandoc
is not available, will return (False, e) where e is
the exception returned by subprocess.check_call.
- warn : bool
issue a user warning if pandoc is not available.
- alt: list of strings
command to print in the error (not used as actual call)
Return
------
out : (Bool, Exception)
On success will return (True, None). On failure and failmode=="return"
will return (False, OSError instance)
"""
cmd = ["pandoc", "-v"]
try:
out = subprocess.check_output(cmd, universal_newlines=True)
return True, None
except OSError as e:
if warn:
warnings.warn(
"Pandoc cannot be found (calling %s failed).\n" % " ".join(alt or cmd) +
"Please check that pandoc is installed:\n" +
"http://johnmacfarlane.net/pandoc/installing.html"
)
if failmode == "return":
return False, e
else:
raise PandocMissing(alt or cmd, e)
#-----------------------------------------------------------------------------
# Classes and functions
#-----------------------------------------------------------------------------
minimal_version = "1.12.1"
minimal_version_ok = False
def pandoc(source, fmt, to, extra_args=None, encoding='utf-8'):
"""Convert an input string in format `from` to format `to` via pandoc.
This function will raise PandocMissing if pandoc is not installed.
Any error messages generated by pandoc are printed to stderr.
Parameters
----------
source : string
Input string, assumed to be valid format `from`.
fmt : string
The name of the input format (markdown, etc.)
to : string
The name of the output format (html, etc.)
Returns
-------
out : unicode
Output as returned by pandoc.
"""
cmd = ['pandoc', '-f', fmt, '-t', to]
if extra_args:
cmd.extend(extra_args)
# if pandoc is missing let the exception bubble us out of here
pandoc_available(failmode="raise", alt=cmd)
check_pandoc_version()
# we can safely continue
p = subprocess.Popen(cmd, stdin=subprocess.PIPE, stdout=subprocess.PIPE)
out, _ = p.communicate(cast_bytes(source, encoding))
out = TextIOWrapper(BytesIO(out), encoding, 'replace').read()
return out.rstrip('\n')
def get_pandoc_version():
"""Gets the Pandoc version if Pandoc is installed.
PandocMissing will be raised if pandoc is unavailable.
"""
try:
if not minimal_version_ok:
raise AttributeError()
else:
return pandoc.version
except AttributeError:
cmd = ["pandoc", "-v"]
try:
out = subprocess.check_output(cmd, universal_newlines=True)
except OSError as e:
raise PandocMissing(cmd, e)
pv_re = re.compile(r'(\d{0,3}\.\d{0,3}\.\d{0,3})')
pandoc.version = pv_re.search(out).group(0)
return pandoc.version
def check_pandoc_version():
"""Returns True if minimal pandoc version is met.
PandocMissing will be raised if pandoc is unavailable.
"""
global minimal_version_ok
if not minimal_version_ok:
minimal_version_ok = check_version( get_pandoc_version(), minimal_version )
if not minimal_version_ok:
warnings.warn( "You are using an old version of pandoc (%s)\n" % pandoc.version +
"Recommended version is %s.\nTry updating." % minimal_version +
"http://johnmacfarlane.net/pandoc/installing.html.\nContinuing with doubts...",
RuntimeWarning, stacklevel=2)
return minimal_version_ok