10000 fix with older libvipses · libvips/pyvips@b7301d2 · GitHub
[go: up one dir, main page]

Skip to content

Commit b7301d2

Browse files
committed
fix with older libvipses
now works with pre-8.9 libvipses
1 parent 140fc57 commit b7301d2

File tree

3 files changed

+161
-151
lines changed

3 files changed

+161
-151
lines changed

pyvips/gobject.py

Lines changed: 78 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@
33
import logging
44

55
import pyvips
6-
from pyvips import ffi, gobject_lib, _to_bytes, Error, type_name
6+
from pyvips import ffi, gobject_lib, _to_bytes, Error, type_name, \
7+
at_least_libvips
78

89
logger = logging.getLogger(__name__)
910

@@ -35,84 +36,85 @@ def _marshal_image_progress(vi, pointer, handle):
3536
ffi.callback('void(VipsImage*, void*, void*)',
3637
_marshal_image_progress))
3738

38-
if pyvips.API_mode:
39-
@ffi.def_extern()
40-
def _marshal_read(streamiu, pointer, length, handle):
41-
buf = ffi.buffer(pointer, length)
42-
callback = ffi.from_handle(handle)
43-
return callback(buf)
44-
_marshal_read_cb = \
45-
ffi.cast('GCallback', gobject_lib._marshal_read)
46-
else:
47-
def _marshal_read(streamiu, pointer, length, handle):
48-
buf = ffi.buffer(pointer, length)
49-
callback = ffi.from_handle(handle)
50-
return callback(buf)
51-
_marshal_read_cb = \
52-
ffi.cast('GCallback',
53-
ffi.callback('gint64(VipsStreamiu*, void*, gint64, void*)',
54-
_marshal_read))
55-
56-
if pyvips.API_mode:
57-
@ffi.def_extern()
58-
def _marshal_seek(streamiu, offset, whence, handle):
59-
callback = ffi.from_handle(handle)
60-
return callback(offset, whence)
61-
_marshal_seek_cb = \
62-
ffi.cast('GCallback', gobject_lib._marshal_seek)
63-
else:
64-
def _marshal_seek(streamiu, offset, whence, handle):
65-
callback = ffi.from_handle(handle)
66-
return callback(offset, whence)
67-
_marshal_seek_cb = \
68-
ffi.cast('GCallback',
69-
ffi.callback('gint64(VipsStreamiu*, gint64, int, void*)',
70-
_marshal_seek))
71-
72-
if pyvips.API_mode:
73-
@ffi.def_extern()
74-
def _marshal_write(streamiu, pointer, length, handle):
75-
buf = ffi.buffer(pointer, length)
76-
callback = ffi.from_handle(handle)
77-
return callback(buf)
78-
_marshal_write_cb = \
79-
ffi.cast('GCallback', gobject_lib._marshal_write)
80-
else:
81-
def _marshal_write(streamiu, pointer, length, handle):
82-
buf = ffi.buffer(pointer, length)
83-
callback = ffi.from_handle(handle)
84-
return callback(buf)
85-
_marshal_write_cb = \
86-
ffi.cast('GCallback',
87-
ffi.callback('gint64(VipsStreamou*, void*, gint64, void*)',
88-
_marshal_write))
89-
90-
if pyvips.API_mode:
91-
@ffi.def_extern()
92-
def _marshal_finish(streamiu, handle):
93-
callback = ffi.from_handle(handle)
94-
callback()
95-
_marshal_finish_cb = \
96-
ffi.cast('GCallback', gobject_lib._marshal_finish)
97-
else:
98-
def _marshal_finish(streamiu, handle):
99-
callback = ffi.from_handle(handle)
100-
callback()
101-
_marshal_finish_cb = \
102-
ffi.cast('GCallback',
103-
ffi.callback('void(VipsStreamou*, void*)',
104-
_marshal_finish))
105-
10639
_marshalers = {
107-
"preeval": _marshal_image_progress_cb,
108-
"eval": _marshal_image_progress_cb,
109-
"posteval": _marshal_image_progress_cb,
110-
"read": _marshal_read_cb,
111-
"seek": _marshal_seek_cb,
112-
"write": _marshal_write_cb,
113-
"finish": _marshal_finish_cb,
40+
'preeval': _marshal_image_progress_cb,
41+
'eval': _marshal_image_progress_cb,
42+
'posteval': _marshal_image_progress_cb,
11443
}
11544

