##// END OF EJS Templates
Fix exception handler syntax for Python 3 compatibility....
Fix exception handler syntax for Python 3 compatibility. Improve error messages.

File last commit:

r14762:e8aa3026
r14762:e8aa3026
Show More
pandoc.py
142 lines | 5.0 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, 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"
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", alt=cmd)
# 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)