Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Port to Py2/3. Test passes all but 2 in Py3 and all but 1 in Py2. #7

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
66 changes: 58 additions & 8 deletions pyfribidi.c
Original file line number Diff line number Diff line change
Expand Up @@ -21,17 +21,26 @@
#include <Python.h>
#include <fribidi.h>

#if PY_MAJOR_VERSION >= 3
#define PYFRIBIDI_UNICODE_OBJECT PyObject
#else
#define PYFRIBIDI_UNICODE_OBJECT PyUnicodeObject
#endif

static PyObject *
unicode_log2vis (PyUnicodeObject* string,
unicode_log2vis (PYFRIBIDI_UNICODE_OBJECT * string,
FriBidiParType base_direction, int clean, int reordernsm)
{
int i;
#if PY_MAJOR_VERSION >= 3
Py_ssize_t length = PyUnicode_GetLength(string);
#else
int length = string->length;
#endif
FriBidiChar *logical = NULL; /* input fribidi unicode buffer */
FriBidiChar *visual = NULL; /* output fribidi unicode buffer */
FriBidiStrIndex new_len = 0; /* length of the UTF-8 buffer */
PyUnicodeObject *result = NULL;
// FriBidiStrIndex new_len = 0; /* length of the UTF-8 buffer */
PYFRIBIDI_UNICODE_OBJECT *result = NULL;

/* Allocate fribidi unicode buffers
TODO - Don't copy strings if sizeof(FriBidiChar) == sizeof(Py_UNICODE)
Expand All @@ -49,9 +58,14 @@ unicode_log2vis (PyUnicodeObject* string,
goto cleanup;
}

#if PY_MAJOR_VERSION >= 3
int number_of_copied_wchar = PyUnicode_AsWideChar(string, logical, length);
//logical[number_of_copied_wchar] = (wchar_t) NULL;
#else
for (i=0; i<length; ++i) {
logical[i] = string->str[i];
}
#endif

/* Convert to unicode and order visually */
fribidi_set_reorder_nsm(reordernsm);
Expand All @@ -69,14 +83,21 @@ unicode_log2vis (PyUnicodeObject* string,
length = fribidi_remove_bidi_marks (visual, length, NULL, NULL, NULL);
}

result = (PyUnicodeObject*) PyUnicode_FromUnicode(NULL, length);
#if PY_MAJOR_VERSION >= 3
result = PyUnicode_FromWideChar(visual, length);

#else
result = (PYFRIBIDI_UNICODE_OBJECT *) PyUnicode_FromUnicode(NULL, length);
#endif
if (result == NULL) {
goto cleanup;
}

#if PY_MAJOR_VERSION >= 3
#else
for (i=0; i<length; ++i) {
result->str[i] = visual[i];
}
#endif

cleanup:
/* Delete unicode buffers */
Expand All @@ -89,7 +110,7 @@ unicode_log2vis (PyUnicodeObject* string,
static PyObject *
_pyfribidi_log2vis (PyObject * self, PyObject * args, PyObject * kw)
{
PyUnicodeObject *logical = NULL; /* input unicode or string object */
PYFRIBIDI_UNICODE_OBJECT *logical = NULL; /* input unicode or string object */
FriBidiParType base = FRIBIDI_TYPE_RTL; /* optional direction */
int clean = 0; /* optional flag to clean the string */
int reordernsm = 1; /* optional flag to allow reordering of non spacing marks*/
Expand All @@ -101,7 +122,6 @@ _pyfribidi_log2vis (PyObject * self, PyObject * args, PyObject * kw)
&logical, &base, &clean, &reordernsm)) {
return NULL;
}

/* Validate base */

if (!(base == FRIBIDI_TYPE_RTL
Expand All @@ -112,7 +132,9 @@ _pyfribidi_log2vis (PyObject * self, PyObject * args, PyObject * kw)
base);
}

return unicode_log2vis (logical, base, clean, reordernsm);
PyObject * return_pyobject = unicode_log2vis (logical, base, clean, reordernsm);

return return_pyobject;
}


Expand All @@ -121,12 +143,40 @@ static PyMethodDef PyfribidiMethods[] = {
{NULL, NULL, 0, NULL}
};

#if PY_MAJOR_VERSION >= 3
#define INITERROR return NULL

static struct PyModuleDef pyfribidi_moduledef = {
PyModuleDef_HEAD_INIT, /* m_base */
"pyfribidi", /* m_name */
NULL, /* m_doc */
-1, /* m_size == -1 means cannot be reinitialized */
PyfribidiMethods, //
NULL, // myextension_traverse,
NULL, // myextension_clear,
NULL
};

PyMODINIT_FUNC
PyInit__pyfribidi (void)
#else
#define INITERROR return

void
init_pyfribidi (void)
#endif
{
#if PY_MAJOR_VERSION >= 3
PyObject *module = PyModule_Create (&pyfribidi_moduledef); // "_pyfribidi", PyfribidiMethods);
#else
PyObject *module = Py_InitModule ("_pyfribidi", PyfribidiMethods);
#endif
if (module == NULL) INITERROR;

PyModule_AddIntConstant (module, "RTL", (long) FRIBIDI_TYPE_RTL);
PyModule_AddIntConstant (module, "LTR", (long) FRIBIDI_TYPE_LTR);
PyModule_AddIntConstant (module, "ON", (long) FRIBIDI_TYPE_ON);
#if PY_MAJOR_VERSION >= 3
return module;
#endif
}
5 changes: 3 additions & 2 deletions pyfribidi.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
logical order, but the conversion may be wrong in certain cases.
"""

from builtins import str
__version__ = "0.11.0"
from _pyfribidi import LTR, ON, RTL, log2vis as _log2vis

Expand All @@ -25,8 +26,8 @@ def log2vis(logical, base_direction=RTL, encoding="utf-8", clean=False, reordern
- encoding: optional string encoding (ignored for unicode input)
"""

if not isinstance(logical, unicode):
logical = unicode(logical, encoding)
if not isinstance(logical, str):
logical = str(logical, encoding)
else:
encoding = None
res = _log2vis(logical, base_direction=base_direction, clean=clean, reordernsm=reordernsm)
Expand Down
2 changes: 2 additions & 0 deletions requirements-27.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
future==0.16.0
six==1.10.0
2 changes: 2 additions & 0 deletions requirements-36.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
future==0.16.0
six==1.10.0
5 changes: 3 additions & 2 deletions setup.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
#!/usr/bin/env python

from past.builtins import execfile
import os
from distutils.core import setup
from distutils.extension import Extension
from distutils.command import build_ext
from my_build_ext import build_ext as _link_build_ext
from distutils.util import strtobool

import os
from my_build_ext import build_ext as _link_build_ext

EMBED = strtobool(os.environ.get("EMBED", "1"))

Expand Down
16 changes: 11 additions & 5 deletions test_pyfribidi.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import sys
import unittest

import pyfribidi
from pyfribidi import RTL, LTR, ON

Expand All @@ -21,7 +22,7 @@ class InputTests(unittest.TestCase):
def testRequireInputString(self):
""" input: require input string or unicode """
self.assertRaises(TypeError, pyfribidi.log2vis)

def testInvalidInputString(self):
""" input: raise TypeError for non string or unicode input """
self.assertRaises(TypeError, pyfribidi.log2vis, 1)
Expand All @@ -40,8 +41,8 @@ def testInvalidEncodedString(self):
""" input: raise UnicodeError for invalid encoded string """
self.assertRaises(UnicodeError, pyfribidi.log2vis, "שלום",
encoding='iso8859-8')


class UnicodeTests(unittest.TestCase):

def testEmpty(self):
Expand Down Expand Up @@ -176,10 +177,15 @@ def testUTF16NaturalRTL(self):
encoding=charset),
u"hello - םולש".encode(charset))