45+
if at_least_libvips(8, 9):
46+
if pyvips.API_mode:
47+
@ffi.def_extern()
48+
def _marshal_read(streamiu, pointer, length, handle):
49+
buf = ffi.buffer(pointer, length)
50+
callback = ffi.from_handle(handle)
51+
return callback(buf)
52+
_marshal_read_cb = \
53+
ffi.cast('GCallback', gobject_lib._marshal_read)
54+
else:
55+
def _marshal_read(streamiu, pointer, length, handle):
56+
buf = ffi.buffer(pointer, length)
57+
callback = ffi.from_handle(handle)
58+
return callback(buf)
59+
_marshal_read_cb = \
60+
ffi.cast('GCallback',
61+
ffi.callback('gint64(VipsStreamiu*, void*, gint64, void*)',
62+
_marshal_read))
63+
_marshalers['read'] = _marshal_read_cb
64+
65+
if pyvips.API_mode:
66+
@ffi.def_extern()
67+
def _marshal_seek(streamiu, offset, whence, handle):
68+
callback = ffi.from_handle(handle)
69+
return callback(offset, whence)
70+
_marshal_seek_cb = \
71+
ffi.cast('GCallback', gobject_lib._marshal_seek)
72+
else:
73+
def _marshal_seek(streamiu, offset, whence, handle):
74+
callback = ffi.from_handle(handle)
75+
return callback(offset, whence)
76+
_marshal_seek_cb = \
77+
ffi.cast('GCallback',
78+
ffi.callback('gint64(VipsStreamiu*, gint64, int, void*)',
79+
_marshal_seek))
80+
_marshalers['seek'] = _marshal_seek_cb
81+
82+
if pyvips.API_mode:
83+
@ffi.def_extern()
84+
def _marshal_write(streamiu, pointer, length, handle):
85+
buf = ffi.buffer(pointer, length)
86+
callback = ffi.from_handle(handle)
87+
return callback(buf)
88+
_marshal_write_cb = \
89+
ffi.cast('GCallback', gobject_lib._marshal_write)
90+
else:
91+
def _marshal_write(streamiu, pointer, length, handle):
92+
buf = ffi.buffer(pointer, length)
93+
callback = ffi.from_handle(handle)
94+
return callback(buf)
95+
_marshal_write_cb = \
96+
ffi.cast('GCallback',
97+
ffi.callback('gint64(VipsStreamou*, void*, gint64, void*)',
98+
_marshal_write))
99+
_marshalers['write'] = _marshal_write_cb
100+
101+
if pyvips.API_mode:
102+
@ffi.def_extern()
103+
def _marshal_finish(streamiu, handle):
104+
callback = ffi.from_handle(handle)
105+
callback()
106+
_marshal_finish_cb = \
107+
ffi.cast('GCallback', gobject_lib._marshal_finish)
108+
else:
109+
def _marshal_finish(streamiu, handle):
110+
callback = ffi.from_handle(handle)
111+
callback()
112+
_marshal_finish_cb = \
113+
ffi.cast('GCallback',
114+
ffi.callback('void(VipsStreamou*, void*)',
115+
_marshal_finish))
116+
_marshalers['finish'] = _marshal_finish_cb
117+
116118

