Commit 2d2c1536 authored by Kunshan Wang's avatar Kunshan Wang

Support both Python 2 and 3

parent d93b1068
# Python Binding of the Mu Client API
The Python binding allows the client to be written in Python. This binding is
based on the `ctypes` module. Currently only the Python 2 binding is available.
based on the `ctypes` module and is tested on Python 2, Python 3, PyPy and
PyPy3.
It depends on the C binding. You need to build the C binding in the
`../cbinding` directory before using this Python binding.
# How to use
See the docstring in `libmupython2.py`
See the docstring in `libmu.py`
<!--
vim: tw=80 spell
......
from __future__ import division, absolute_import, print_function, unicode_literals
def _assert_instance(obj, *tys):
if not any(isinstance(obj, ty) for ty in tys):
raise AssertionError("{} is not an instance of {}".format(obj,
" or ".join(map(str,tys))))
from __future__ import division, absolute_import, print_function, unicode_literals
from _libmuprivcommon import _assert_instance
def _is_str_like(v):
return isinstance(v, str) or isinstance(v, unicode)
def _encode_ascii(v):
_assert_instance(v, str, unicode)
if isinstance(v, unicode):
return v.encode("ascii")
else:
return v
def _decode_ascii(v):
_assert_instance(v, str, unicode)
if isinstance(v, str):
return v.decode("ascii")
else:
return v
def _assert_int_like(v):
_assert_instance(v, int, long)
from _libmuprivcommon import _assert_instance
def _is_str_like(v):
return isinstance(v, str) or isinstance(v, bytes)
def _encode_ascii(v):
_assert_instance(v, bytes, str)
if isinstance(v, str):
return v.encode("ascii")
else:
return v
def _decode_ascii(v):
_assert_instance(v, bytes, str)
if isinstance(v, bytes):
return v.decode("ascii")
else:
return v
def _assert_int_like(v):
_assert_instance(v, int)
......@@ -3,7 +3,7 @@ from __future__ import division, absolute_import, print_function, unicode_litera
import sys
import ctypes, ctypes.util
from libmupython2 import *
from libmu import *
def slurp(filename):
with open(filename) as t:
......
"""
libmupython2: Python2 binding for the Mu-client API.
libmu: Python binding for the Mu-client API.
This module works for both Python 2 and Python 3.
For PyPy users: This module is not RPython!
......@@ -147,6 +149,13 @@ It is recommended to read the docstrings in the following types: ``MuVM``,
from __future__ import division, absolute_import, print_function, unicode_literals
import sys
if sys.version_info[0] == 2:
import _libmuprivpython2 as _priv
else:
import _libmuprivpython3 as _priv
import ctypes, ctypes.util
_libc = ctypes.CDLL(ctypes.util.find_library("c"))
......@@ -165,10 +174,7 @@ def _assert_range(v, lb, ub):
if not (lb <= v <= ub):
raise AssertionError("{} is not between {} and {}".format(v, lb, ub))
def _assert_instance(obj, *tys):
if not any(isinstance(obj, ty) for ty in tys):
raise AssertionError("{} is not an instance of {}".format(obj,
" or ".join(tys)))
from _libmuprivcommon import _assert_instance
#### Low-level C types counterpart
......@@ -664,8 +670,8 @@ class MuCtx(_StructOfMethodsWrapper):
Arguments:
bundle_str: a str or unicode as the text-based bundle.
"""
_assert_instance(bundle_str, str, unicode)
return self.load_bundle_(bundle_str, len(bundle_str))
ascii_bundle = _priv._encode_ascii(bundle_str)
return self.load_bundle_(ascii_bundle, len(ascii_bundle))
def load_hail(self, hail_str):
"""Load a HAIL script.
......@@ -673,8 +679,8 @@ class MuCtx(_StructOfMethodsWrapper):
Arguments:
bundle_str: a str or unicode as the text-based HAIL script.
"""
_assert_instance(hail_str, str, unicode)
return self.load_hail_(hail_str, len(hail_str))
ascii_bundle = _priv._encode_ascii(hail_str)
return self.load_hail_(ascii_bundle, len(ascii_bundle))
def handle_from_int(self, value, length):
"""Convert a Python int to a Mu handle.
......@@ -688,7 +694,7 @@ class MuCtx(_StructOfMethodsWrapper):
Returns:
a MuIntValue
"""
_assert_instance(value, int, long)
_priv._assert_int_like(value)
_assert_range(length, 0, 64)
if _MIN_SINT64 <= value <= _MAX_SINT64:
return self.handle_from_sint64_(value, length)
......@@ -837,13 +843,15 @@ def _to_low_level_type(ty):
ty)
def _to_low_level_arg(arg):
return (arg._to_low_level_arg() if isinstance(arg, _LowLevelTypeWrapper)
else arg)
return (arg._to_low_level_arg() if isinstance(arg, _LowLevelTypeWrapper) else
_priv._encode_ascii(arg) if _priv._is_str_like(arg) else
arg)
def _from_low_level_retval(restype, low_level_rv, self):
return (restype._from_low_level_retval(low_level_rv, self)
if isinstance(restype, type) and issubclass(restype, _LowLevelTypeWrapper)
else low_level_rv)
if isinstance(restype, type) and issubclass(restype, _LowLevelTypeWrapper) else
_priv._decode_ascii(low_level_rv) if _priv._is_str_like(low_level_rv) else
low_level_rv)
def _make_high_level_method(name, expected_nargs, restype, argtypes):
def wrapper(self, *args):
......@@ -1104,7 +1112,7 @@ class MuRefImpl2StartDLL(object):
dll is a CDLL object of the "libmurefimpl2start.so" library, or a
pathname to it. In the latter case, a CDLL will be created.
"""
if isinstance(dll, str) or isinstance(dll, unicode):
if _priv._is_str_like(dll):
dll = ctypes.CDLL(dll)
dll.mu_refimpl2_new.restype = CPtrMuVM
......
#!/usr/bin/env python2
from __future__ import division, absolute_import, print_function, unicode_literals
import unittest
from libmupython2 import *
from libmu import *
dll = MuRefImpl2StartDLL(u"../cbinding/libmurefimpl2start.so")
mu = dll.mu_refimpl2_new()
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment