10000 Fix character encoding/decoding issue · libvips/pyvips@f7f2f6c · GitHub
[go: up one dir, main page]

Skip to content

Commit f7f2f6c

Browse files
committed
Fix character encoding/decoding issue
1 parent 59441dc commit f7f2f6c

File tree

7 files changed

+75
-61
lines changed

7 files changed

+75
-61
lines changed

pyvips/base.py

Lines changed: 30 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,13 @@
1919
logger.debug('Loaded lib {0}'.format(vips_lib))
2020
logger.debug('Loaded lib {0}'.format(gobject_lib))
2121

22+
is_PY3 = sys.version_info[0] == 3
23+
24+
if is_PY3:
25+
text_type = str
26+
else:
27+
text_type = unicode
28+
2229
# apparently the best way to find out
2330
is_64bits = sys.maxsize > 2 ** 32
2431

@@ -64,8 +71,8 @@ class Error(Exception):
6471
"""
6572
def __init__(self, message, detail = None):
6673
self.message = message
67-
if detail == None or detail == "":
68-
detail = ffi.string(vips_lib.vips_error_buffer()).decode('utf-8')
74+
if detail is None or detail == "":
75+
detail = to_string(ffi.string(vips_lib.vips_error_buffer()))
6976
vips_lib.vips_error_clear()
7077
self.detail = detail
7178

@@ -74,7 +81,11 @@ def __init__(self, message, detail = None):
7481
def __str__(self):
7582
return '{0}\n {1}'.format(self.message, self.detail)
7683

77-
if vips_lib.vips_init(bytes(sys.argv[0], 'utf-8')) != 0:
84+
argv = sys.argv[0]
85+
if isinstance(argv, text_type):
86+
argv = argv.encode()
87+
88+
if vips_lib.vips_init(argv) != 0:
7889
raise Error('unable to init Vips')
7990

8091
def shutdown():
@@ -87,18 +98,28 @@ def shutdown():
8798
def leak_set(leak):
8899
return vips_lib.vips_leak_set(leak)
89100

101+
def to_bytes(x):
102+
if isinstance(x, text_type):
103+
x = x.encode()
104+
return x
105+
106+
def to_string(x):
107+
if is_PY3 and isinstance(x, bytes):
108+
x = x.decode('utf-8')
109+
return x
110+
90111
def path_filename7(filename):
91-
return ffi.string(vips_lib.vips_path_filename7(filename.encode())).decode('utf-8')
112+
return to_string(ffi.string(vips_lib.vips_path_filename7(to_bytes(filename))))
92113

93114
def path_mode7(filename):
94-
return ffi.string(vips_lib.vips_path_mode7(filename.encode())).decode('utf-8')
115+
return to_string(ffi.string(vips_lib.vips_path_mode7(to_bytes(filename))))
95116

96117
def type_find(basename, nickname):
97-
return vips_lib.vips_type_find(basename.encode(), nickname.encode())
118+
return vips_lib.vips_type_find(to_bytes(basename), to_bytes(nickname))
98119

99120
def type_name(gtype):
100-
return ffi.string(gobject_lib.g_type_name(gtype)).decode('utf-8')
121+
return to_string(ffi.string(gobject_lib.g_type_name(gtype)))
101122

102-
__all__ = ['ffi', 'vips_lib', 'gobject_lib', 'Error', 'leak_set',
103-
'type_find', 'type_name',
123+
__all__ = ['ffi', 'vips_lib', 'gobject_lib', 'Error', 'leak_set',
124+
'to_bytes', 'to_string', 'type_find', 'type_name',
104125
'path_filename7', 'path_mode7', 'shutdown']

pyvips/gvalue.py

Lines changed: 18 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -62,25 +62,22 @@
6262
6363
''')
6464

65-
def type_from_name(name):
66-
return gobject_lib.g_type_from_name(name.encode())
67-
6865
class GValue(object):
6966

7067
# look up some common gtypes at init for speed
71-
gbool_type = type_from_name('gboolean')
72-
gint_type = type_from_name('gint')
73-
gdouble_type = type_from_name('gdouble')
74-
gstr_type = type_from_name('gchararray')
75-
genum_type = type_from_name('GEnum')
76-
gflags_type = type_from_name('GFlags')
77-
gobject_type = type_from_name('GObject')
78-
image_type = type_from_name('VipsImage')
79-
array_int_type = type_from_name('VipsArrayInt')
80-
array_double_type = type_from_name('VipsArrayDouble')
81-
array_image_type = type_from_name('VipsArrayImage')
82-
refstr_type = type_from_name('VipsRefString')
83-
blob_type = type_from_name('VipsBlob')
68+
gbool_type = gobject_lib.g_type_from_name(b'gboolean')
69+
gint_type = gobject_lib.g_type_from_name(b'gint')
70+
gdouble_type = gobject_lib.g_type_from_name(b'gdouble')
71+
gstr_type = gobject_lib.g_type_from_name(b'gchararray')
72+
genum_type = gobject_lib.g_type_from_name(b'GEnum')
73+
gflags_type = gobject_lib.g_type_from_name(b'GFlags')
74+
gobject_type = gobject_lib.g_type_from_name(b'GObject')
75+
image_type = gobject_lib.g_type_from_name(b'VipsImage')
76+
array_int_type = gobject_lib.g_type_from_name(b'VipsArrayInt')
77+
array_double_type = gobject_lib.g_type_from_name(b'VipsArrayDouble')
78+
array_image_type = gobject_lib.g_type_from_name(b'VipsArrayImage')
79+
refstr_type = gobject_lib.g_type_from_name(b'VipsRefString')
80+
blob_type = gobject_lib.g_type_from_name(b'VipsBlob')
8481

8582
def __init__(self):
8683
# allocate memory for the gvalue which will be freed on GC
@@ -108,7 +105,7 @@ def set(self, value):
108105
gobject_lib.g_value_set_double(self.gvalue, value)
109106
elif fundamental == GValue.genum_type:
110107
if isinstance(value, basestring if _is_PY2 else str):
111-
enum_value = vips_lib.vips_enum_from_nick('pyvips'.encode(), gtype, value.encode())
108+
enum_value = vips_lib.vips_enum_from_nick(b'pyvips', gtype, to_bytes(value))
112109

113110
if enum_value < 0:
114111
raise Error('no such enum {0}')
@@ -119,10 +116,7 @@ def set(self, value):
119116
elif fundamental == GValue.gflags_type:
120117
gobject_lib.g_value_set_flags(self.gvalue, value)
121118
elif gtype == GValue.gstr_type or gtype == GValue.refstr_type:
122-
if isinstance(value, basestring if _is_PY2 else str):
123-
value = value.encode()
124-
125-
gobject_lib.g_value_set_string(self.gvalue, value)
119+
gobject_lib.g_value_set_string(self.gvalue, to_bytes(value))
126120
elif fundamental == GValue.gobject_type:
127121
gobject_lib.g_value_set_object(self.gvalue, value.pointer)
128122
elif gtype == GValue.array_int_type:
@@ -178,19 +172,19 @@ def get(self):
178172
if cstr == 0:
179173
raise Error('value not in enum')
180174

181-
result = ffi.string(cstr).decode('utf-8')
175+
result = to_string(ffi.string(cstr))
182176
elif fundamental == GValue.gflags_type:
183177
result = gobject_lib.g_value_get_flags(self.gvalue)
184178
elif gtype == GValue.gstr_type:
185179
cstr = gobject_lib.g_value_get_string(self.gvalue)
186180

187181
if cstr != ffi.NULL:
188-
result = ffi.string(cstr).decode('utf-8')
182+
result = to_string(ffi.string(cstr))
189183
elif gtype == GValue.refstr_type:
190184
psize = ffi.new('size_t *')
191185
cstr = vips_lib.vips_value_get_ref_string(self.gvalue, psize)
192186

193-
result = ffi.string(cstr, psize[0]).decode('utf-8')
187+
result = to_string(ffi.string(cstr, psize[0]))
194188
elif gtype == GValue.image_type:
195189
# g_value_get_object() will not add a ref ... that is
196190
# held by the gvalue

pyvips/tests/test_gvalue.py

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,6 @@
33
from .helpers import *
44

55
class TestGValue(PyvipsTester):
6-
def type_from_name(self, name):
7-
return pyvips.gobject_lib.g_type_from_name(name.encode())
8-
96
def test_bool(self):
107
gv = pyvips.GValue()
118
gv.init(pyvips.GValue.gbool_type)
@@ -35,7 +32,8 @@ def test_enum(self):
3532
# the Interpretation enum is created when the first image is made --
3633
# make it ourselves in case we are run before the first image
3734
pyvips.vips_lib.vips_interpretation_get_type()
38-
interpretation_gtype = self.type_from_name('VipsInterpretation')
35+
interpretation_gtype = pyvips.gobject_lib. \
36+
g_type_from_name(b'VipsInterpretation')
3937
gv = pyvips.GValue()
4038
gv.init(interpretation_gtype)
4139
gv.set('xyz')
@@ -46,7 +44,8 @@ def test_flags(self):
4644
# the OperationFlags enum is created when the first op is made --
4745
# make it ourselves in case we are run before that
4846
pyvips.vips_lib.vips_operation_flags_get_type()
49-
operationflags_gtype = self.type_from_name('VipsOperationFlags')
47+
operationflags_gtype = pyvips.gobject_lib. \
48+
g_type_from_name(b'VipsOperationFlags')
5049
gv = pyvips.GValue()
5150
gv.init(operationflags_gtype)
5251
gv.set(12)

pyvips/vimage.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -152,23 +152,23 @@ def __init__(self, pointer):
152152

153153
@staticmethod
154154
def new_from_file(vips_filename, **kwargs):
155-
vips_filename = vips_filename.encode()
155+
vips_filename = to_bytes(vips_filename)
156156
filename = vips_lib.vips_filename_get_filename(vips_filename)
157157
options = vips_lib.vips_filename_get_options(vips_filename)
158158
name = vips_lib.vips_foreign_find_load(filename)
159159
if name == ffi.NULL:
160160
raise Error('unable to load from file {0}'.format(vips_filename))
161161

162-
return Operation.call(ffi.string(name).decode('utf-8'), ffi.string(filename).decode('utf-8'),
163-
string_options = ffi.string(options).decode('utf-8'), **kwargs)
162+
return Operation.call(to_string(ffi.string(name)), to_string(ffi.string(filename)),
163+
string_options = to_string(ffi.string(options)), **kwargs)
164164

165165
@staticmethod
166166
def new_from_buffer(data, options, **kwargs):
167167
name = vips_lib.vips_foreign_find_load_buffer(data, len(data))
168168
if name == ffi.NULL:
169169
raise Error('unable to load from buffer')
170170

171-
return Operation.call(ffi.string(name).decode('utf-8'), data,
171+
return Operation.call(to_string(ffi.string(name)), data,
172172
string_options = options, **kwargs)
173173

174174
@staticmethod
@@ -197,7 +197,7 @@ def new_from_array(array, scale = 1.0, offset = 0.0):
197197

198198
@staticmethod
199199
def new_temp_file(format):
200-
vi = vips_lib.vips_image_new_temp_file(format.encode())
200+
vi = vips_lib.vips_image_new_temp_file(to_bytes(format))
201201
if vi == ffi.NULL:
202202
raise Error('unable to make temp file')
203203

@@ -225,25 +225,25 @@ def copy_memory(self):
225225
# writers
226226

227227
def write_to_file(self, vips_filename, **kwargs):
228-
vips_filename = vips_filename.encode()
228+
vips_filename = to_bytes(vips_filename)
229229
filename = vips_lib.vips_filename_get_filename(vips_filename)
230230
options = vips_lib.vips_filename_get_options(vips_filename)
231231
name = vips_lib.vips_foreign_find_save(filename)
232232
if name == ffi.NULL:
233233
raise Error('unable to write to file {0}'.format(vips_filename))
234234

235-
return Operation.call(ffi.string(name).decode('utf-8'), self, filename,
236-
string_options = ffi.string(options).decode('utf-8'), **kwargs)
235+
return Operation.call(to_string(ffi.string(name)), self, filename,
236+
string_options = to_string(ffi.string(options)), **kwargs)
237237

238238
def write_to_buffer(self, format_string, **kwargs):
239-
format_string = format_string.encode()
239+
format_string = to_bytes(format_string)
240240
options = vips_lib.vips_filename_get_options(format_string)
241241
name = vips_lib.vips_foreign_find_save_buffer(format_string)
242242
if name == ffi.NULL:
243243
raise Error('unable to write to buffer')
244244

245-
return Operation.call(ffi.string(name).decode('utf-8'), self,
246-
string_options = ffi.string(options).decode('utf-8'), **kwargs)
245+
return Operation.call(to_string(ffi.string(name)), self,
246+
string_options = to_string(ffi.string(options)), **kwargs)
247247

248248
def write(self, other):
249249
result = vips_lib.vips_image_write(self.pointer, other.pointer)
@@ -253,11 +253,11 @@ def write(self, other):
253253
# get/set metadata
254254

255255
def get_typeof(self, name):
256-
return vips_lib.vips_image_get_typeof(self.pointer, name.encode())
256+
return vips_lib.vips_image_get_typeof(self.pointer, to_bytes(name))
257257

258258
def get(self, name):
259259
gv = GValue()
260-
result = vips_lib.vips_image_get(self.pointer, name.encode(), gv.pointer)
260+
result = vips_lib.vips_image_get(self.pointer, to_bytes(name), gv.pointer)
261261
if result != 0:
262262
raise Error('unable to get {0}'.format(name))
263263

@@ -267,14 +267,14 @@ def set_type(self, gtype, name, value):
267267
gv = GValue()
268268
gv.init(gtype)
269269
gv.set(value)
270-
vips_lib.vips_image_set(self.pointer, name.encode(), gv.pointer)
270+
vips_lib.vips_image_set(self.pointer, to_bytes(name), gv.pointer)
271271

272272
def set(self, name, value):
273273
gtype = self.get_typeof(name)
274274
self.set_type(gtype, name, value)
275275

276276
def remove(self, name):
277-
return vips_lib.vips_image_remove(self.pointer, name.encode()) != 0
277+
return vips_lib.vips_image_remove(self.pointer, to_bytes(name)) != 0
278278

279279
def __getattr__(self, name):
280280
# logger.debug('Image.__getattr__ {0}'.format(name))

pyvips/vinterpolate.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@ def __init__(self, pointer):
2929
def new(name):
3030
# logger.debug('VipsInterpolate.new: name = {0}'.format(name))
3131

32-
vi = vips_lib.vips_interpolate_new(name.encode())
32+
vi = vips_lib.vips_interpolate_new(to_bytes(name))
3333
if vi == ffi.NULL:
3434
raise Error('no such interpolator {0}'.format(name))
3535

pyvips/vobject.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -88,7 +88,7 @@ def get_typeof(self, name):
8888
argument_class = ffi.new('VipsArgumentClass **')
8989
argument_instance = ffi.new('VipsArgumentInstance **')
9090
vo = ffi.cast('VipsObject *', self.pointer)
91-
result = vips_lib.vips_object_get_argument(vo, name.encode(),
91+
result = vips_lib.vips_object_get_argument(vo, to_bytes(name),
9292
pspec, argument_class, argument_instance)
9393

9494
if result != 0:
@@ -106,7 +106,7 @@ def get(self, name):
106106
gv = GValue()
107107
gv.init(gtype)
108108
go = ffi.cast('GObject *', self.pointer)
109-
gobject_lib.g_object_get_property(go, name.encode(), gv.pointer)
109+
gobject_lib.g_object_get_property(go, to_bytes(name), gv.pointer)
110110

111111
return gv.get()
112112

@@ -120,11 +120,11 @@ def set(self, name, value):
120120
gv.init(gtype)
121121
gv.set(value)
122122
go = ffi.cast('GObject *', self.pointer)
123-
gobject_lib.g_object_set_property(go, name.encode(), gv.pointer)
123+
gobject_lib.g_object_set_property(go, to_bytes(name), gv.pointer)
124124

125125
# set a series of options using a string, perhaps 'fred=12, tile'
126126
def set_string(self, string_options):
127127
vo = ffi.cast('VipsObject *', self.pointer)
128-
return vips_lib.vips_object_set_from_string(vo, string_options) == 0
128+
return vips_lib.vips_object_set_from_string(vo, to_bytes(string_options)) == 0
129129

130130
__all__ = ['VipsObject']

pyvips/voperation.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ def getargs(self):
9191
def add_construct(self, pspec, argument_class, argument_instance, a, b):
9292
flags = argument_class.flags
9393
if (flags & _CONSTRUCT) != 0:
94-
name = ffi.string(pspec.name).decode('utf-8')
94+
name = to_string(ffi.string(pspec.name))
9595

9696
# libvips uses '-' to separate parts of arg names, but we
9797
# need '_' for Python
@@ -121,7 +121,7 @@ def call(operation_name, *args, **kwargs):
121121
logger.debug('VipsOperation.call: string_options = {0}'.
122122
format(string_options))
123123

124-
vop = vips_lib.vips_operation_new(operation_name.encode())
124+
vop = vips_lib.vips_operation_new(to_bytes(operation_name))
125125
if vop == ffi.NULL:
126126
raise Error('no such operation {0}'.format(operation_name))
127127
op = Operation(vop)
@@ -159,7 +159,7 @@ def call(operation_name, *args, **kwargs):
159159

160160
# set any string options before any args so they can't be
161161
# overridden
162-
if not op.set_string(string_options.encode()):
162+
if not op.set_string(string_options):
163163
raise Error('unable to call {0}'.format(operation_name))
164164

165165
# set required and optional args

0 commit comments

Comments
 (0)
0