117119
class GObject(object):
118120
"""Manage GObject lifetime.

tests/test_progress.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
import pyvips
66

77

8-
class TestSignals:
8+
class TestProgress:
99
def test_progress(self):
1010
# py27 reques this pattern for non-local modification
1111
notes = {}

tests/test_streams.py

Lines changed: 82 additions & 74 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,119 @@
11
# vim: set fileencoding=utf-8 :
22

33
import tempfile
4+
import pytest
45

56
import pyvips
67
from helpers import JPEG_FILE, temp_filename, skip_if_no
78

9+
if pyvips.at_least_libvips(8, 9):
10+
class Mystreami(pyvips.Streamiu):
11+
def __init__(self, pointer):
12+
super(Mystreami, self).__init__(pointer)
813

9-
class Mystreami(pyvips.Streamiu):
10-
def __init__(self, pointer):
11-
super(Mystreami, self).__init__(pointer)
14+
# these must be attached before we build the streamiu, see `new`
15+
self.signal_connect('read', self.read_cb)
16+
self.signal_connect('seek', self.seek_cb)
1217

13-
# these must be attached before we build the streamiu, see `new`
14-
self.signal_connect('read', self.read_cb)
15-
self.signal_connect('seek', self.seek_cb)
18+
@staticmethod
19+
def new(name, pipe_mode=False):
20+
"""Make a new input stream from a filename.
1621
17-
@staticmethod
18-
def new(name, pipe_mode=False):
19-
"""Make a new input stream from a filename.
22+
"""
2023

21-
"""
24+
gtype = pyvips.type_from_name('VipsStreamiu')
25+
pointer = pyvips.GObject.new_pointer_from_gtype(gtype)
26+
self = Mystreami(pointer)
2227

23-
gtype = pyvips.type_from_name('VipsStreamiu')
24-
pointer = pyvips.GObject.new_pointer_from_gtype(gtype)
25-
self = Mystreami(pointer)
28+
self.name = name
29+
self.pipe_mode = pipe_mode
30+
self.loaded_bytes = open(name, 'rb').read()
31+
self.memory = memoryview(self.loaded_bytes)
32+
self.length = len(self.loaded_bytes)
33+
self.read_point = 0
2634

27-
self.name = name
28-
self.pipe_mode = pipe_mode
29-
self.loaded_bytes = open(name, 'rb').read()
30-
self.memory = memoryview(self.loaded_bytes)
31-
self.length = len(self.loaded_bytes)
32-
self.read_point = 0
35+
return self.build()
3336

34-
return self.build()
37+
def read_cb(self, buf):
38+
# print('read: {0} bytes ...'.format(len(buf)))
39+
p = self.read_point
40+
bytes_available = self.length - p
41+
bytes_to_copy = min(bytes_available, len(buf))
42+
buf[:bytes_to_copy] = self.memory[p:p + bytes_to_copy]
43+
self.read_point += bytes_to_copy
44+
# print(' copied from position {0}'.format(p))
3545

36-
def read_cb(self, buf):
37-
# print('read: {0} bytes ...'.format(len(buf)))
38-
p = self.read_point
39-
bytes_available = self.length - p
40-
bytes_to_copy = min(bytes_available, len(buf))
41-
buf[:bytes_to_copy] = self.memory[p:p + bytes_to_copy]
42-
self.read_point += bytes_to_copy
43-
# print(' copied from position {0}'.format(p))
46+
return bytes_to_copy
4447

45-
return bytes_to_copy
48+
def seek_cb(self, offset, whence):
49+
# print('seek: offset = {0}, whence = {1} ...'
50+
# .format(offset, whence))
4651

47-
def seek_cb(self, offset, whence):
48-
# print('seek: offset = {0}, whence = {1} ...'.format(offset, whence))
52+
if self.pipe_mode:
53+
# print(' -1 (pipe mode)')
54+
return -1
4955

50-
if self.pipe_mode:
51-
# print(' -1 (pipe mode)')
52-
return -1
56+
if whence == 0:
57+
# SEEK_SET
58+
new_read_point = offset
59+
elif whence == 1:
60+
# SEEK_CUR
61+
new_read_point = self.read_point + offset
62+
elif whence == 2:
63+
# SEEK_END
64+
new_read_point = self.length + offset
65+
else:
66+
raise Exception('bad whence {0}'.format(whence))
5367

54-
if whence == 0:
55-
# SEEK_SET
56-
new_read_point = offset
57-
elif whence == 1:
58-
# SEEK_CUR
59-
new_read_point = self.read_point + offset
60-
elif whence == 2:
61-
# SEEK_END
62-
new_read_point = self.length + offset
63-
else:
64-
raise Exception('bad whence {0}'.format(whence))
68+
self.read_point = max(0, min(self.length, new_read_point))
69+
# print(' new read_point = {0}'.format(self.read_point))
6570

66-
self.read_point = max(0, min(self.length, new_read_point))
67-
# print(' new read_point = {0}'.format(self.read_point))
71+
return self.read_point
6872

69-
return self.read_point
7073

74+
class Mystreamo(pyvips.Streamou):
75+
def __init__(self, pointer):
76+
super(Mystreamo, self).__init__(pointer)
7177

72-
class Mystreamo(pyvips.Streamou):
73-
def __init__(self, pointer):
74-
super(Mystreamo, self).__init__(pointer)
78+
# these must be attached before we build the streamou, see `new`
79+
self.signal_connect('write', self.write_cb)
80+
self.signal_connect('finish', self.finish_cb)
7581

76-
# these must be attached before we build the streamou, see `new`
77-
self.signal_connect('write', self.write_cb)
78-
self.signal_connect('finish', self.finish_cb)
82+
@staticmethod
83+
def new(name):
84+
"""Make a new output stream from a filename.
7985
80-
@staticmethod
81-
def new(name):
82-
"""Make a new output stream from a filename.
86+
"""
8387