class Crasher(unittest.TestCase):
def test_glibc_free_invalid_next_size(self):
# *** glibc detected *** /home/ralf/py27/bin/python2: free(): invalid next size (fast): 0x00000000011cff00 ***
pyfribidi.log2vis('\xf0\x90\x8e\xa2\xf0\x90\x8e\xaf\xf0\x90\x8e\xb4\xf0\x90\x8e\xa1\xf0\x90\x8f\x83')
# *** glibc detected *** /home/ralf/py27/bin/python2: free(): invalid
# next size (fast): 0x00000000011cff00 ***
pyfribidi.log2vis(
'\xf0\x90\x8e\xa2\xf0\x90\x8e\xaf\xf0\x90\x8e\xb4\xf0\x90\x8e\xa1'
'\xf0\x90\x8f\x83')


if __name__ == '__main__':
suite = unittest.defaultTestLoader.loadTestsFromName(__name__)
Expand Down
20 changes: 11 additions & 9 deletions time_pyfribidi.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
"""
time pyfribidi with all hebrew encodings.
"""
from __future__ import print_function

from builtins import range
import syspath
import timeit
import pyfribidi
Expand All @@ -30,24 +32,24 @@ def timeEncoding(encoding, tests):
timer = timeit.Timer(code, setup)
seconds = timer.timeit(number=tests)
microseconds = 1000000 * seconds / tests
print "%12s: %.8f seconds (%.2f usec/pass)" % (encoding, seconds,
microseconds)
print("%12s: %.8f seconds (%.2f usec/pass)" % (encoding, seconds,
microseconds))


# warm up caches
for i in xrange(100000):
for i in range(100000):
pyfribidi.log2vis(u'Some text to warm up the caches')

lines = 50 # typical screen of text
print
print 'time to rerorder %s lines:' % lines
print
print()
print('time to rerorder %s lines:' % lines)
print()
for encoding in hebrew_encodings:
timeEncoding(encoding, lines)

lines = 100000
print
print 'time to rerorder %s lines:' % lines
print
print()
print('time to rerorder %s lines:' % lines)
print()
for encoding in hebrew_encodings:
timeEncoding(encoding, lines)