[Python-modules-commits] [python-djvulibre] 01/05: Imported Upstream version 0.5
Daniel Stender
danstender-guest at moszumanska.debian.org
Tue Aug 11 00:00:47 UTC 2015
This is an automated email from the git hooks/post-receive script.
danstender-guest pushed a commit to branch master
in repository python-djvulibre.
commit 5bce0f4bfa6f8400d43fc8de25c595280f0564e0
Author: Daniel Stender <debian at danielstender.com>
Date: Tue Aug 11 01:48:33 2015 +0200
Imported Upstream version 0.5
---
MANIFEST.in | 2 +-
PKG-INFO | 2 +-
djvu/common.pxi | 153 +++++++++--------
djvu/config.pxi | 3 -
djvu/decode.pyx | 28 ++-
djvu/sexpr.pyx | 315 ++++++++++++++++++++++------------
doc/api/conf.py | 2 +-
doc/changelog | 26 +++
python_djvulibre.egg-info/PKG-INFO | 2 +-
python_djvulibre.egg-info/SOURCES.txt | 1 -
setup.py | 45 ++++-
tests/common.py | 8 +-
tests/test_decode.py | 3 +-
tests/test_sexpr.py | 256 +++++++++++++++------------
14 files changed, 520 insertions(+), 326 deletions(-)
diff --git a/MANIFEST.in b/MANIFEST.in
index e035ff7..ff7776d 100644
--- a/MANIFEST.in
+++ b/MANIFEST.in
@@ -8,7 +8,7 @@ include doc/api/conf.py
include examples/*
-recursive-exclude djvu config.pxi
recursive-include djvu *.py *.pxi *.pxd *.pyx
+recursive-exclude djvu config.pxi
recursive-include tests *.py Makefile *.jpeg *.tex *.djvu
diff --git a/PKG-INFO b/PKG-INFO
index f202e05..62cb069 100644
--- a/PKG-INFO
+++ b/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: python-djvulibre
-Version: 0.4
+Version: 0.5
Summary: Python support for the DjVu image format
Home-page: http://jwilk.net/software/python-djvulibre
Author: Jakub Wilk
diff --git a/djvu/common.pxi b/djvu/common.pxi
index b93f349..936ae67 100644
--- a/djvu/common.pxi
+++ b/djvu/common.pxi
@@ -11,96 +11,106 @@
include 'config.pxi'
-# python-distutils preprocessor macros
+# C library:
-cdef extern from *:
- char* PYTHON_DJVULIBRE_VERSION
+from libc.stdlib cimport free
+from libc.string cimport strlen
-# C library
+# Python memory handling:
-ctypedef int size_t
+from cpython.mem cimport PyMem_Malloc as py_malloc
+from cpython.mem cimport PyMem_Free as py_free
-cdef extern from 'stdio.h':
- ctypedef struct FILE
+# Python numbers:
-cdef extern from 'stdlib.h':
- void libc_free 'free'(void* ptr) nogil
+from cpython cimport (
+ PyInt_Check as is_short_int,
+ PyLong_Check as is_long_int,
+)
+cdef int is_int(object o):
+ return is_short_int(o) or is_long_int(o)
-cdef extern from 'string.h':
- int strcmp(char *s1, char *s2) nogil
- size_t strlen(char *s) nogil
+from cpython cimport (
+ PyNumber_Check as is_number,
+ PyFloat_Check as is_float,
+)
-# Python library
+IF PY3K:
+ from cpython cimport PyNumber_Long as int
+ELSE:
+ from cpython cimport PyNumber_Int as int
+
+# Python strings:
+
+from cpython cimport (
+ PyUnicode_Check as is_unicode,
+ PyString_Check as is_string,
+ PyBytes_Check as is_bytes,
+)
+
+from cpython cimport (
+ PyUnicode_AsUTF8String as encode_utf8,
+ PyUnicode_DecodeUTF8 as decode_utf8_ex,
+ PyBytes_AsStringAndSize as bytes_to_charp,
+ PyBytes_FromStringAndSize as charp_to_bytes,
+)
+IF PY3K:
+ cdef extern from 'Python.h':
+ object charp_to_string 'PyUnicode_FromString'(char *v)
+ELSE:
+ from cpython cimport PyString_FromString as charp_to_string
+
+cdef object decode_utf8(char* s):
+ return decode_utf8_ex(s, strlen(s), NULL)
cdef extern from 'Python.h':
+ int buffer_to_writable_memory 'PyObject_AsWriteBuffer'(object, void **, Py_ssize_t *)
- void* py_malloc 'PyMem_Malloc'(size_t)
- void py_free 'PyMem_Free'(void*)
+# Python booleans:
- int is_short_int 'PyInt_Check'(object)
- int is_long_int 'PyLong_Check'(object)
- int is_number 'PyNumber_Check'(object)
- int is_float 'PyFloat_Check'(object)
- int is_slice 'PySlice_Check'(object)
+from cpython cimport PyBool_FromLong as bool
- int is_unicode 'PyUnicode_Check'(object)
- int is_string 'PyString_Check'(object)
- IF PY3K:
- int is_bytes 'PyBytes_Check'(object)
- ELSE:
- int is_bytes 'PyString_Check'(object)
-
- object encode_utf8 'PyUnicode_AsUTF8String'(object)
- object decode_utf8_ex 'PyUnicode_DecodeUTF8'(char *, Py_ssize_t, char *)
- IF PY3K:
- int bytes_to_charp 'PyBytes_AsStringAndSize'(object, char**, Py_ssize_t*) except -1
- object charp_to_bytes 'PyBytes_FromStringAndSize'(char *, Py_ssize_t)
- ELSE:
- int bytes_to_charp 'PyString_AsStringAndSize'(object, char**, Py_ssize_t*) except -1
- object charp_to_bytes 'PyString_FromStringAndSize'(char *, Py_ssize_t)
- IF PY3K:
- object charp_to_string 'PyUnicode_FromString'(char *)
- ELSE:
- object charp_to_string 'PyString_FromString'(char *)
- int buffer_to_writable_memory 'PyObject_AsWriteBuffer'(object, void **, Py_ssize_t *)
+# Python pointer->integer conversion:
+
+from cpython cimport PyLong_FromVoidPtr as voidp_to_int
- IF PY3K:
- object int 'PyNumber_Long'(object)
- ELSE:
- object int 'PyNumber_Int'(object)
- object bool 'PyBool_FromLong'(long)
- object voidp_to_int 'PyLong_FromVoidPtr'(void *)
+# Python files:
- IF PY3K:
- object posix_error 'PyErr_SetFromErrno'(object)
- int file_to_fd 'PyObject_AsFileDescriptor'(object)
- ELSE:
- FILE* file_to_cfile 'PyFile_AsFile'(object)
+from libc.stdio cimport FILE
- int list_append 'PyList_Append'(object, object) except -1
+# Python lists:
- cdef object richcmp 'PyObject_RichCompare'(object, object, int)
+from cpython cimport PyList_Append as list_append
-cdef extern from 'pythread.h':
- ctypedef void* Lock 'PyThread_type_lock'
- cdef Lock allocate_lock 'PyThread_allocate_lock'()
- cdef void free_lock 'PyThread_free_lock'(Lock lock)
- cdef int acquire_lock 'PyThread_acquire_lock'(Lock lock, int mode) nogil
- cdef void release_lock 'PyThread_release_lock'(Lock lock)
+# Python rich comparison:
- ctypedef enum:
- WAIT_LOCK
- NOWAIT_LOCK
+from cpython cimport PyObject_RichCompare as richcmp
+
+# Python slices:
+
+cdef extern from 'Python.h':
+ int is_slice 'PySlice_Check'(object)
+
+# Python threads:
+
+from cpython cimport (
+ PyThread_type_lock as Lock,
+ PyThread_allocate_lock as allocate_lock,
+ PyThread_free_lock as free_lock,
+ PyThread_acquire_lock as acquire_lock,
+ PyThread_release_lock as release_lock,
+ WAIT_LOCK,
+ NOWAIT_LOCK,
+)
+
+# Python type checks:
cdef extern from 'object.h':
ctypedef struct PyTypeObject:
char *tp_name
- ctypedef struct PyObject:
- PyTypeObject *ob_type
- int _typecheck 'PyObject_TypeCheck'(object o, PyTypeObject* type)
-cdef int is_int(object o):
- return is_short_int(o) or is_long_int(o)
+from cpython cimport PyObject
+from cpython cimport PyObject_TypeCheck as _typecheck
cdef object type(object o):
return <object>((<PyObject*>o).ob_type)
@@ -115,18 +125,11 @@ ELSE:
cdef int typecheck(object o, object type):
return _typecheck(o, <PyTypeObject*> type)
-cdef int is_file(object o):
- IF PY3K:
- return not is_number(o) and file_to_fd(o) != -1
- ELSE:
- return typecheck(o, file)
+# Python exceptions:
cdef void raise_instantiation_error(object cls) except *:
raise TypeError, 'cannot create \'{tp}\' instances'.format(tp=get_type_name(cls))
-cdef object decode_utf8(char* s):
- return decode_utf8_ex(s, strlen(s), NULL)
-
cdef extern from 'pyerrors.h':
ctypedef class __builtin__.Exception [object PyBaseExceptionObject]:
pass
diff --git a/djvu/config.pxi b/djvu/config.pxi
deleted file mode 100644
index 9ac1fdd..0000000
--- a/djvu/config.pxi
+++ /dev/null
@@ -1,3 +0,0 @@
-DEF PY3K = False
-DEF PYTHON_DJVULIBRE_VERSION = "0.4"
-DEF HAVE_LANGINFO_H = True
diff --git a/djvu/decode.pyx b/djvu/decode.pyx
index 0ba53ca..bfe56e0 100644
--- a/djvu/decode.pyx
+++ b/djvu/decode.pyx
@@ -197,10 +197,23 @@ cdef extern from 'libdjvu/ddjvuapi.h':
cexpr_t* ddjvu_anno_get_metadata_keys(cexpr_t annotations) nogil
char* ddjvu_anno_get_metadata(cexpr_t annotations, cexpr_t key) nogil
+# Python files:
+
+IF PY3K:
+ from cpython cimport (
+ PyErr_SetFromErrno as posix_error,
+ PyObject_AsFileDescriptor as file_to_fd,
+ )
+ cdef int is_file(object o):
+ return not is_number(o) and file_to_fd(o) != -1
+ELSE:
+ cdef extern from 'Python.h':
+ FILE* file_to_cfile 'PyFile_AsFile'(object)
+ int is_file 'PyFile_Check'(object)
+from posix.unistd cimport dup
+from libc.stdio cimport fclose
cdef extern from 'unistd.h':
- int dup(int)
FILE *fdopen(int, char*)
- int fclose(FILE *)
IF HAVE_LANGINFO_H:
cdef extern from 'langinfo.h':
@@ -516,7 +529,7 @@ cdef class Page:
try:
return decode_utf8(s)
finally:
- libc_free(s)
+ free(s)
def decode(self, wait=1):
'''
@@ -897,7 +910,7 @@ cdef class File:
try:
return decode_utf8(s)
finally:
- libc_free(s)
+ free(s)
cdef object pages_to_opt(object pages, int sort_uniq):
if sort_uniq:
@@ -3317,7 +3330,7 @@ cdef class Hyperlinks:
list_append(self._sexpr, wrap_sexpr(annotations._document, current[0]))
current = current + 1
finally:
- libc_free(all)
+ free(all)
def __len__(self):
return len(self._sexpr)
@@ -3349,7 +3362,7 @@ cdef class Metadata:
current = current + 1
self._keys = frozenset(keys)
finally:
- libc_free(all)
+ free(all)
def __len__(self):
return len(self._keys)
@@ -3419,7 +3432,6 @@ __author__ = 'Jakub Wilk <jwilk at jwilk.net>'
IF PY3K:
__version__ = decode_utf8(PYTHON_DJVULIBRE_VERSION)
ELSE:
- __version__ = PYTHON_DJVULIBRE_VERSION
-__version__ = '{0}/{1}'.format(__version__, DDJVU_VERSION)
+ __version__ = str(PYTHON_DJVULIBRE_VERSION)
# vim:ts=4 sts=4 sw=4 et ft=pyrex
diff --git a/djvu/sexpr.pyx b/djvu/sexpr.pyx
index 060bc54..d5b7bd5 100644
--- a/djvu/sexpr.pyx
+++ b/djvu/sexpr.pyx
@@ -52,15 +52,28 @@ cdef extern from 'libdjvu/miniexp.h':
void cvar_free 'minivar_free'(cvar_t* v) nogil
cexpr_t* cvar_ptr 'minivar_pointer'(cvar_t* v) nogil
- int io_7bit 'minilisp_print_7bits'
- int (*io_puts 'minilisp_puts')(char *s)
- int (*io_getc 'minilisp_getc')()
- int (*io_ungetc 'minilisp_ungetc')(int c)
- void io_set_output 'minilisp_set_output'(FILE *f)
- void io_set_input 'minilisp_set_input'(FILE *f)
- cexpr_t cexpr_read 'miniexp_read'()
- cexpr_t cexpr_print 'miniexp_prin'(cexpr_t cexpr)
- cexpr_t cexpr_printw 'miniexp_pprin'(cexpr_t cexpr, int width)
+ IF HAVE_MINIEXP_IO_T:
+ ctypedef cexpr_io_s cexpr_io_t 'miniexp_io_t'
+ struct cexpr_io_s 'miniexp_io_s':
+ int (*puts 'fputs')(cexpr_io_t*, char*)
+ int (*getc 'fgetc')(cexpr_io_t*)
+ int (*ungetc)(cexpr_io_t*, int)
+ void *data[4]
+ int *p_flags
+ void cexpr_io_init 'miniexp_io_init'(cexpr_io_t *cio)
+ enum:
+ cexpr_io_print7bits 'miniexp_io_print7bits'
+ cexpr_t cexpr_read 'miniexp_read_r'(cexpr_io_t *cio)
+ cexpr_t cexpr_print 'miniexp_prin_r'(cexpr_io_t *cio, cexpr_t cexpr)
+ cexpr_t cexpr_printw 'miniexp_pprin_r'(cexpr_io_t *cio, cexpr_t cexpr, int width)
+ ELSE:
+ int io_7bit 'minilisp_print_7bits'
+ int (*io_puts 'minilisp_puts')(char *s)
+ int (*io_getc 'minilisp_getc')()
+ int (*io_ungetc 'minilisp_ungetc')(int c)
+ cexpr_t cexpr_read 'miniexp_read'()
+ cexpr_t cexpr_print 'miniexp_prin'(cexpr_t cexpr)
+ cexpr_t cexpr_printw 'miniexp_pprin'(cexpr_t cexpr, int width)
cdef extern from 'stdio.h':
int EOF
@@ -83,112 +96,186 @@ import weakref
cdef object symbol_dict
symbol_dict = weakref.WeakValueDictionary()
-cdef Lock _myio_lock
-_myio_lock = allocate_lock()
-cdef object _myio_stdin
-cdef object _myio_stdout
-cdef int _myio_stdout_binary
-cdef object _myio_buffer
-_myio_buffer = []
-cdef int _backup_io_7bit
-cdef int (*_backup_io_puts)(char *s)
-cdef int (*_backup_io_getc)()
-cdef int (*_backup_io_ungetc)(int c)
-
-cdef object write_unraisable_exception(object cause):
- message = format_exc()
- sys.stderr.write(
- 'Unhandled exception ({obj!r})\n{msg}\n'.format(obj=cause, msg=message)
- )
-
-cdef void myio_set(object stdin, object stdout, int escape_unicode=True):
- global _myio_stdin, _myio_stdout, _myio_stdout_binary, _myio_buffer
- global _backup_io_7bit, _backup_io_puts, _backup_io_getc, _backup_io_ungetc
- global io_7bit, io_puts, io_getc, io_ungetc
- cdef int opt_stdin, opt_stdout
- with nogil: acquire_lock(_myio_lock, WAIT_LOCK)
- _backup_io_7bit = io_7bit
- _backup_io_puts = io_puts
- _backup_io_getc = io_getc
- _backup_io_ungetc = io_ungetc
- _myio_stdin = stdin
- IF PY3K:
- # TODO
- opt_stdin = opt_stdout = 0
+cdef object codecs
+import codecs
+
+IF not HAVE_MINIEXP_IO_T:
+ cdef Lock _myio_lock
+ _myio_lock = allocate_lock()
+
+cdef class _ExpressionIO:
+ IF HAVE_MINIEXP_IO_T:
+ cdef cexpr_io_t cio
+ cdef int flags
ELSE:
- opt_stdin = is_file(stdin)
- opt_stdout = is_file(stdout)
- if opt_stdin:
- IF not PY3K:
- io_set_input(file_to_cfile(stdin))
+ cdef int (*backup_io_puts)(char *s)
+ cdef int (*backup_io_getc)()
+ cdef int (*backup_io_ungetc)(int c)
+ cdef int backup_io_7bit
+ cdef object stdin
+ cdef object stdout
+ cdef int stdout_binary
+ cdef object buffer
+ cdef object exc
+
+ _reentrant = HAVE_MINIEXP_IO_T
+
+ def __init__(self, object stdin=None, object stdout=None, int escape_unicode=True):
+ IF not HAVE_MINIEXP_IO_T:
+ global io_7bit, io_puts, io_getc, io_ungetc
+ global _myio
+ with nogil: acquire_lock(_myio_lock, WAIT_LOCK)
+ self.backup_io_7bit = io_7bit
+ self.backup_io_puts = io_puts
+ self.backup_io_getc = io_getc
+ self.backup_io_ungetc = io_ungetc
+ self.stdin = stdin
+ self.stdout = stdout
+ IF PY3K:
+ self.stdout_binary = not hasattr(stdout, 'encoding')
ELSE:
- pass # TODO
- else:
- io_getc = _myio_getc
- io_ungetc = _myio_ungetc
- _myio_stdout = stdout
- IF PY3K:
- _myio_stdout_binary = not hasattr(stdout, 'encoding')
- ELSE:
- _myio_stdout_binary = 1
- if opt_stdout:
- IF not PY3K:
- io_set_output(file_to_cfile(stdout))
+ # In Python 2, sys.stdout has the encoding attribute,
+ # even though it accepts byte strings.
+ # Let's only make a special-case for codecs.
+ self.stdout_binary = not isinstance(stdout, codecs.StreamReaderWriter)
+ self.buffer = []
+ self.exc = None
+ IF HAVE_MINIEXP_IO_T:
+ cexpr_io_init(&self.cio)
+ self.cio.data[0] = <void*>self
+ self.cio.getc = _myio_getc
+ self.cio.ungetc = _myio_ungetc
+ self.cio.puts = _myio_puts
+ if escape_unicode:
+ self.flags = cexpr_io_print7bits
+ else:
+ self.flags = 0
+ self.cio.p_flags = &self.flags
ELSE:
- pass # TODO
- else:
- io_puts = _myio_puts
- io_7bit = escape_unicode
- _myio_buffer = []
-
-cdef void myio_reset():
- global _myio_stdin, _myio_stdout, _myio_stdout_binary, _myio_buffer
- global io_7bit, io_puts, io_getc, io_ungetc
- _myio_stdin = None
- _myio_stdout = None
- _myio_stdout_binary = 0
- _myio_buffer = None
- io_7bit = _backup_io_7bit
- io_puts = _backup_io_puts
- io_getc = _backup_io_getc
- io_ungetc = _backup_io_ungetc
- release_lock(_myio_lock)
-
-cdef int _myio_puts(char *s):
- try:
- if _myio_stdout_binary:
- _myio_stdout.write(s)
- else:
- _myio_stdout.write(decode_utf8(s))
- except:
- write_unraisable_exception(_myio_stdout)
- return EOF
-
-cdef int _myio_getc():
- global _myio_buffer
- cdef int result
- if _myio_buffer:
- return _myio_buffer.pop()
- else:
+ io_getc = _myio_getc
+ io_ungetc = _myio_ungetc
+ io_puts = _myio_puts
+ io_7bit = escape_unicode
+ _myio = self
+
+ cdef close(self):
+ IF not HAVE_MINIEXP_IO_T:
+ global io_7bit, io_puts, io_getc, io_ungetc
+ global _myio
+ _myio = None
+ self.stdin = None
+ self.stdout = None
+ self.buffer = None
+ IF not HAVE_MINIEXP_IO_T:
+ io_7bit = self.backup_io_7bit
+ io_puts = self.backup_io_puts
+ io_getc = self.backup_io_getc
+ io_ungetc = self.backup_io_ungetc
+ try:
+ if self.exc is not None:
+ raise self.exc[0], self.exc[1], self.exc[2]
+ finally:
+ IF not HAVE_MINIEXP_IO_T:
+ release_lock(_myio_lock)
+ self.exc = None
+
+ IF HAVE_MINIEXP_IO_T:
+
+ cdef cexpr_t read(self):
+ return cexpr_read(&self.cio)
+
+ cdef cexpr_t print_(self, cexpr_t cexpr):
+ return cexpr_print(&self.cio, cexpr)
+
+ cdef cexpr_t printw(self, cexpr_t cexpr, int width):
+ return cexpr_printw(&self.cio, cexpr, width)
+
+ ELSE:
+
+ cdef cexpr_t read(self):
+ return cexpr_read()
+
+ cdef cexpr_t print_(self, cexpr_t cexpr):
+ return cexpr_print(cexpr)
+
+ cdef cexpr_t printw(self, cexpr_t cexpr, int width):
+ return cexpr_printw(cexpr, width)
+
+IF HAVE_MINIEXP_IO_T:
+
+ cdef int _myio_puts(cexpr_io_t* cio, char *s):
+ cdef _ExpressionIO io
+ xio = <_ExpressionIO> cio.data[0]
try:
- s = _myio_stdin.read(1)
+ if xio.stdout_binary:
+ xio.stdout.write(s)
+ else:
+ xio.stdout.write(decode_utf8(s))
except:
- write_unraisable_exception(_myio_stdin)
+ xio.exc = sys.exc_info()
return EOF
- if s:
+
+ cdef int _myio_getc(cexpr_io_t* cio):
+ cdef _ExpressionIO xio
+ cdef int result
+ xio = <_ExpressionIO> cio.data[0]
+ if xio.buffer:
+ return xio.buffer.pop()
+ try:
+ s = xio.stdin.read(1)
+ if not s:
+ return EOF
if is_unicode(s):
- s = s.encode('UTF-8')
+ s = encode_utf8(s)
IF PY3K:
- _myio_buffer += reversed(s)
+ xio.buffer += reversed(s)
ELSE:
- _myio_buffer += map(ord, reversed(s))
- return _myio_buffer.pop()
- else:
+ xio.buffer += map(ord, reversed(s))
+ return xio.buffer.pop()
+ except:
+ xio.exc = sys.exc_info()
+ return EOF
+
+ cdef int _myio_ungetc(cexpr_io_t* cio, int c):
+ cdef _ExpressionIO io
+ xio = <_ExpressionIO> cio.data[0]
+ list_append(xio.buffer, c)
+
+ELSE:
+
+ cdef _ExpressionIO _myio
+
+ cdef int _myio_puts(char *s):
+ try:
+ if _myio.stdout_binary:
+ _myio.stdout.write(s)
+ else:
+ _myio.stdout.write(decode_utf8(s))
+ except:
+ _myio.exc = sys.exc_info()
+ return EOF
+
+ cdef int _myio_getc():
+ cdef int result
+ if _myio.buffer:
+ return _myio.buffer.pop()
+ try:
+ s = _myio.stdin.read(1)
+ if not s:
+ return EOF
+ if is_unicode(s):
+ s = encode_utf8(s)
+ IF PY3K:
+ _myio.buffer += reversed(s)
+ ELSE:
+ _myio.buffer += map(ord, reversed(s))
+ return _myio.buffer.pop()
+ except:
+ _myio.exc = sys.exc_info()
return EOF
-cdef int _myio_ungetc(int c):
- global _myio_buffer
- _myio_buffer += (c,)
+ cdef int _myio_ungetc(int c):
+ list_append(_myio.buffer, c)
cdef object the_sentinel
the_sentinel = object()
@@ -205,6 +292,7 @@ cdef class _WrappedCExpr:
cdef object print_into(self, object stdout, object width, int escape_unicode):
cdef cexpr_t cexpr
+ cdef _ExpressionIO xio
if width is None:
pass
elif not is_int(width):
@@ -212,14 +300,14 @@ cdef class _WrappedCExpr:
elif width <= 0:
raise ValueError('width <= 0')
cexpr = self.cexpr()
- myio_set(None, stdout, escape_unicode)
+ xio = _ExpressionIO(stdout=stdout, escape_unicode=escape_unicode)
try:
if width is None:
- cexpr_print(cexpr)
+ xio.print_(cexpr)
else:
- cexpr_printw(cexpr, width)
+ xio.printw(cexpr, width)
finally:
- myio_reset()
+ xio.close()
cdef object as_string(self, object width, int escape_unicode):
stdout = StringIO()
@@ -355,14 +443,15 @@ def _expression_from_stream(stdin):
Read an expression from a stream.
'''
+ cdef _ExpressionIO xio
try:
- myio_set(stdin, None)
+ xio = _ExpressionIO(stdin=stdin)
try:
- return _c2py(cexpr_read())
+ return _c2py(xio.read())
except InvalidExpression:
raise ExpressionSyntaxError
finally:
- myio_reset()
+ xio.close()
def _expression_from_string(str):
'''
@@ -663,7 +752,7 @@ cdef BaseExpression _c2py(cexpr_t cexpr):
elif cexpr_is_str(cexpr):
result = StringExpression(_wexpr)
else:
- raise ValueError
+ raise InvalidExpression
return result
cdef _WrappedCExpr _build_list_cexpr(object items):
@@ -987,6 +1076,6 @@ __author__ = 'Jakub Wilk <jwilk at jwilk.net>'
IF PY3K:
__version__ = decode_utf8(PYTHON_DJVULIBRE_VERSION)
ELSE:
- __version__ = PYTHON_DJVULIBRE_VERSION
+ __version__ = str(PYTHON_DJVULIBRE_VERSION)
# vim:ts=4 sts=4 sw=4 et ft=pyrex
diff --git a/doc/api/conf.py b/doc/api/conf.py
index 77c6174..eed4890 100644
--- a/doc/api/conf.py
+++ b/doc/api/conf.py
@@ -19,7 +19,7 @@ master_doc = 'index'
import setup as _setup
project = _setup.setup_params['name']
-version = release = _setup.__version__
+version = release = _setup.py_version
_setup_file = codecs.open(
os.path.splitext(_setup.__file__)[0] + '.py',
'r', encoding='UTF-8'
diff --git a/doc/changelog b/doc/changelog
index fb0ec09..9e02054 100644
--- a/doc/changelog
+++ b/doc/changelog
@@ -1,3 +1,28 @@
+python-djvulibre (0.5) unstable; urgency=low
+
+ * Make print_into() raise exceptions properly instead of just printing them
+ on stderr.
+ * Make it possible to print S-expressions into file-like objects created by
+ codecs.open().
+ * Make djvu.sexpr.__version__ a byte string in Python 2.X.
+ * Don't include DjVu file format version in djvu.decode.__version__.
+ This information is more conveniently available in
+ djvu.decode.DDJVU_VERSION.
+ * Make S-expression input/output methods reentrant.
+ (DjVuLibre >= 3.5.26 is required for this feature.)
+ * Improve error handling.
+ * Improve the test suite.
+
+ -- Jakub Wilk <jwilk at jwilk.net> Sun, 02 Aug 2015 17:45:08 +0200
+
+python-djvulibre (0.4.1) unstable; urgency=low
+
+ * Exclude djvu/config.pxi from the source tarball.
+ Thanks to Daniel Stender for the bug report.
+ https://bitbucket.org/jwilk/python-djvulibre/issues/4
+
+ -- Jakub Wilk <jwilk at jwilk.net> Mon, 27 Jul 2015 10:28:21 +0200
+
python-djvulibre (0.4) unstable; urgency=low
* Drop support for Python 2.5.
@@ -12,6 +37,7 @@ python-djvulibre (0.4) unstable; urgency=low
Making it work offline and consistently across different Python versions
is too much of a hassle, and it was used only to cross-reference one
well-known exception (IOError).
+ * Make djvu.decode.__version__ a byte string in Python 2.X.
* Improve the test suite.
-- Jakub Wilk <jwilk at jwilk.net> Wed, 22 Jul 2015 21:05:11 +0200
diff --git a/python_djvulibre.egg-info/PKG-INFO b/python_djvulibre.egg-info/PKG-INFO
index f202e05..62cb069 100644
--- a/python_djvulibre.egg-info/PKG-INFO
+++ b/python_djvulibre.egg-info/PKG-INFO
@@ -1,6 +1,6 @@
Metadata-Version: 1.1
Name: python-djvulibre
-Version: 0.4
+Version: 0.5
Summary: Python support for the DjVu image format
Home-page: http://jwilk.net/software/python-djvulibre
Author: Jakub Wilk
diff --git a/python_djvulibre.egg-info/SOURCES.txt b/python_djvulibre.egg-info/SOURCES.txt
index 4f08d38..377fa18 100644
--- a/python_djvulibre.egg-info/SOURCES.txt
+++ b/python_djvulibre.egg-info/SOURCES.txt
@@ -2,7 +2,6 @@ MANIFEST.in
setup.py
djvu/__init__.py
djvu/common.pxi
-djvu/config.pxi
djvu/const.py
djvu/decode.pxd
djvu/decode.pyx
diff --git a/setup.py b/setup.py
index 46e4df8..6bce5b9 100644
--- a/setup.py
+++ b/setup.py
@@ -63,6 +63,7 @@ import distutils.ccompiler
import distutils.command.clean
import distutils.command.build_ext
import distutils.dep_util
+import distutils.version
try:
import sphinx.setup_command as sphinx_setup_command
@@ -89,9 +90,12 @@ def get_version():
finally:
changelog.close()
-PKG_CONFIG_FLAG_MAP = {'-I': 'include_dirs', '-L': 'library_dirs', '-l': 'libraries'}
-
-def pkg_config(*packages, **kwargs):
+def pkgconfig_build_flags(*packages, **kwargs):
+ flag_map = {
+ '-I': 'include_dirs',
+ '-L': 'library_dirs',
+ '-l': 'libraries',
+ }
fallback = dict(
libraries=['djvulibre'],
)
@@ -123,13 +127,34 @@ def pkg_config(*packages, **kwargs):
key = argument[:2]
try:
value = argument[2:]
- kwargs.setdefault(PKG_CONFIG_FLAG_MAP[key], []).append(value)
+ kwargs.setdefault(flag_map[key], []).append(value)
except KeyError:
kwargs['extra_link_args'].append(argument)
kwargs['extra_compile_args'].append(argument)
return kwargs
-__version__ = get_version()
+def pkgconfig_version(package):
+ V = distutils.version.LooseVersion
+ try:
+ pkgconfig = ipc.Popen(
+ ['pkg-config', '--modversion', package],
+ stdout=ipc.PIPE, stderr=ipc.PIPE
+ )
+ except OSError:
+ _, ex, _ = sys.exc_info()
+ distutils.log.warn('cannot execute pkg-config: ' + str(ex))
+ return V('0')
+ stdout, stderr = pkgconfig.communicate()
+ stdout = stdout.decode('ASCII', 'replace')
+ stderr = stderr.decode('ASCII', 'replace')
+ if pkgconfig.returncode:
+ distutils.log.warn('pkg-config failed: ' + stderr.strip())
+ return V('0')
+ version = stdout.strip()
+ return V(version)
+
+djvulibre_version = pkgconfig_version('ddjvuapi')
+py_version = get_version()
# Work-around for <https://bugs.python.org/issue969718>:
try:
@@ -144,11 +169,13 @@ class build_ext(distutils.command.build_ext.build_ext):
def run(self):
new_config = [
'DEF PY3K = {0}'.format(sys.version_info >= (3, 0)),
- 'DEF PYTHON_DJVULIBRE_VERSION = "{0}"'.format(__version__),
+ 'DEF PYTHON_DJVULIBRE_VERSION = "{0}"'.format(py_version),
+ 'DEF HAVE_MINIEXP_IO_T = {0}'.format(djvulibre_version >= '3.5.26'),
'DEF HAVE_LANGINFO_H = {0}'.format(os.name == 'posix' and not mingw32cross),
]
try:
- old_config = open(self.config_filename, 'rt').read()
+ with open(self.config_filename, 'rt') as fp:
+ old_config = fp.read()
except IOError:
old_config = ''
if '\n'.join(new_config).strip() != old_config.strip():
@@ -223,11 +250,11 @@ if sphinx_setup_command:
else:
build_sphinx = None
-compiler_flags = pkg_config('ddjvuapi')
+compiler_flags = pkgconfig_build_flags('ddjvuapi')
setup_params = dict(
name='python-djvulibre',
- version=__version__,
+ version=py_version,
author='Jakub Wilk',
author_email='jwilk at jwilk.net',
license='GNU GPL 2',
diff --git a/tests/common.py b/tests/common.py
index afec209..72cb41a 100644
--- a/tests/common.py
+++ b/tests/common.py
@@ -228,9 +228,11 @@ def skip_unless_translation_exists(lang):
raise SkipTest('libc translation not found: ' + lang)
def skip_unless_command_exists(command):
- child = ipc.Popen('command -v ' + command, shell=True, stdout=ipc.PIPE, stderr=ipc.PIPE)
- if child.wait() == 0:
- return
+ directories = os.environ['PATH'].split(os.pathsep)
+ for directory in directories:
+ path = os.path.join(directory, command)
+ if os.access(path, os.X_OK):
+ return
raise SkipTest('command not found: ' + command)
__all__ = [
diff --git a/tests/test_decode.py b/tests/test_decode.py
index 6b8c4bc..e0c2d79 100644
--- a/tests/test_decode.py
+++ b/tests/test_decode.py
@@ -568,7 +568,8 @@ class test_streams:
document.pages[0].annotations.sexpr
try:
- message.stream.write(open(images + 'test1.djvu', 'rb').read())
+ with open(images + 'test1.djvu', 'rb') as fp:
+ message.stream.write(fp.read())
finally:
message.stream.close()
with assert_raises_str(IOError, 'I/O operation on closed file'):
diff --git a/tests/test_sexpr.py b/tests/test_sexpr.py
index 2724904..2d4f1c8 100644
--- a/tests/test_sexpr.py
+++ b/tests/test_sexpr.py
@@ -12,11 +12,10 @@
# General Public License for more details.
import collections
+import codecs
import copy
+import errno
import io
-import os
-import re
-import sys
import tempfile
import pickle
@@ -26,6 +25,8 @@ except ImportError:
cpickle = None
from djvu.sexpr import *
+from djvu.sexpr import __version__
+from djvu.sexpr import _ExpressionIO
from common import *
@@ -78,6 +79,16 @@ class test_int_expressions():
x = Expression(42)
assert_pickle_equal(x)
+class test_float_expressions():
+
+ # TODO: float expressions are not implemented yet
+
+ def test_parse(self):
+ with assert_raises(ExpressionSyntaxError):
+ x = Expression.from_string('3.14')
+ if isinstance(x.value, Symbol):
+ raise ExpressionSyntaxError
+
class test_symbols():
def t(self, name):
@@ -405,11 +416,6 @@ class test_list_expressions():
x = Expression(lst)
assert_pickle_equal(x)
-def strip_line_numbers_from_traceback(s):
- s = re.sub('(?<=[.]c):[0-9]+(?=[)])', '', s)
- s = re.sub(', line [0-9]+(?=, )', '', s)
- return s
-
class test_expression_parser():
def test_badstring(self):
@@ -420,91 +426,113 @@ class test_expression_parser():
assert_is(getattr(Expression, 'from_file', None), None)
def test_bad_io(self):
- stderr = StringIO()
- with interim(sys, stderr=stderr):
- with assert_raises(ExpressionSyntaxError):
- Expression.from_stream(42)
- stderr = strip_line_numbers_from_traceback(stderr.getvalue())
- stderr = stderr.replace(
- '"sexpr.pyx"', # Cython < 0.21
- '"djvu/sexpr.pyx"' # Cython ≥ 0.21
- )
- stderr = stderr.replace('\n s = _myio_stdin.read(1)\n', '\n')
- assert_multi_line_equal(stderr, '''\
-Unhandled exception (42)
-Traceback (most recent call last):
- File "djvu/sexpr.pyx", in djvu.sexpr._myio_getc (djvu/sexpr.c)
-AttributeError: 'int' object has no attribute 'read'
+ with assert_raises_str(AttributeError, "'int' object has no attribute 'read'"):
+ Expression.from_stream(42)
... 255 lines suppressed ...
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/python-modules/packages/python-djvulibre.git
More information about the Python-modules-commits
mailing list