├── .gitignore ├── AUTHORS ├── HISTORY.rst ├── LICENSE ├── MANIFEST.in ├── README.rst ├── TODO.rst ├── fabfile.py ├── pandoc ├── __init__.py └── core.py └── setup.py /.gitignore: -------------------------------------------------------------------------------- 1 | # application builds 2 | build/* 3 | dist/* 4 | MANIFEST 5 | 6 | # python skin 7 | *.pyc 8 | *.pyo 9 | 10 | # osx noise 11 | .DS_Store 12 | profile 13 | 14 | # pycharm noise 15 | .idea 16 | .idea/* 17 | 18 | # vi noise 19 | *.swp 20 | docs/_build/* -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Pyandoc is written and maintained by Kenneth Reitz and 2 | various contributors: 3 | 4 | Development Lead 5 | ```````````````` 6 | 7 | - Kenneth Reitz 8 | 9 | 10 | Patches and Suggestions 11 | ``````````````````````` 12 | 13 | - A lucky someone! -------------------------------------------------------------------------------- /HISTORY.rst: -------------------------------------------------------------------------------- 1 | v0.0.2 (02-04-2016) 2 | +++++++++++++++++++ 3 | 4 | * Automatically find pandoc executable. 5 | * Updated export formats. 6 | 7 | 8 | v0.0.1 (01-02-2010) 9 | +++++++++++++++++++ 10 | 11 | * Initial release. 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Kenneth Reitz. 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in 11 | all copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 19 | THE SOFTWARE. -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | include HISTORY.rst README.rst LICENSE AUTHORS -------------------------------------------------------------------------------- /README.rst: -------------------------------------------------------------------------------- 1 | Pyandoc: a simple Pandoc wrapper for Python 2 | =========================================== 3 | 4 | Pyandoc is a simple Python wrapper for the excellent `pandoc `_ utility. It allows you to convert the format of text documents by interacting with a `Document` object's attributes. Each supported format is available as a property, and can either read from or written to. 5 | 6 | Requirements 7 | ++++++++++++ 8 | 9 | * Pandoc 10 | 11 | 12 | Usage 13 | +++++ 14 | 15 | Get setup. 16 | 17 | .. code-block:: python 18 | 19 | import pandoc 20 | 21 | 22 | Let's start with a Markdown document: 23 | 24 | .. code-block:: python 25 | 26 | doc = pandoc.Document() 27 | doc.markdown = ''' 28 | # I am an H1 Tag 29 | 30 | * bullet point 31 | * more points 32 | * point with [link](http://kennethreitz.com)! 33 | ''' 34 | 35 | Now let's convert that into a ReST document: :: 36 | 37 | >>> print doc.rst 38 | 39 | I am an H1 Tag 40 | ============== 41 | 42 | 43 | - bullet point 44 | - more points 45 | - point with `link `_! 46 | 47 | Formats available: 48 | - asciidoc 49 | - beamer 50 | - commonmark 51 | - context 52 | - docbook 53 | - doc- x 54 | - dokuwiki 55 | - dzslides 56 | - epub 57 | - epub3 58 | - fb2 59 | - haddock 60 | - html 61 | - html5 62 | - icml 63 | - json (pandoc's AST) 64 | - latex 65 | - man 66 | - markdown 67 | - markdown_github 68 | - markdown_mmd 69 | - markdown_phpextra 70 | - markdown_strict 71 | - mediawiki 72 | - native 73 | - odt 74 | - opendocument 75 | - opml 76 | - org 77 | - pdf 78 | - plain 79 | - revealjs 80 | - rst 81 | - rtf 82 | - s5, 83 | - slideous 84 | - slidy 85 | - texinfo 86 | - textile 87 | 88 | Enjoy. 89 | -------------------------------------------------------------------------------- /TODO.rst: -------------------------------------------------------------------------------- 1 | * Get inital work implimented -------------------------------------------------------------------------------- /fabfile.py: -------------------------------------------------------------------------------- 1 | import os 2 | from fabric.api import * 3 | 4 | 5 | def scrub(): 6 | """ Death to the bytecode! """ 7 | local('rm -fr dist build') 8 | local("find . -name \"*.pyc\" -exec rm '{}' ';'") -------------------------------------------------------------------------------- /pandoc/__init__.py: -------------------------------------------------------------------------------- 1 | from .core import * 2 | -------------------------------------------------------------------------------- /pandoc/core.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python 2 | # -*- encoding: utf-8 -*- 3 | """ 4 | 5 | """ 6 | import subprocess 7 | from os.path import exists 8 | from tempfile import NamedTemporaryFile 9 | import os 10 | 11 | # Import find executable engine 12 | try: 13 | from shutil import which 14 | except ImportError: 15 | from distutils.spawn import find_executable 16 | 17 | which = find_executable 18 | 19 | # Path to the executable 20 | PANDOC_PATH = which('pandoc') 21 | 22 | 23 | class Document(object): 24 | """A formatted document.""" 25 | 26 | # removed pdf and epub which cannot be handled by stdout 27 | OUTPUT_FORMATS = ( 28 | 'asciidoc', 'beamer', 'commonmark', 'context', 'docbook', 29 | 'docx', 'dokuwiki', 'dzslides', 'epub', 'epub3', 'fb2', 30 | 'haddock', 'html', 'html5', 'icml', 'json', 'latex', 'man', 31 | 'markdown', 'markdown_github', 'markdown_mmd', 32 | 'markdown_phpextra', 'markdown_strict', 'mediawiki', 'native', 33 | 'odt', 'opendocument', 'opml', 'org', 'pdf', 'plain', 34 | 'revealjs', 'rst', 'rtf', 's5', 'slideous', 'slidy', 'texinfo', 35 | 'textile' 36 | ) 37 | 38 | # TODO: Add odt, epub formats (requires file access, not stdout) 39 | 40 | def __init__(self): 41 | self._content = None 42 | self._format = None 43 | self._register_formats() 44 | self.arguments = [] 45 | 46 | if not exists(PANDOC_PATH): 47 | raise OSError("Path to pandoc executable does not exists") 48 | 49 | 50 | def bib(self, bibfile): 51 | if not exists(bibfile): 52 | raise IOError("Bib file not found: %s" % bibfile) 53 | self.add_argument("bibliography=%s" % bibfile) 54 | 55 | 56 | def csl(self, cslfile): 57 | if not exists(cslfile): 58 | raise IOError("CSL file not found: %s" % cslfile) 59 | self.add_argument("csl=%s" % cslfile) 60 | 61 | def abbr(self, abbrfile): 62 | if not exists(abbrfile): 63 | raise IOError("Abbreviations file not found: " + abbrfile) 64 | self.add_argument("citation-abbreviations=%s" % abbrfile) 65 | 66 | 67 | def add_argument(self, arg): 68 | self.arguments.append("--%s" % arg) 69 | return self.arguments 70 | 71 | 72 | @classmethod 73 | def _register_formats(cls): 74 | """Adds format properties.""" 75 | for fmt in cls.OUTPUT_FORMATS: 76 | clean_fmt = fmt.replace('+', '_') 77 | setattr(cls, clean_fmt, property( 78 | (lambda x, fmt=fmt: cls._output(x, fmt)), # fget 79 | (lambda x, y, fmt=fmt: cls._input(x, y, fmt)))) # fset 80 | 81 | 82 | def _input(self, value, format=None): 83 | # format = format.replace('_', '+') 84 | self._content = value 85 | self._format = format 86 | 87 | 88 | def _output(self, format): 89 | subprocess_arguments = [PANDOC_PATH, '--from=%s' % self._format, '--to=%s' % format] 90 | subprocess_arguments.extend(self.arguments) 91 | 92 | p = subprocess.Popen( 93 | subprocess_arguments, 94 | stdin=subprocess.PIPE, 95 | stdout=subprocess.PIPE 96 | ) 97 | return p.communicate(self._content)[0] 98 | 99 | 100 | def to_file(self, output_filename): 101 | '''Handles pdf and epub format. 102 | Inpute: output_filename should have the proper extension. 103 | Output: The name of the file created, or an IOError if failed''' 104 | temp_file = NamedTemporaryFile(mode="w", suffix=".md", delete=False) 105 | temp_file.write(self._content) 106 | temp_file.close() 107 | 108 | subprocess_arguments = [PANDOC_PATH, temp_file.name, '-o %s' % output_filename] 109 | subprocess_arguments.extend(self.arguments) 110 | cmd = " ".join(subprocess_arguments) 111 | 112 | fin = os.popen(cmd) 113 | msg = fin.read() 114 | fin.close() 115 | if msg: 116 | print("Pandoc message: {}",format(msg)) 117 | 118 | os.remove(temp_file.name) 119 | 120 | if exists(output_filename): 121 | return output_filename 122 | else: 123 | raise IOError("Failed creating file: %s" % output_filename) 124 | -------------------------------------------------------------------------------- /setup.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | import os 5 | import sys 6 | 7 | from setuptools import setup 8 | 9 | 10 | def publish(): 11 | """Publish to PyPi""" 12 | os.system("python setup.py sdist upload") 13 | 14 | if sys.argv[-1] == "publish": 15 | publish() 16 | sys.exit() 17 | 18 | required = [] 19 | 20 | # if sys.version_info < (2, 6): 21 | # required.append('simplejson') 22 | 23 | setup( 24 | name='pyandoc', 25 | version='0.2.0', 26 | description='Python wrapper for Pandoc - the universal document converter', 27 | long_description=open('README.rst').read() + '\n\n' + 28 | open('HISTORY.rst').read(), 29 | author='Kenneth Reitz', 30 | author_email='me@kennethreitz.com', 31 | url='http://github.com/kennethreitz/pyandoc', 32 | packages= [ 33 | 'pandoc', 34 | ], 35 | install_requires=required, 36 | license='MIT', 37 | classifiers=( 38 | 'Development Status :: 5 - Production/Stable', 39 | 'Intended Audience :: Developers', 40 | 'Natural Language :: English', 41 | 'License :: OSI Approved :: MIT License', 42 | 'Programming Language :: Python', 43 | 'Programming Language :: Python :: 2.6', 44 | 'Programming Language :: Python :: 2.7', 45 | 'Programming Language :: Python :: 3.0', 46 | 'Programming Language :: Python :: 3.1', 47 | 'Programming Language :: Python :: 3.2', 48 | 'Programming Language :: Python :: 3.3', 49 | 'Programming Language :: Python :: 3.4', 50 | 'Programming Language :: Python :: 3.5', 51 | ), 52 | # entry_points={ 53 | # 'console_scripts': [ 54 | # 'tabbed = tablib.cli:start', 55 | # ], 56 | # } 57 | ) 58 | --------------------------------------------------------------------------------