diff options
Diffstat (limited to 'wrappers/wrapper.py')
-rwxr-xr-x[-rw-r--r--] | wrappers/wrapper.py | 944 |
1 files changed, 30 insertions, 914 deletions
diff --git a/wrappers/wrapper.py b/wrappers/wrapper.py index 7ef032a..98e7f2b 100644..100755 --- a/wrappers/wrapper.py +++ b/wrappers/wrapper.py @@ -1,921 +1,37 @@ -from __future__ import unicode_literals +#!/usr/bin/env python -from ctypes import * +# Example for using the shared library from python +# Will work with either python 2 or python 3 +# Requires cmark library to be installed + +from ctypes import CDLL, c_char_p, c_long import sys import platform -c_object_p = POINTER(c_void_p) - sysname = platform.system() -if sysname == 'Windows': - libc = CDLL('msvcrt.dll') -else: - libc = CDLL('libc.so.6') - -if sys.version_info[0] > 2: - def bytes_and_length(text): - if type(text) == str: - text = text.encode("utf8") - return text, len(text) +if sysname == 'Darwin': + libname = "libcmark.dylib" +elif sysname == 'Windows': + libname = "cmark.dll" else: - def bytes_and_length(text): - if type(text) == unicode: - text = text.encode("utf8") - return text, len(text) - -def unicode_from_char_p(res, fn, args): - ret = res.decode("utf8") - return ret - -class owned_char_p(c_void_p): - def __del__(self): - conf.lib.cmark_default_mem_free(self.value) - -def unicode_from_owned_char_p(res, fn, args): - ret = cast(res, c_char_p).value.decode("utf8") - return ret - -def boolean_from_result(res, fn, args): - return bool(res) - -def delim_from_int(res, fn, args): - if res == 0: - return '' - elif res == 1: - return '.' - elif res == 2: - return ')' - -class BaseEnumeration(object): - def __init__(self, value): - if value >= len(self.__class__._kinds): - self.__class__._kinds += [None] * (value - len(self.__class__._kinds) + 1) - if self.__class__._kinds[value] is not None: - raise ValueError('{0} value {1} already loaded'.format( - str(self.__class__), value)) - self.value = value - self.__class__._kinds[value] = self - self.__class__._name_map = None - - def from_param(self): - return self.value - - @classmethod - def from_id(cls, id, fn, args): - if id >= len(cls._kinds) or cls._kinds[id] is None: - raise ValueError('Unknown template argument kind %d' % id) - return cls._kinds[id] - - @property - def name(self): - """Get the enumeration name of this cursor kind.""" - if self._name_map is None: - self._name_map = {} - for key, value in self.__class__.__dict__.items(): - if isinstance(value, self.__class__): - self._name_map[value] = key - return str(self._name_map[self]) - - def __repr__(self): - return '%s.%s' % (self.__class__.__name__, self.name,) - -class Parser(object): - OPT_DEFAULT = 0 - OPT_SOURCEPOS = 1 << 1 - OPT_HARDBREAKS = 1 << 2 - OPT_SAFE = 1 << 3 - OPT_NOBREAKS = 1 << 4 - OPT_NORMALIZE = 1 << 8 - OPT_VALIDATE_UTF8 = 1 << 9 - OPT_SMART = 1 << 10 - - def __init__(self, options=0): - self._parser = conf.lib.cmark_parser_new(options) - - def __del__(self): - conf.lib.cmark_parser_free(self._parser) - - def feed(self, text): - conf.lib.cmark_parser_feed(self._parser, *bytes_and_length(text)) - - def finish(self): - return conf.lib.cmark_parser_finish(self._parser) - - def get_source_map(self): - return conf.lib.cmark_parser_get_first_source_extent(self._parser) - -class LibcmarkError(Exception): - def __init__(self, message): - self.m = message - - def __str__(self): - return self.m - -class NodeType(BaseEnumeration): - _kinds = [] - _name_map = None - -NodeType.NONE = NodeType(0) -NodeType.DOCUMENT = NodeType(1) -NodeType.BLOCK_QUOTE = NodeType(2) -NodeType.LIST = NodeType(3) -NodeType.ITEM = NodeType(4) -NodeType.CODE_BLOCK = NodeType(5) -NodeType.HTML_BLOCK = NodeType(6) -NodeType.CUSTOM_BLOCK = NodeType(7) -NodeType.PARAGRAPH = NodeType(8) -NodeType.HEADING = NodeType(9) -NodeType.THEMATIC_BREAK = NodeType(10) -NodeType.TEXT = NodeType(11) -NodeType.SOFTBREAK = NodeType(12) -NodeType.LINEBREAK = NodeType(13) -NodeType.CODE = NodeType(14) -NodeType.HTML_INLINE = NodeType(15) -NodeType.CUSTOM_INLINE = NodeType(16) -NodeType.EMPH = NodeType(17) -NodeType.STRONG = NodeType(18) -NodeType.LINK = NodeType(19) -NodeType.IMAGE = NodeType(20) - -class ListType(BaseEnumeration): - _kinds = [] - _name_map = None - -ListType.BULLET = ListType(1) -ListType.ORDERED = ListType(2) - -class Node(object): - __subclass_map = {} - - def __init__(self): - self._owned = False - raise NotImplementedError - - @staticmethod - def from_result(res, fn=None, args=None): - try: - res.contents - except ValueError: - return None - - cls = Node.get_subclass_map()[conf.lib.cmark_node_get_type(res)] - - ret = cls.__new__(cls) - ret._node = res - ret._owned = False - return ret - - @classmethod - def get_subclass_map(cls): - if cls.__subclass_map: - return cls.__subclass_map - - res = {c._node_type: c for c in cls.__subclasses__()} - - for c in cls.__subclasses__(): - res.update(c.get_subclass_map()) - - return res - - def unlink(self): - conf.lib.cmark_node_unlink(self._node) - self._owned = True - - def append_child(self, child): - res = conf.lib.cmark_node_append_child(self._node, child._node) - if not res: - raise LibcmarkError("Can't append child %s to node %s" % (str(child), str(self))) - child._owned = False - - def prepend_child(self, child): - res = conf.lib.cmark_node_prepend_child(self._node, child._node) - if not res: - raise LibcmarkError("Can't prepend child %s to node %s" % (str(child), str(self))) - child._owned = False - - def insert_before(self, sibling): - res = conf.lib.cmark_node_insert_before(self._node, sibling._node) - if not res: - raise LibcmarkError("Can't insert sibling %s before node %s" % (str(sibling), str(self))) - sibling._owned = False - - def insert_after(self, sibling): - res = conf.lib.cmark_node_insert_after(self._node, sibling._node) - if not res: - raise LibcmarkError("Can't insert sibling %s after node %s" % (str(sibling), str(self))) - sibling._owned = False - - def consolidate_text_nodes(self): - conf.lib.cmark_consolidate_text_nodes(self._node) - - def to_html(self, options=Parser.OPT_DEFAULT): - return conf.lib.cmark_render_html(self._node, options) - - def to_xml(self, options=Parser.OPT_DEFAULT): - return conf.lib.cmark_render_xml(self._node, options) - - def to_commonmark(self, options=Parser.OPT_DEFAULT, width=0): - return conf.lib.cmark_render_commonmark(self._node, options, width) - - def to_man(self, options=Parser.OPT_DEFAULT, width=0): - return conf.lib.cmark_render_man(self._node, options, width) - - def to_latex(self, options=Parser.OPT_DEFAULT, width=0): - return conf.lib.cmark_render_latex(self._node, options, width) - - @property - def first_child(self): - return conf.lib.cmark_node_first_child(self._node) - - @property - def last_child(self): - return conf.lib.cmark_node_last_child(self._node) - - @property - def next(self): - return conf.lib.cmark_node_next(self._node) - - @property - def previous(self): - return conf.lib.cmark_node_previous(self._node) - - def __eq__(self, other): - return self._node.contents.value == other._node.contents.value - - def __ne__(self, other): - return self._node.contents.value != other._node.contents.value - - def __del__(self): - if self._owned: - conf.lib.cmark_node_free(self._node) - - def __iter__(self): - cur = self.first_child - while (cur): - yield cur - cur = cur.next - -class Literal(Node): - _node_type = NodeType.NONE - - @property - def literal(self): - return conf.lib.cmark_node_get_literal(self._node) - - @literal.setter - def literal(self, value): - bytes_, _ = bytes_and_length(value) - if not conf.lib.cmark_node_set_literal(self._node, bytes_): - raise LibcmarkError("Invalid literal %s\n" % str(value)) - -class Document(Node): - _node_type = NodeType.DOCUMENT - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - -class BlockQuote(Node): - _node_type = NodeType.BLOCK_QUOTE - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - -class List(Node): - _node_type = NodeType.LIST - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - - @property - def type(self): - return conf.lib.cmark_node_get_list_type(self._node) - - @type.setter - def type(self, type_): - if not conf.lib.cmark_node_set_list_type(self._node, type_.value): - raise LibcmarkError("Invalid type %s" % str(type_)) - - @property - def delim(self): - return conf.lib.cmark_node_get_list_delim(self._node) - - @delim.setter - def delim(self, value): - if value == '.': - delim_type = 1 - elif value == ')': - delim_type = 2 - else: - raise LibcmarkError('Invalid delim type %s' % str(value)) - - conf.lib.cmark_node_set_list_delim(self._node, delim_type) - - @property - def start(self): - return conf.lib.cmark_node_get_list_start(self._node) - - @start.setter - def start(self, value): - if not conf.lib.cmark_node_set_list_start(self._node, value): - raise LibcmarkError("Invalid list start %s\n" % str(value)) - - @property - def tight(self): - return conf.lib.cmark_node_get_list_tight(self._node) - - @tight.setter - def tight(self, value): - if value is True: - tightness = 1 - elif value is False: - tightness = 0 - else: - raise LibcmarkError("Invalid list tightness %s\n" % str(value)) - if not conf.lib.cmark_node_set_list_tight(self._node, tightness): - raise LibcmarkError("Invalid list tightness %s\n" % str(value)) - -class Item(Node): - _node_type = NodeType.ITEM - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - -class CodeBlock(Literal): - _node_type = NodeType.CODE_BLOCK - - def __init__(self, literal='', fence_info=''): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - self.literal = literal - self.fence_info = fence_info - - @property - def fence_info(self): - return conf.lib.cmark_node_get_fence_info(self._node) - - @fence_info.setter - def fence_info(self, value): - bytes_, _ = bytes_and_length(value) - if not conf.lib.cmark_node_set_fence_info(self._node, bytes_): - raise LibcmarkError("Invalid fence info %s\n" % str(value)) - -class HtmlBlock(Literal): - _node_type = NodeType.HTML_BLOCK - - def __init__(self, literal=''): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - self.literal = literal - - -class CustomBlock(Node): - _node_type = NodeType.CUSTOM_BLOCK - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - - -class Paragraph(Node): - _node_type = NodeType.PARAGRAPH - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - -class Heading(Node): - _node_type = NodeType.HEADING - - def __init__(self, level=1): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self.level = level - self._owned = True - - @property - def level(self): - return int(conf.lib.cmark_node_get_heading_level(self._node)) - - @level.setter - def level(self, value): - res = conf.lib.cmark_node_set_heading_level(self._node, value) - if (res == 0): - raise LibcmarkError("Invalid heading level %s" % str(value)) - -class ThematicBreak(Node): - _node_type = NodeType.THEMATIC_BREAK - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - - -class Text(Literal): - _node_type = NodeType.TEXT - - def __init__(self, literal=''): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - self.literal = literal - - -class SoftBreak(Node): - _node_type = NodeType.SOFTBREAK - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - - -class LineBreak(Node): - _node_type = NodeType.LINEBREAK - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - - -class Code(Literal): - _node_type = NodeType.CODE - - def __init__(self, literal=''): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - self.literal = literal - - -class HtmlInline(Literal): - _node_type = NodeType.HTML_INLINE - - def __init__(self, literal=''): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - self.literal = literal - - -class CustomInline(Node): - _node_type = NodeType.CUSTOM_INLINE - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - -class Emph(Node): - _node_type = NodeType.EMPH - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - -class Strong(Node): - _node_type = NodeType.STRONG - - def __init__(self): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - - -class Link(Node): - _node_type = NodeType.LINK - - def __init__(self, url='', title=''): - self._node = conf.lib.cmark_node_new(self.__class__._node_type.value) - self._owned = True - self.url = url - self.title = title - - @property - def url(self): - return conf.lib.cmark_node_get_url(self._node) - - @url.setter - def url(self, value): - bytes_, _ = bytes_and_length(value) - if not conf.lib.cmark_node_set_url(self._node, bytes_): - raise LibcmarkError("Invalid url %s\n" % str(value)) - - @property - def title(self): - return conf.lib.cmark_node_get_title(self._node) - - @title.setter - def title(self, value): - bytes_, _ = bytes_and_length(value) - if not conf.lib.cmark_node_set_title(self._node, bytes_): - raise LibcmarkError("Invalid title %s\n" % str(value)) - -class Image(Link): - _node_type = NodeType.IMAGE - -class ExtentType(BaseEnumeration): - _kinds = [] - _name_map = None - -ExtentType.NONE = ExtentType(0) -ExtentType.OPENER = ExtentType(1) -ExtentType.CLOSER = ExtentType(2) -ExtentType.BLANK = ExtentType(3) -ExtentType.CONTENT = ExtentType(4) -ExtentType.PUNCTUATION = ExtentType(5) -ExtentType.LINK_DESTINATION = ExtentType(6) -ExtentType.LINK_TITLE = ExtentType(7) -ExtentType.LINK_LABEL = ExtentType(8) -ExtentType.REFERENCE_DESTINATION = ExtentType(9) -ExtentType.REFERENCE_LABEL = ExtentType(10) -ExtentType.REFERENCE_TITLE = ExtentType(11) - -class Extent(object): - @staticmethod - def from_result(res, fn=None, args=None): - ret = Extent() - ret._extent = res - return ret - - @property - def start(self): - return conf.lib.cmark_source_extent_get_start(self._extent) - - @property - def stop(self): - return conf.lib.cmark_source_extent_get_stop(self._extent) - - @property - def type(self): - return conf.lib.cmark_source_extent_get_type(self._extent) - - @property - def node(self): - return conf.lib.cmark_source_extent_get_node(self._extent) - -class SourceMap(object): - @staticmethod - def from_result(res, fn, args): - ret = SourceMap() - ret._root = res - return ret - - def __iter__(self): - cur = self._root - while (cur): - yield Extent.from_result(cur) - cur = conf.lib.cmark_source_extent_get_next(cur) - -def markdown_to_html(text, options=Parser.OPT_DEFAULT): - bytes_, length = bytes_and_length(text) - return conf.lib.cmark_markdown_to_html(bytes_, length, options) - -def parse_document(text, options=Parser.OPT_DEFAULT): - bytes_, length = bytes_and_length(text) - return conf.lib.cmark_parse_document(bytes_, length, options) - -functionList = [ - ("cmark_default_mem_free", - [c_void_p]), - ("cmark_markdown_to_html", - [c_char_p, c_long, c_int], - owned_char_p, - unicode_from_owned_char_p), - ("cmark_parse_document", - [c_char_p, c_long, c_int], - c_object_p, - Node.from_result), - ("cmark_parser_new", - [c_int], - c_object_p), - ("cmark_parser_free", - [c_object_p]), - ("cmark_parser_feed", - [c_object_p, c_char_p, c_long]), - ("cmark_parser_finish", - [c_object_p], - c_object_p, - Node.from_result), - ("cmark_parser_get_first_source_extent", - [c_object_p], - c_object_p, - SourceMap.from_result), - ("cmark_source_extent_get_next", - [c_object_p], - c_object_p), - ("cmark_source_extent_get_start", - [c_object_p], - c_ulonglong), - ("cmark_source_extent_get_stop", - [c_object_p], - c_ulonglong), - ("cmark_source_extent_get_type", - [c_object_p], - c_int, - ExtentType.from_id), - ("cmark_source_extent_get_node", - [c_object_p], - c_object_p, - Node.from_result), - ("cmark_render_html", - [c_object_p, c_int], - owned_char_p, - unicode_from_owned_char_p), - ("cmark_render_xml", - [c_object_p, c_int], - owned_char_p, - unicode_from_owned_char_p), - ("cmark_render_commonmark", - [c_object_p, c_int, c_int], - owned_char_p, - unicode_from_owned_char_p), - ("cmark_render_man", - [c_object_p, c_int, c_int], - owned_char_p, - unicode_from_owned_char_p), - ("cmark_render_latex", - [c_object_p, c_int, c_int], - owned_char_p, - unicode_from_owned_char_p), - ("cmark_node_new", - [c_int], - c_object_p), - ("cmark_node_free", - [c_object_p]), - ("cmark_node_get_type", - [c_object_p], - c_int, - NodeType.from_id), - ("cmark_node_first_child", - [c_object_p], - c_object_p, - Node.from_result), - ("cmark_node_last_child", - [c_object_p], - c_object_p, - Node.from_result), - ("cmark_node_next", - [c_object_p], - c_object_p, - Node.from_result), - ("cmark_node_previous", - [c_object_p], - c_object_p, - Node.from_result), - ("cmark_node_unlink", - [c_object_p]), - ("cmark_node_append_child", - [c_object_p, c_object_p], - c_int, - boolean_from_result), - ("cmark_node_prepend_child", - [c_object_p, c_object_p], - c_int, - boolean_from_result), - ("cmark_node_insert_before", - [c_object_p, c_object_p], - c_int, - boolean_from_result), - ("cmark_node_insert_after", - [c_object_p, c_object_p], - c_int, - boolean_from_result), - ("cmark_consolidate_text_nodes", - [c_object_p]), - ("cmark_node_get_literal", - [c_object_p], - c_char_p, - unicode_from_char_p), - ("cmark_node_set_literal", - [c_object_p, c_char_p], - c_int, - boolean_from_result), - ("cmark_node_get_heading_level", - [c_object_p], - c_int), - ("cmark_node_set_heading_level", - [c_object_p, c_int], - c_int, - boolean_from_result), - ("cmark_node_get_list_type", - [c_object_p], - c_int, - ListType.from_id), - ("cmark_node_set_list_type", - [c_object_p], - c_int, - boolean_from_result), - ("cmark_node_get_list_delim", - [c_object_p], - c_int, - delim_from_int), - ("cmark_node_set_list_delim", - [c_object_p, c_int], - c_int), - ("cmark_node_get_list_start", - [c_object_p], - c_int), - ("cmark_node_set_list_start", - [c_object_p, c_int], - c_int, - boolean_from_result), - ("cmark_node_get_list_tight", - [c_object_p], - c_int, - boolean_from_result), - ("cmark_node_set_list_tight", - [c_object_p, c_int], - c_int, - boolean_from_result), - ("cmark_node_get_fence_info", - [c_object_p], - c_char_p, - unicode_from_char_p), - ("cmark_node_set_fence_info", - [c_object_p, c_char_p], - c_int, - boolean_from_result), - ("cmark_node_get_url", - [c_object_p], - c_char_p, - unicode_from_char_p), - ("cmark_node_set_url", - [c_object_p, c_char_p], - c_int, - boolean_from_result), - ("cmark_node_get_title", - [c_object_p], - c_char_p, - unicode_from_char_p), - ("cmark_node_set_title", - [c_object_p, c_char_p], - c_int, - boolean_from_result), -] - -# Taken from clang.cindex -def register_function(lib, item, ignore_errors): - # A function may not exist, if these bindings are used with an older or - # incompatible version of libcmark.so. - try: - func = getattr(lib, item[0]) - except AttributeError as e: - msg = str(e) + ". Please ensure that your python bindings are "\ - "compatible with your libcmark version." - if ignore_errors: - return - raise LibcmarkError(msg) - - if len(item) >= 2: - func.argtypes = item[1] - - if len(item) >= 3: - func.restype = item[2] - - if len(item) == 4: - func.errcheck = item[3] - -def register_functions(lib, ignore_errors): - """Register function prototypes with a libccmark library instance. - - This must be called as part of library instantiation so Python knows how - to call out to the shared library. - """ - - def register(item): - return register_function(lib, item, ignore_errors) - - for f in functionList: - register(f) - -class Config: - library_path = None - library_file = None - compatibility_check = True - loaded = False - lib_ = None - - @staticmethod - def set_library_path(path): - """Set the path in which to search for libcmark""" - if Config.loaded: - raise Exception("library path must be set before before using " \ - "any other functionalities in libcmark.") - - Config.library_path = path - - @staticmethod - def set_library_file(filename): - """Set the exact location of libcmark""" - if Config.loaded: - raise Exception("library file must be set before before using " \ - "any other functionalities in libcmark.") - - Config.library_file = filename - - @staticmethod - def set_compatibility_check(check_status): - """ Perform compatibility check when loading libcmark - - The python bindings are only tested and evaluated with the version of - libcmark they are provided with. To ensure correct behavior a (limited) - compatibility check is performed when loading the bindings. This check - will throw an exception, as soon as it fails. - - In case these bindings are used with an older version of libcmark, parts - that have been stable between releases may still work. Users of the - python bindings can disable the compatibility check. This will cause - the python bindings to load, even though they are written for a newer - version of libcmark. Failures now arise if unsupported or incompatible - features are accessed. The user is required to test themselves if the - features they are using are available and compatible between different - libcmark versions. - """ - if Config.loaded: - raise Exception("compatibility_check must be set before before " \ - "using any other functionalities in libcmark.") - - Config.compatibility_check = check_status - - @property - def lib(self): - if self.lib_: - return self.lib_ - lib = self.get_cmark_library() - register_functions(lib, not Config.compatibility_check) - Config.loaded = True - self.lib_ = lib - return lib - - def get_filename(self): - if Config.library_file: - return Config.library_file - - import platform - name = platform.system() - - if name == 'Darwin': - file = 'libcmark.dylib' - elif name == 'Windows': - file = 'cmark.dll' - else: - file = 'libcmark.so' - - if Config.library_path: - file = Config.library_path + '/' + file - - return file - - def get_cmark_library(self): - try: - library = cdll.LoadLibrary(self.get_filename()) - except OSError as e: - msg = str(e) + "(%s). To provide a path to libcmark use " \ - "Config.set_library_path() or " \ - "Config.set_library_file()." % self.get_filename() - raise LibcmarkError(msg) - - return library - - def function_exists(self, name): - try: - getattr(self.lib, name) - except AttributeError: - return False - - return True - -conf = Config() - -__alla__ = [ - 'Parser', - 'LibcmarkError', - 'NodeType', - 'ListType', - 'Node', - 'Document', - 'BlockQuote', - 'List', - 'Item', - 'CodeBlock', - 'HtmlBlock', - 'CustomBlock', - 'Paragraph', - 'Heading', - 'ThematicBreak', - 'Text', - 'SoftBreak', - 'LineBreak', - 'Code', - 'HtmlInline', - 'CustomInline', - 'Emph', - 'Strong', - 'Link', - 'Image', - 'ExtentType', - 'Extent', - 'SourceMap', - 'markdown_to_html', - 'parse_document', - 'Config', - 'conf' -] + libname = "libcmark.so" +cmark = CDLL(libname) + +markdown = cmark.cmark_markdown_to_html +markdown.restype = c_char_p +markdown.argtypes = [c_char_p, c_long, c_long] + +opts = 0 # defaults + +def md2html(text): + if sys.version_info >= (3,0): + textbytes = text.encode('utf-8') + textlen = len(textbytes) + return markdown(textbytes, textlen, opts).decode('utf-8') + else: + textbytes = text + textlen = len(text) + return markdown(textbytes, textlen, opts) + +sys.stdout.write(md2html(sys.stdin.read())) |