84-
"""
88+
gtype = pyvips.type_from_name('VipsStreamou')
89+
pointer = pyvips.GObject.new_pointer_from_gtype(gtype)
90+
self = Mystreamo(pointer)
8591

86-
gtype = pyvips.type_from_name('VipsStreamou')
87-
pointer = pyvips.GObject.new_pointer_from_gtype(gtype)
88-
self = Mystreamo(pointer)
92+
self.name = name
93+
self.f = open(name, 'wb')
8994

90-
self.name = name
91-
self.f = open(name, 'wb')
95+
return self.build()
9296

93-
return self.build()
97+
def write_cb(self, buf):
98+
# print('write: {0} bytes ...'.format(len(buf)))
99+
# py2 write does not return number of bytes written
100+
self.f.write(buf)
94101

95-
def write_cb(self, buf):
96-
# print('write: {0} bytes ...'.format(len(buf)))
97-
# py2 write does not return number of bytes written
98-
self.f.write(buf)
102+
return len(buf)
99103

100-
return len(buf)
104+
def finish_cb(self):
105+
# print('finish: ...')
106+
self.f.close()
101107

102-
def finish_cb(self):
103-
# print('finish: ...')
104-
self.f.close()
105108

106-
107-
class TestSignals:
109+
class TestStreams:
108110
@classmethod
109111
def setup_class(cls):
110112
cls.tempdir = tempfile.mkdtemp()
111113

112114
@skip_if_no('jpegload')
115+
@pytest.mark.skipif(not pyvips.at_least_libvips(8, 9),
116+
reason="requires libvips >= 8.9")
113117
def test_stream(self):
114118
streami = pyvips.Streami.new_from_file(JPEG_FILE)
115119
image = pyvips.Image.new_from_stream(streami, '', access='sequential')
@@ -123,6 +127,8 @@ def test_stream(self):
123127
assert abs(image - image2).abs().max() < 10
124128

125129
@skip_if_no('jpegload')
130+
@pytest.mark.skipif(not pyvips.at_least_libvips(8, 9),
131+
reason="requires libvips >= 8.9")
126132
def test_streamu(self):
127133
streamiu = Mystreami.new(JPEG_FILE)
128134
image = pyvips.Image.new_from_stream(streamiu, '', access='sequential')
@@ -137,6 +143,8 @@ def test_streamu(self):
137143
assert abs(image - image2).abs().max() < 10
138144

139145
@skip_if_no('jpegload')
146+
@pytest.mark.skipif(not pyvips.at_least_libvips(8, 9),
147+
reason="requires libvips >= 8.9")
140148
def test_streamu_pipe(self):
141149
streamiu = Mystreami.new(JPEG_FILE, True)
142150
image = pyvips.Image.new_from_stream(streamiu, '', access='sequential')

0 commit comments

Comments
 (0)
0