Skip to main content

A Python interface for Discount, the C Markdown parser

Project description

This Python package is a ctypes binding of David Loren’s Discount, a C implementation of John Gruber’s Markdown.


Markdown is a text-to-HTML conversion tool for web writers. Markdown allows you to write using an easy-to-read, easy-to-write plain text format, then convert it to structurally valid XHTML (or HTML).

The discount Python module contains two things of interest:

  • libmarkdown, a submodule that provides access to the public C functions defined by Discount.
  • Markdown, a helper class built on top of libmarkdown, providing a more familiar Pythonic interface

Using the Markdown class

The Markdown class wraps the c functions exposed in the libmarkdown submodule and handles the ctypes leg work for you. If you want to use the Discount functions directly, skip to the next section about libmarkdown.

Let’s take a look at a simple example:

import sys
import discount

mkd = discount.Markdown(sys.stdin)

Markdown takes one required argument, input_file_or_string, the markdown formatted data. If this argument is a file-like object, the file must be a real OS file descriptor, i.e. sys.stdin yes, a StringIO object, no. The argument is otherwise assumed to be a string-like object. The same is true for Markdown methods that write HTML output to files.

Otherwise, the data is assumed to be string-like. Markdown also has methods for getting the output as a string, instead of writing to a file-like object. Let’s look at a modified version of the first example, this time using strings:

import discout

mkd = discount.Markdown('`test`')
print mkd.get_html_content()

The Markdown class constructor also takes optional boolean keyword arguments.

Generate table-of-contents headers (each generated <h1>, <h2>, etc will include a id=”name” argument.) Use get_html_toc() or write_html_toc() to generate the table-of-contents itself.
Disable relaxed emphasis and superscripts.
Greedily expand links; if a url is encountered, convert it to a hyperlink even if it isn’t surrounded with <>s.
Be paranoid about how [][] is expanded into a link - if the url isn’t a local reference, http://, https://, ftp://, or news://, it will not be converted into a hyperlink.
Do not process the pandoc document header, but treat it like regular text.
Do not allow <a or expand [][] into a link.
Do not allow <img or expand ![][] into a image.
Don’t process PHP Markdown Extra tables.
Disable SmartyPants processing.
Disable all embedded HTML by replacing all <’s with &lt;.
Do not process pseudo-protocols.

Pandoc header elements can be retrieved with the methods get_pandoc_title(), get_pandoc_author() and get_pandoc_date().

The converted HTML document parts can be retrieved as a string with the get_html_css(), get_html_toc() and get_html_content() methods, or written to a file with the write_html_css(fp), write_html_toc(fp) and write_html_content(fp) methods, where fp is the output file descriptor.

Under some conditions, the functions in libmarkdown may return integer error codes. These errors are raised as a MarkdownError exceptions when using the Markdown class.

Using libmarkdown

If you are familiar with using the C library and would rather use Discount’s functionality directly, libmarkdown is what you are looking for; its simply a thin wrapper around the original C implementation. libmarkdown exposes the public functions and flags documented on the Discount homepage.

In Python you’ll need to do some extra work preparing Python objects you want to pass to libmarkdown’s functions.

Most of these functions accept FILE* and char** types as their arguments, which require some additional ctypes boilerplate.

To get a FILE* from a Python file descriptor for use with libmarkdown, use the following pattern:

i = ctypes.pythonapi.PyFile_AsFile(sys.stdin)
o = ctypes.pythonapi.PyFile_AsFile(sys.stdout)
doc = libmarkdown.mkd_in(i)
libmarkdown.markdown(doc, o)

For libmarkdown functions to which you pass a char**, use the following pattern:

cp = ctypes.c_char_p('')
ln = libmarkdown.mkd_document(doc, ctypes.byref(cp))
html_text = cp.value[:ln]

It is important to initialize c_char_p with an empty string.

Running the test suite

Tests are available with the source distibution of discount in the file. The C shared object should be compiled first:

python build_ext

Then you can run the tests:


Source code and reporting bugs

You can obtain the source code and report bugs on GitHub project page.


See the LICENSE file in the source distribution for details.


discount is maintained by Tamas Kemenczy, and is funded by Trapeze. See the AUTHORS file for details.

Project details

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Files for discount, version 0.1.0BETA
Filename, size File type Python version Upload date Hashes
Filename, size discount-0.1.0BETA.tar.gz (11.9 kB) File type Source Python version None Upload date Hashes View

Supported by

AWS AWS Cloud computing Datadog Datadog Monitoring DigiCert DigiCert EV certificate Facebook / Instagram Facebook / Instagram PSF Sponsor Fastly Fastly CDN Google Google Object Storage and Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Salesforce Salesforce PSF Sponsor Sentry Sentry Error logging StatusPage StatusPage Status page