##// END OF EJS Templates
Arg, forgot the most important:...
Arg, forgot the most important: Put the pandoc version test under the pandoc_available test. This avoids raising an exception when the module is imported: the exception is only raised on pandoc(...) function calls. It also prints warnings if pandoc is not found at import time and if the version does not meet the expected one.

File last commit:

r14761:0d6b11ea
r14761:0d6b11ea
Show More
pandoc.py
140 lines | 4.8 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 .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):
"""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.
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, e:
if warn:
warnings.warn(
"Pandoc cannot be found (call %s failed).\n" % " ".join(cmd) +
"Please check that pandoc is installed:\n" +
"http://johnmacfarlane.net/pandoc/installing.html"
)
if failmode == "return":
return False, e
else:
raise PandocMissing(cmd, e)
#-----------------------------------------------------------------------------
# Classes and functions
#-----------------------------------------------------------------------------
minimal_version = "1.12.1"
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 an error 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")
# 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."""
try:
return pandoc.version
except AttributeError:
out = pandoc("None", "None", "None", ["-v"])
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"""
return get_pandoc_version() >= minimal_version
if pandoc_available(warn=True)[0]:
if(not check_pandoc_version()):
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)