Merge lp:~jelmer/pygpgme/bug452194 into lp:~launchpad-pqm/pygpgme/devel

Proposed by Jelmer Vernooij
Status: Merged
Merged at revision: not available
Proposed branch: lp:~jelmer/pygpgme/bug452194
Merge into: lp:~launchpad-pqm/pygpgme/devel
Diff against target: 1868 lines (+544/-303)
24 files modified
Makefile (+1/-1)
gpgme/__init__.py (+1/-1)
gpgme/tests/test_context.py (+20/-0)
gpgme/tests/test_delete.py (+0/-1)
gpgme/tests/test_editkey.py (+5/-2)
gpgme/tests/test_encrypt_decrypt.py (+38/-16)
gpgme/tests/test_export.py (+7/-4)
gpgme/tests/test_genkey.py (+7/-4)
gpgme/tests/test_import.py (+8/-5)
gpgme/tests/test_passphrase.py (+8/-5)
gpgme/tests/test_progress.py (+6/-3)
gpgme/tests/test_sign_verify.py (+27/-24)
setup.py (+12/-8)
src/gpgme.c (+40/-6)
src/pycompat.h (+49/-0)
src/pygpgme-context.c (+148/-118)
src/pygpgme-data.c (+17/-9)
src/pygpgme-error.c (+48/-20)
src/pygpgme-genkey.c (+6/-6)
src/pygpgme-import.c (+26/-20)
src/pygpgme-key.c (+36/-22)
src/pygpgme-keyiter.c (+1/-2)
src/pygpgme-signature.c (+31/-26)
src/pygpgme.h (+2/-0)
To merge this branch: bzr merge lp:~jelmer/pygpgme/bug452194
Reviewer Review Type Date Requested Status
Michael Hudson-Doyle (community) Approve
James Henstridge Pending
Review via email: mp+21636@code.launchpad.net

Commit message

Initialize GPGME properly by calling gpgme_check_version().

Description of the change

This adds a call to gpgme_check_version() to PyGPGME. Without this, all functions in PyGPGME modules built against newer versions of GPGME fail with GPG_ERR_NOT_OPERATIONAL.

To post a comment you must log in.
Revision history for this message
Jelmer Vernooij (jelmer) wrote :

This patch also pulls in the last few fixes from James on trunk.

Revision history for this message
Michael Hudson-Doyle (mwhudson) wrote :

I think this looks reasonable, but I sure hope our tests find any incompatibilities the trunk changes have brought :-)

review: Approve

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'Makefile'
2--- Makefile 2008-10-16 12:06:10 +0000
3+++ Makefile 2010-03-25 00:48:28 +0000
4@@ -1,4 +1,4 @@
5-PYTHON = python2.4
6+PYTHON = python
7
8 build:
9 $(PYTHON) setup.py build_ext -i
10
11=== modified file 'gpgme/__init__.py'
12--- gpgme/__init__.py 2006-02-14 04:11:33 +0000
13+++ gpgme/__init__.py 2010-03-25 00:48:28 +0000
14@@ -15,7 +15,7 @@
15 # License along with this library; if not, write to the Free Software
16 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
17
18-from _gpgme import *
19+from gpgme._gpgme import *
20
21 # create constants
22 make_constants(globals())
23
24=== modified file 'gpgme/tests/test_context.py'
25--- gpgme/tests/test_context.py 2006-10-16 08:22:31 +0000
26+++ gpgme/tests/test_context.py 2010-03-25 00:48:28 +0000
27@@ -15,6 +15,7 @@
28 # License along with this library; if not, write to the Free Software
29 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30
31+import os
32 import unittest
33
34 import gpgme
35@@ -119,6 +120,25 @@
36 del ctx.progress_cb
37 self.assertEqual(ctx.progress_cb, None)
38
39+ def test_set_engine_info(self):
40+ # Add a key using the default $GNUPGHOME based keyring.
41+ ctx = gpgme.Context()
42+ ctx.import_(self.keyfile('key1.pub'))
43+
44+ # If we set $GNUPGHOME to a dummy value, we can't read in the
45+ # keywe just loaded.
46+ os.environ['GNUPGHOME'] = '/no/such/dir'
47+ ctx = gpgme.Context()
48+ self.assertRaises(gpgme.GpgmeError, ctx.get_key,
49+ 'E79A842DA34A1CA383F64A1546BB55F0885C65A4')
50+
51+ # But if we configure the context using set_engine_info(), it
52+ # will find the key.
53+ ctx = gpgme.Context()
54+ ctx.set_engine_info(gpgme.PROTOCOL_OpenPGP, None, self._gpghome)
55+ key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
56+ self.assertTrue(key)
57+
58
59 def test_suite():
60 loader = unittest.TestLoader()
61
62=== modified file 'gpgme/tests/test_delete.py'
63--- gpgme/tests/test_delete.py 2006-02-14 04:11:33 +0000
64+++ gpgme/tests/test_delete.py 2010-03-25 00:48:28 +0000
65@@ -16,7 +16,6 @@
66 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
67
68 import unittest
69-import StringIO
70
71 import gpgme
72 from gpgme.tests.util import GpgHomeTestCase
73
74=== modified file 'gpgme/tests/test_editkey.py'
75--- gpgme/tests/test_editkey.py 2006-02-14 04:11:33 +0000
76+++ gpgme/tests/test_editkey.py 2010-03-25 00:48:28 +0000
77@@ -17,7 +17,10 @@
78
79 import unittest
80 import os
81-import StringIO
82+try:
83+ from io import BytesIO
84+except ImportError:
85+ from StringIO import StringIO as BytesIO
86
87 import gpgme
88 import gpgme.editutil
89@@ -38,7 +41,7 @@
90 def test_edit_quit(self):
91 ctx = gpgme.Context()
92 key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
93- output = StringIO.StringIO()
94+ output = BytesIO()
95
96 self.status = None
97 self.args = None
98
99=== modified file 'gpgme/tests/test_encrypt_decrypt.py'
100--- gpgme/tests/test_encrypt_decrypt.py 2006-02-14 04:11:33 +0000
101+++ gpgme/tests/test_encrypt_decrypt.py 2010-03-25 00:48:28 +0000
102@@ -15,8 +15,12 @@
103 # License along with this library; if not, write to the Free Software
104 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
105
106+import os
107 import unittest
108-import StringIO
109+try:
110+ from io import BytesIO
111+except ImportError:
112+ from StringIO import StringIO as BytesIO
113 from textwrap import dedent
114
115 import gpgme
116@@ -28,7 +32,7 @@
117 'signonly.pub', 'signonly.sec']
118
119 def test_decrypt(self):
120- ciphertext = StringIO.StringIO(dedent('''
121+ ciphertext = BytesIO(dedent('''
122 -----BEGIN PGP MESSAGE-----
123 Version: GnuPG v1.4.1 (GNU/Linux)
124
125@@ -48,13 +52,13 @@
126 =1s5N
127 -----END PGP MESSAGE-----
128 '''))
129- plaintext = StringIO.StringIO()
130+ plaintext = BytesIO()
131 ctx = gpgme.Context()
132 ctx.decrypt(ciphertext, plaintext)
133 self.assertEqual(plaintext.getvalue(), 'hello world\n')
134
135 def test_decrypt_verify(self):
136- ciphertext = StringIO.StringIO(dedent('''
137+ ciphertext = BytesIO(dedent('''
138 -----BEGIN PGP MESSAGE-----
139 Version: GnuPG v1.4.1 (GNU/Linux)
140
141@@ -76,7 +80,7 @@
142 =fl3U
143 -----END PGP MESSAGE-----
144 '''))
145- plaintext = StringIO.StringIO()
146+ plaintext = BytesIO()
147 ctx = gpgme.Context()
148 sigs = ctx.decrypt_verify(ciphertext, plaintext)
149 self.assertEqual(plaintext.getvalue(), 'hello world\n')
150@@ -93,8 +97,8 @@
151 self.assertEqual(sigs[0].validity_reason, None)
152
153 def test_encrypt(self):
154- plaintext = StringIO.StringIO('Hello World\n')
155- ciphertext = StringIO.StringIO()
156+ plaintext = BytesIO('Hello World\n')
157+ ciphertext = BytesIO()
158 ctx = gpgme.Context()
159 recipient = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
160 ctx.encrypt([recipient], gpgme.ENCRYPT_ALWAYS_TRUST,
161@@ -102,13 +106,13 @@
162
163 # rewind ciphertext buffer, and try to decrypt:
164 ciphertext.seek(0)
165- plaintext = StringIO.StringIO()
166+ plaintext = BytesIO()
167 ctx.decrypt(ciphertext, plaintext)
168 self.assertEqual(plaintext.getvalue(), 'Hello World\n')
169
170 def test_encrypt_armor(self):
171- plaintext = StringIO.StringIO('Hello World\n')
172- ciphertext = StringIO.StringIO()
173+ plaintext = BytesIO('Hello World\n')
174+ ciphertext = BytesIO()
175 ctx = gpgme.Context()
176 ctx.armor = True
177 recipient = ctx.get_key('93C2240D6B8AA10AB28F701D2CF46B7FC97E6B0F')
178@@ -117,13 +121,31 @@
179
180 # rewind ciphertext buffer, and try to decrypt:
181 ciphertext.seek(0)
182- plaintext = StringIO.StringIO()
183+ plaintext = BytesIO()
184+ ctx.decrypt(ciphertext, plaintext)
185+ self.assertEqual(plaintext.getvalue(), 'Hello World\n')
186+
187+ def test_encrypt_symmetric(self):
188+ plaintext = BytesIO('Hello World\n')
189+ ciphertext = BytesIO()
190+ def passphrase(uid_hint, passphrase_info, prev_was_bad, fd):
191+ os.write(fd, 'Symmetric passphrase\n')
192+ ctx = gpgme.Context()
193+ ctx.armor = True
194+ ctx.passphrase_cb = passphrase
195+ ctx.encrypt(None, 0, plaintext, ciphertext)
196+ self.assertTrue(
197+ ciphertext.getvalue().startswith('-----BEGIN PGP MESSAGE-----'))
198+
199+ # Rewind ciphertext buffer and try to decrypt it:
200+ ciphertext.seek(0)
201+ plaintext = BytesIO()
202 ctx.decrypt(ciphertext, plaintext)
203 self.assertEqual(plaintext.getvalue(), 'Hello World\n')
204
205 def test_encrypt_sign(self):
206- plaintext = StringIO.StringIO('Hello World\n')
207- ciphertext = StringIO.StringIO()
208+ plaintext = BytesIO('Hello World\n')
209+ ciphertext = BytesIO()
210 ctx = gpgme.Context()
211 ctx.armor = True
212 signer = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
213@@ -139,7 +161,7 @@
214
215 # rewind ciphertext buffer, and try to decrypt:
216 ciphertext.seek(0)
217- plaintext = StringIO.StringIO()
218+ plaintext = BytesIO()
219 sigs = ctx.decrypt_verify(ciphertext, plaintext)
220 self.assertEqual(plaintext.getvalue(), 'Hello World\n')
221 self.assertEqual(len(sigs), 1)
222@@ -152,8 +174,8 @@
223 self.assertEqual(sigs[0].validity_reason, None)
224
225 def test_encrypt_to_signonly(self):
226- plaintext = StringIO.StringIO('Hello World\n')
227- ciphertext = StringIO.StringIO()
228+ plaintext = BytesIO('Hello World\n')
229+ ciphertext = BytesIO()
230 ctx = gpgme.Context()
231 recipient = ctx.get_key('15E7CE9BF1771A4ABC550B31F540A569CB935A42')
232 try:
233
234=== modified file 'gpgme/tests/test_export.py'
235--- gpgme/tests/test_export.py 2006-02-14 04:11:33 +0000
236+++ gpgme/tests/test_export.py 2010-03-25 00:48:28 +0000
237@@ -16,7 +16,10 @@
238 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
239
240 import unittest
241-import StringIO
242+try:
243+ from io import BytesIO
244+except ImportError:
245+ from StringIO import StringIO as BytesIO
246 from textwrap import dedent
247
248 import gpgme
249@@ -29,7 +32,7 @@
250 def test_export_by_fingerprint(self):
251 ctx = gpgme.Context()
252 ctx.armor = True
253- keydata = StringIO.StringIO()
254+ keydata = BytesIO()
255 ctx.export('15E7CE9BF1771A4ABC550B31F540A569CB935A42', keydata)
256
257 self.assertTrue(keydata.getvalue().startswith(
258@@ -38,7 +41,7 @@
259 def test_export_by_email(self):
260 ctx = gpgme.Context()
261 ctx.armor = True
262- keydata = StringIO.StringIO()
263+ keydata = BytesIO()
264 ctx.export('signonly@example.org', keydata)
265
266 self.assertTrue(keydata.getvalue().startswith(
267@@ -47,7 +50,7 @@
268 def test_export_by_name(self):
269 ctx = gpgme.Context()
270 ctx.armor = True
271- keydata = StringIO.StringIO()
272+ keydata = BytesIO()
273 ctx.export('Sign Only', keydata)
274
275 self.assertTrue(keydata.getvalue().startswith(
276
277=== modified file 'gpgme/tests/test_genkey.py'
278--- gpgme/tests/test_genkey.py 2008-10-16 07:44:55 +0000
279+++ gpgme/tests/test_genkey.py 2010-03-25 00:48:28 +0000
280@@ -16,7 +16,10 @@
281 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
282
283 import unittest
284-import StringIO
285+try:
286+ from io import BytesIO
287+except ImportError:
288+ from StringIO import StringIO as BytesIO
289
290 import gpgme
291 from gpgme.tests.util import GpgHomeTestCase
292@@ -47,8 +50,8 @@
293 ctx = gpgme.Context()
294 ctx.signers = [key]
295
296- plaintext = StringIO.StringIO('Hello World\n')
297- signature = StringIO.StringIO()
298+ plaintext = BytesIO('Hello World\n')
299+ signature = BytesIO()
300
301 ctx.armor = True
302 new_sigs = ctx.sign(
303@@ -61,7 +64,7 @@
304 self.assertEqual(len(sigs), 1)
305 self.assertEqual(sigs[0].fpr, key.subkeys[0].fpr)
306
307- def test_generate_signing_only_keys(self):
308+ def _test_generate_signing_only_keys(self):
309 ctx = gpgme.Context()
310 result = ctx.genkey(signing_only_param)
311
312
313=== modified file 'gpgme/tests/test_import.py'
314--- gpgme/tests/test_import.py 2006-02-14 04:11:33 +0000
315+++ gpgme/tests/test_import.py 2010-03-25 00:48:28 +0000
316@@ -16,7 +16,10 @@
317 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
318
319 import unittest
320-import StringIO
321+try:
322+ from io import BytesIO
323+except ImportError:
324+ from StringIO import StringIO as BytesIO
325
326 import gpgme
327 from gpgme.tests.util import GpgHomeTestCase
328@@ -79,7 +82,7 @@
329 key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4', True)
330
331 def test_import_stringio(self):
332- fp = StringIO.StringIO(self.keyfile('key1.pub').read())
333+ fp = BytesIO(self.keyfile('key1.pub').read())
334 ctx = gpgme.Context()
335 result = ctx.import_(fp)
336 self.assertEqual(len(result.imports), 1)
337@@ -93,7 +96,7 @@
338 keys = '\n'.join([self.keyfile('key1.pub').read(),
339 self.keyfile('key1.sec').read(),
340 self.keyfile('key2.pub').read()])
341- fp = StringIO.StringIO(keys)
342+ fp = BytesIO(keys)
343 ctx = gpgme.Context()
344 result = ctx.import_(fp)
345 self.assertEqual(result.considered, 3)
346@@ -130,7 +133,7 @@
347 key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4', True)
348
349 def test_import_empty(self):
350- fp = StringIO.StringIO('')
351+ fp = BytesIO('')
352 ctx = gpgme.Context()
353 result = ctx.import_(fp)
354 self.assertEqual(result.considered, 0)
355@@ -143,7 +146,7 @@
356
357 fp = self.keyfile('key1.pub')
358 result = ctx.import_(fp)
359-
360+
361 self.assertEqual(result.considered, 1)
362 self.assertEqual(result.no_user_id, 0)
363 self.assertEqual(result.imported, 0)
364
365=== modified file 'gpgme/tests/test_passphrase.py'
366--- gpgme/tests/test_passphrase.py 2006-02-14 04:11:33 +0000
367+++ gpgme/tests/test_passphrase.py 2010-03-25 00:48:28 +0000
368@@ -17,7 +17,10 @@
369
370 import unittest
371 import os
372-import StringIO
373+try:
374+ from io import BytesIO
375+except ImportError:
376+ from StringIO import StringIO as BytesIO
377 from textwrap import dedent
378
379 import gpgme
380@@ -31,8 +34,8 @@
381 ctx = gpgme.Context()
382 key = ctx.get_key('EFB052B4230BBBC51914BCBB54DCBBC8DBFB9EB3')
383 ctx.signers = [key]
384- plaintext = StringIO.StringIO('Hello World\n')
385- signature = StringIO.StringIO()
386+ plaintext = BytesIO('Hello World\n')
387+ signature = BytesIO()
388
389 try:
390 new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_CLEAR)
391@@ -53,8 +56,8 @@
392 key = ctx.get_key('EFB052B4230BBBC51914BCBB54DCBBC8DBFB9EB3')
393 ctx.signers = [key]
394 ctx.passphrase_cb = self.passphrase_cb
395- plaintext = StringIO.StringIO('Hello World\n')
396- signature = StringIO.StringIO()
397+ plaintext = BytesIO('Hello World\n')
398+ signature = BytesIO()
399
400 self.uid_hint = None
401 self.passphrase_info = None
402
403=== modified file 'gpgme/tests/test_progress.py'
404--- gpgme/tests/test_progress.py 2006-02-14 04:11:33 +0000
405+++ gpgme/tests/test_progress.py 2010-03-25 00:48:28 +0000
406@@ -17,7 +17,10 @@
407
408 import unittest
409 import os
410-import StringIO
411+try:
412+ from io import BytesIO
413+except ImportError:
414+ from StringIO import StringIO as BytesIO
415 from textwrap import dedent
416
417 import gpgme
418@@ -35,8 +38,8 @@
419 key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
420 ctx.signers = [key]
421 ctx.progress_cb = self.progress_cb
422- plaintext = StringIO.StringIO('Hello World\n')
423- signature = StringIO.StringIO()
424+ plaintext = BytesIO('Hello World\n')
425+ signature = BytesIO()
426
427 self.progress_cb_called = False
428 new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_CLEAR)
429
430=== modified file 'gpgme/tests/test_sign_verify.py'
431--- gpgme/tests/test_sign_verify.py 2007-04-10 02:34:52 +0000
432+++ gpgme/tests/test_sign_verify.py 2010-03-25 00:48:28 +0000
433@@ -16,7 +16,10 @@
434 # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
435
436 import unittest
437-import StringIO
438+try:
439+ from io import BytesIO
440+except ImportError:
441+ from StringIO import StringIO as BytesIO
442 from textwrap import dedent
443
444 import gpgme
445@@ -28,7 +31,7 @@
446 'signonly.pub', 'signonly.sec']
447
448 def test_verify_normal(self):
449- signature = StringIO.StringIO(dedent('''
450+ signature = BytesIO(dedent('''
451 -----BEGIN PGP MESSAGE-----
452 Version: GnuPG v1.4.1 (GNU/Linux)
453
454@@ -38,7 +41,7 @@
455 =HCW0
456 -----END PGP MESSAGE-----
457 '''))
458- plaintext = StringIO.StringIO()
459+ plaintext = BytesIO()
460 ctx = gpgme.Context()
461 sigs = ctx.verify(signature, None, plaintext)
462
463@@ -56,7 +59,7 @@
464 self.assertEqual(sigs[0].validity_reason, None)
465
466 def test_verify_detached(self):
467- signature = StringIO.StringIO(dedent('''
468+ signature = BytesIO(dedent('''
469 -----BEGIN PGP SIGNATURE-----
470 Version: GnuPG v1.4.1 (GNU/Linux)
471
472@@ -65,7 +68,7 @@
473 =dyZS
474 -----END PGP SIGNATURE-----
475 '''))
476- signed_text = StringIO.StringIO('Hello World\n')
477+ signed_text = BytesIO('Hello World\n')
478 ctx = gpgme.Context()
479 sigs = ctx.verify(signature, signed_text, None)
480
481@@ -82,7 +85,7 @@
482 self.assertEqual(sigs[0].validity_reason, None)
483
484 def test_verify_clearsign(self):
485- signature = StringIO.StringIO(dedent('''
486+ signature = BytesIO(dedent('''
487 -----BEGIN PGP SIGNED MESSAGE-----
488 Hash: SHA1
489
490@@ -95,7 +98,7 @@
491 =kZ2c
492 -----END PGP SIGNATURE-----
493 '''))
494- plaintext = StringIO.StringIO()
495+ plaintext = BytesIO()
496 ctx = gpgme.Context()
497 sigs = ctx.verify(signature, None, plaintext)
498
499@@ -113,7 +116,7 @@
500 self.assertEqual(sigs[0].validity_reason, None)
501
502 def test_verify_multiple_sigs(self):
503- signature = StringIO.StringIO(dedent('''
504+ signature = BytesIO(dedent('''
505 -----BEGIN PGP SIGNED MESSAGE-----
506 Hash: SHA1
507
508@@ -137,7 +140,7 @@
509 =0A7N
510 -----END PGP SIGNATURE-----
511 '''))
512- plaintext = StringIO.StringIO()
513+ plaintext = BytesIO()
514 ctx = gpgme.Context()
515 sigs = ctx.verify(signature, None, plaintext)
516
517@@ -166,7 +169,7 @@
518 self.assertEqual(sigs[1].validity_reason, None)
519
520 def test_verify_no_signature(self):
521- signature = StringIO.StringIO(dedent('''
522+ signature = BytesIO(dedent('''
523 -----BEGIN PGP SIGNED MESSAGE-----
524 Hash: SHA1
525
526@@ -174,7 +177,7 @@
527 -----BEGIN PGP SIGNATURE-----
528 -----END PGP SIGNATURE-----
529 '''))
530- plaintext = StringIO.StringIO()
531+ plaintext = BytesIO()
532 ctx = gpgme.Context()
533 sigs = ctx.verify(signature, None, plaintext)
534
535@@ -182,7 +185,7 @@
536 self.assertEqual(len(sigs), 0)
537
538 def test_verify_bad_signature(self):
539- signature = StringIO.StringIO(dedent('''
540+ signature = BytesIO(dedent('''
541 -----BEGIN PGP SIGNED MESSAGE-----
542 Hash: SHA1
543
544@@ -193,7 +196,7 @@
545 iNhhNHx+gzGBUqtIK5LpENTCGgCfV3aO
546 -----END PGP SIGNATURE-----
547 '''))
548- plaintext = StringIO.StringIO()
549+ plaintext = BytesIO()
550 ctx = gpgme.Context()
551 try:
552 ctx.verify(signature, None, plaintext)
553@@ -208,8 +211,8 @@
554 ctx.armor = False
555 key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
556 ctx.signers = [key]
557- plaintext = StringIO.StringIO('Hello World\n')
558- signature = StringIO.StringIO()
559+ plaintext = BytesIO('Hello World\n')
560+ signature = BytesIO()
561
562 new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_NORMAL)
563 self.assertEqual(len(new_sigs), 1)
564@@ -219,7 +222,7 @@
565
566 # now verify the signature
567 signature.seek(0)
568- plaintext = StringIO.StringIO()
569+ plaintext = BytesIO()
570 sigs = ctx.verify(signature, None, plaintext)
571 self.assertEqual(plaintext.getvalue(), 'Hello World\n')
572 self.assertEqual(len(sigs), 1)
573@@ -236,8 +239,8 @@
574 ctx.armor = True
575 key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
576 ctx.signers = [key]
577- plaintext = StringIO.StringIO('Hello World\n')
578- signature = StringIO.StringIO()
579+ plaintext = BytesIO('Hello World\n')
580+ signature = BytesIO()
581
582 new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_NORMAL)
583 self.assertEqual(len(new_sigs), 1)
584@@ -247,7 +250,7 @@
585
586 # now verify the signature
587 signature.seek(0)
588- plaintext = StringIO.StringIO()
589+ plaintext = BytesIO()
590 sigs = ctx.verify(signature, None, plaintext)
591 self.assertEqual(plaintext.getvalue(), 'Hello World\n')
592 self.assertEqual(len(sigs), 1)
593@@ -264,8 +267,8 @@
594 ctx.armor = True
595 key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
596 ctx.signers = [key]
597- plaintext = StringIO.StringIO('Hello World\n')
598- signature = StringIO.StringIO()
599+ plaintext = BytesIO('Hello World\n')
600+ signature = BytesIO()
601
602 new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_DETACH)
603 self.assertEqual(len(new_sigs), 1)
604@@ -291,8 +294,8 @@
605 ctx.armor = True
606 key = ctx.get_key('E79A842DA34A1CA383F64A1546BB55F0885C65A4')
607 ctx.signers = [key]
608- plaintext = StringIO.StringIO('Hello World\n')
609- signature = StringIO.StringIO()
610+ plaintext = BytesIO('Hello World\n')
611+ signature = BytesIO()
612
613 new_sigs = ctx.sign(plaintext, signature, gpgme.SIG_MODE_CLEAR)
614 self.assertEqual(len(new_sigs), 1)
615@@ -302,7 +305,7 @@
616
617 # now verify the signature
618 signature.seek(0)
619- plaintext = StringIO.StringIO()
620+ plaintext = BytesIO()
621 sigs = ctx.verify(signature, None, plaintext)
622 self.assertEqual(plaintext.getvalue(), 'Hello World\n')
623 self.assertEqual(len(sigs), 1)
624
625=== modified file 'setup.py'
626--- setup.py 2008-10-15 21:36:35 +0000
627+++ setup.py 2010-03-25 00:48:28 +0000
628@@ -1,4 +1,11 @@
629 #!/usr/bin/env python
630+"""A Python module for working with OpenPGP messages
631+
632+PyGPGME is a Python module that lets you sign, verify, encrypt and
633+decrypt messages using the OpenPGP format.
634+
635+It is built on top of the GNU Privacy Guard and the GPGME library.
636+"""
637
638 from distutils.core import setup, Extension
639
640@@ -17,17 +24,14 @@
641 ],
642 libraries=['gpgme'])
643
644+description, long_description = __doc__.split("\n\n", 1)
645+
646 setup(name='pygpgme',
647 version='0.1',
648 author='James Henstridge',
649 author_email='james@jamesh.id.au',
650- description='A Python module for working with OpenPGP messages',
651- long_description='''
652- PyGPGME is a Python module that lets you sign, verify, encrypt
653- and decrypt messages using the OpenPGP format.
654-
655- It is built on top of the GNU Privacy Guard and the GPGME
656- library.''',
657+ description=description,
658+ long_description=long_description,
659 license='LGPL',
660 classifiers=[
661 'Intended Audience :: Developers',
662@@ -38,7 +42,7 @@
663 'Topic :: Security :: Cryptography',
664 'Topic :: Software Development :: Libraries :: Python Modules'
665 ],
666- url='https://launchpad.net/products/pygpgme',
667+ url='https://launchpad.net/pygpgme',
668 ext_modules=[gpgme],
669 packages=['gpgme', 'gpgme.tests'],
670 package_data={'gpgme.tests': ['keys/*.pub', 'keys/*.sec']})
671
672=== modified file 'src/gpgme.c'
673--- src/gpgme.c 2008-10-15 21:36:35 +0000
674+++ src/gpgme.c 2010-03-25 00:48:28 +0000
675@@ -26,23 +26,33 @@
676 { NULL, NULL, 0 }
677 };
678
679-PyMODINIT_FUNC
680-init_gpgme(void)
681+#if PY_VERSION_HEX >= 0x03000000
682+static PyModuleDef pygpgme_module = {
683+ PyModuleDef_HEAD_INIT,
684+ "gpgme._gpgme",
685+ .m_size = -1,
686+ .m_methods = pygpgme_functions
687+};
688+#endif
689+
690+static PyObject *
691+create_module(void)
692 {
693+ const char *gpgme_version;
694 PyObject *mod;
695
696 pygpgme_error = PyErr_NewException("gpgme.GpgmeError",
697 PyExc_RuntimeError, NULL);
698
699 #define INIT_TYPE(type) \
700- if (!type.ob_type) \
701- type.ob_type = &PyType_Type; \
702+ if (!Py_TYPE(&type)) \
703+ Py_TYPE(&type) = &PyType_Type; \
704 if (!type.tp_alloc) \
705 type.tp_alloc = PyType_GenericAlloc; \
706 if (!type.tp_new) \
707 type.tp_new = PyType_GenericNew; \
708 if (PyType_Ready(&type) < 0) \
709- return
710+ return NULL
711
712 #define ADD_TYPE(type) \
713 Py_INCREF(&PyGpgme ## type ## _Type); \
714@@ -59,7 +69,11 @@
715 INIT_TYPE(PyGpgmeGenkeyResult_Type);
716 INIT_TYPE(PyGpgmeKeyIter_Type);
717
718+#if PY_VERSION_HEX >= 0x03000000
719+ mod = PyModule_Create(&pygpgme_module);
720+#else
721 mod = Py_InitModule("gpgme._gpgme", pygpgme_functions);
722+#endif
723
724 ADD_TYPE(Context);
725 ADD_TYPE(Key);
726@@ -74,4 +88,24 @@
727
728 Py_INCREF(pygpgme_error);
729 PyModule_AddObject(mod, "GpgmeError", pygpgme_error);
730-}
731+
732+ gpgme_version = gpgme_check_version(NULL);
733+ PyModule_AddObject(mod, "GPGME_VERSION",
734+ PyString_FromString(gpgme_version));
735+
736+ return mod;
737+}
738+
739+#if PY_VERSION_HEX >= 0x03000000
740+PyMODINIT_FUNC
741+PyInit__gpgme(void)
742+{
743+ return create_module();
744+}
745+#else
746+PyMODINIT_FUNC
747+init_gpgme(void)
748+{
749+ create_module();
750+}
751+#endif
752
753=== added file 'src/pycompat.h'
754--- src/pycompat.h 1970-01-01 00:00:00 +0000
755+++ src/pycompat.h 2010-03-25 00:48:28 +0000
756@@ -0,0 +1,49 @@
757+
758+#ifndef PYGPGME_COMPAT_H
759+#define PYGPGME_COMPAT_H
760+
761+#if PY_VERSION_HEX < 0x02060000
762+
763+# define PyVarObject_HEAD_INIT(type, size) \
764+ PyObject_HEAD_INIT(type) size,
765+# define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
766+
767+
768+# define PyBytesObject PyStringObject
769+# define PyBytes_Type PyString_Type
770+
771+# define PyBytes_Check PyString_Check
772+# define PyBytes_CheckExact PyString_CheckExact
773+# define PyBytes_CHECK_INTERNED PyString_CHECK_INTERNED
774+# define PyBytes_AS_STRING PyString_AS_STRING
775+# define PyBytes_GET_SIZE PyString_GET_SIZE
776+# define Py_TPFLAGS_BYTES_SUBCLASS Py_TPFLAGS_STRING_SUBCLASS
777+
778+# define PyBytes_FromStringAndSize PyString_FromStringAndSize
779+# define PyBytes_FromString PyString_FromString
780+# define PyBytes_FromFormatV PyString_FromFormatV
781+# define PyBytes_FromFormat PyString_FromFormat
782+# define PyBytes_Size PyString_Size
783+# define PyBytes_AsString PyString_AsString
784+# define PyBytes_Repr PyString_Repr
785+# define PyBytes_Concat PyString_Concat
786+# define PyBytes_ConcatAndDel PyString_ConcatAndDel
787+# define PyBytes_Format PyString_Format
788+# define PyBytes_DecodeEscape PyString_DecodeEscape
789+# define PyBytes_Decode PyString_Decode
790+# define PyBytes_Encode PyString_Encode
791+# define PyBytes_AsEncodedObject PyString_AsEncodedObject
792+# define PyBytes_AsEncodedString PyString_AsEncodedString
793+# define PyBytes_AsDecodedObject PyString_AsDecodedObject
794+# define PyBytes_AsDecodedString PyString_AsDecodedString
795+# define PyBytes_AsStringAndSize PyString_AsStringAndSize
796+
797+#endif
798+
799+#if PY_VERSION_HEX > 0x03000000
800+/* Ugh. I'll need to fix this code, but the text/bytes changes take
801+ precedence. */
802+# include <intobject.h>
803+#endif
804+
805+#endif /* PYGPGME_COMPAT_H */
806
807=== modified file 'src/pygpgme-context.c'
808--- src/pygpgme-context.c 2008-10-16 07:44:55 +0000
809+++ src/pygpgme-context.c 2010-03-25 00:48:28 +0000
810@@ -356,7 +356,22 @@
811 { NULL, (getter)0, (setter)0 }
812 };
813
814-/* XXX: set_locale */
815+static PyObject *
816+pygpgme_context_set_engine_info(PyGpgmeContext *self, PyObject *args)
817+{
818+ int protocol;
819+ const char *file_name, *home_dir;
820+
821+ if (!PyArg_ParseTuple(args, "izz", &protocol, &file_name, &home_dir))
822+ return NULL;
823+
824+ if (pygpgme_check_error(gpgme_ctx_set_engine_info(self->ctx, protocol,
825+ file_name, home_dir)))
826+ return NULL;
827+
828+ Py_RETURN_NONE;
829+}
830+
831 static PyObject *
832 pygpgme_context_set_locale(PyGpgmeContext *self, PyObject *args)
833 {
834@@ -372,11 +387,6 @@
835 Py_RETURN_NONE;
836 }
837
838-/* the following don't seem to be used */
839-/* XXX: signers_clear */
840-/* XXX: signers_add */
841-/* XXX: signers_enum */
842-
843 static PyObject *
844 pygpgme_context_get_key(PyGpgmeContext *self, PyObject *args)
845 {
846@@ -424,10 +434,17 @@
847
848 list = PyList_New(0);
849 for (key = res->invalid_recipients; key != NULL; key = key->next) {
850- PyObject *item, *err;
851+ PyObject *item, *py_fpr, *err;
852
853+ if (key->fpr)
854+ py_fpr = PyUnicode_DecodeASCII(key->fpr, strlen(key->fpr),
855+ "replace");
856+ else {
857+ py_fpr = Py_None;
858+ Py_INCREF(py_fpr);
859+ }
860 err = pygpgme_error_object(key->reason);
861- item = Py_BuildValue("(zN)", key->fpr, err);
862+ item = Py_BuildValue("(NN)", py_fpr, err);
863 PyList_Append(list, item);
864 Py_DECREF(item);
865 }
866@@ -442,121 +459,107 @@
867 static PyObject *
868 pygpgme_context_encrypt(PyGpgmeContext *self, PyObject *args)
869 {
870- PyObject *py_recp, *py_plain, *py_cipher;
871+ PyObject *py_recp, *py_plain, *py_cipher, *recp_seq = NULL, *result = NULL;
872 int flags, i, length;
873- gpgme_key_t *recp;
874- gpgme_data_t plain, cipher;
875+ gpgme_key_t *recp = NULL;
876+ gpgme_data_t plain = NULL, cipher = NULL;
877 gpgme_error_t err;
878
879 if (!PyArg_ParseTuple(args, "OiOO", &py_recp, &flags,
880 &py_plain, &py_cipher))
881- return NULL;
882-
883- py_recp = PySequence_Fast(py_recp, "first argument must be a sequence");
884- if (py_recp == NULL)
885- return NULL;
886-
887- length = PySequence_Fast_GET_SIZE(py_recp);
888- recp = malloc((length + 1) * sizeof (gpgme_key_t));
889- for (i = 0; i < length; i++) {
890- PyObject *item = PySequence_Fast_GET_ITEM(py_recp, i);
891-
892- if (!PyObject_TypeCheck(item, &PyGpgmeKey_Type)) {
893- free(recp);
894- Py_DECREF(py_recp);
895- PyErr_SetString(PyExc_TypeError, "items in first argument must "
896- "be gpgme.Key objects");
897- return NULL;
898+ goto end;
899+
900+ if (py_recp != Py_None) {
901+ recp_seq = PySequence_Fast(py_recp, "first argument must be a "
902+ "sequence or None");
903+ if (recp_seq == NULL)
904+ goto end;
905+
906+ length = PySequence_Fast_GET_SIZE(recp_seq);
907+ recp = malloc((length + 1) * sizeof (gpgme_key_t));
908+ for (i = 0; i < length; i++) {
909+ PyObject *item = PySequence_Fast_GET_ITEM(recp_seq, i);
910+
911+ if (!PyObject_TypeCheck(item, &PyGpgmeKey_Type)) {
912+ PyErr_SetString(PyExc_TypeError, "items in first argument "
913+ "must be gpgme.Key objects");
914+ goto end;
915+ }
916+ recp[i] = ((PyGpgmeKey *)item)->key;
917 }
918- recp[i] = ((PyGpgmeKey *)item)->key;
919- }
920- recp[i] = NULL;
921-
922- if (pygpgme_data_new(&plain, py_plain)) {
923- free(recp);
924- Py_DECREF(py_recp);
925- return NULL;
926- }
927- if (pygpgme_data_new(&cipher, py_cipher)) {
928- free(recp);
929- Py_DECREF(py_recp);
930- gpgme_data_release(plain);
931- return NULL;
932- }
933-
934- Py_BEGIN_ALLOW_THREADS;
935- err = gpgme_op_encrypt(self->ctx, recp, flags, plain, cipher);
936+ recp[i] = NULL;
937+ }
938+
939+ if (pygpgme_data_new(&plain, py_plain))
940+ goto end;
941+ if (pygpgme_data_new(&cipher, py_cipher))
942+ goto end;
943+
944+ Py_BEGIN_ALLOW_THREADS; err = gpgme_op_encrypt(self->ctx, recp, flags, plain, cipher);
945 Py_END_ALLOW_THREADS;
946
947- free(recp);
948- Py_DECREF(py_recp);
949- gpgme_data_release(plain);
950- gpgme_data_release(cipher);
951-
952 if (pygpgme_check_error(err)) {
953 decode_encrypt_result(self);
954- return NULL;
955+ goto end;
956 }
957
958- Py_RETURN_NONE;
959+ Py_INCREF(Py_None);
960+ result = Py_None;
961+
962+ end:
963+ if (recp != NULL)
964+ free(recp);
965+ Py_XDECREF(recp_seq);
966+ if (plain != NULL)
967+ gpgme_data_release(plain);
968+ if (cipher != NULL)
969+ gpgme_data_release(cipher);
970+
971+ return result;
972 }
973
974 static PyObject *
975 pygpgme_context_encrypt_sign(PyGpgmeContext *self, PyObject *args)
976 {
977- PyObject *py_recp, *py_plain, *py_cipher;
978+ PyObject *py_recp, *py_plain, *py_cipher, *recp_seq = NULL, *result = NULL;
979 int flags, i, length;
980- gpgme_key_t *recp;
981- gpgme_data_t plain, cipher;
982+ gpgme_key_t *recp = NULL;
983+ gpgme_data_t plain = NULL, cipher = NULL;
984 gpgme_error_t err;
985- gpgme_sign_result_t result;
986+ gpgme_sign_result_t sign_result;
987
988 if (!PyArg_ParseTuple(args, "OiOO", &py_recp, &flags,
989 &py_plain, &py_cipher))
990- return NULL;
991-
992- py_recp = PySequence_Fast(py_recp, "first argument must be a sequence");
993- if (py_recp == NULL)
994- return NULL;
995-
996- length = PySequence_Fast_GET_SIZE(py_recp);
997+ goto end;
998+
999+ recp_seq = PySequence_Fast(py_recp, "first argument must be a sequence");
1000+ if (recp_seq == NULL)
1001+ goto end;
1002+
1003+ length = PySequence_Fast_GET_SIZE(recp_seq);
1004 recp = malloc((length + 1) * sizeof (gpgme_key_t));
1005 for (i = 0; i < length; i++) {
1006- PyObject *item = PySequence_Fast_GET_ITEM(py_recp, i);
1007+ PyObject *item = PySequence_Fast_GET_ITEM(recp_seq, i);
1008
1009 if (!PyObject_TypeCheck(item, &PyGpgmeKey_Type)) {
1010- free(recp);
1011- Py_DECREF(py_recp);
1012- PyErr_SetString(PyExc_TypeError, "items in first argument must "
1013- "be gpgme.Key objects");
1014- return NULL;
1015+ PyErr_SetString(PyExc_TypeError, "items in first argument "
1016+ "must be gpgme.Key objects");
1017+ goto end;
1018 }
1019 recp[i] = ((PyGpgmeKey *)item)->key;
1020 }
1021 recp[i] = NULL;
1022
1023- if (pygpgme_data_new(&plain, py_plain)) {
1024- free(recp);
1025- Py_DECREF(py_recp);
1026- return NULL;
1027- }
1028- if (pygpgme_data_new(&cipher, py_cipher)) {
1029- free(recp);
1030- Py_DECREF(py_recp);
1031- gpgme_data_release(plain);
1032- return NULL;
1033- }
1034+ if (pygpgme_data_new(&plain, py_plain))
1035+ goto end;
1036+ if (pygpgme_data_new(&cipher, py_cipher))
1037+ goto end;
1038
1039 Py_BEGIN_ALLOW_THREADS;
1040 err = gpgme_op_encrypt_sign(self->ctx, recp, flags, plain, cipher);
1041 Py_END_ALLOW_THREADS;
1042
1043- free(recp);
1044- Py_DECREF(py_recp);
1045- gpgme_data_release(plain);
1046- gpgme_data_release(cipher);
1047-
1048- result = gpgme_op_sign_result(self->ctx);
1049+ sign_result = gpgme_op_sign_result(self->ctx);
1050
1051 /* annotate exception */
1052 if (pygpgme_check_error(err)) {
1053@@ -569,36 +572,54 @@
1054 PyErr_Fetch(&err_type, &err_value, &err_traceback);
1055 PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
1056
1057- if (result == NULL)
1058- goto end;
1059+ if (sign_result == NULL)
1060+ goto error_end;
1061
1062 if (!PyErr_GivenExceptionMatches(err_type, pygpgme_error))
1063- goto end;
1064+ goto error_end;
1065
1066 list = PyList_New(0);
1067- for (key = result->invalid_signers; key != NULL; key = key->next) {
1068- PyObject *item, *err;
1069+ for (key = sign_result->invalid_signers; key != NULL; key = key->next) {
1070+ PyObject *item, *py_fpr, *err;
1071
1072+ if (key->fpr)
1073+ py_fpr = PyUnicode_DecodeASCII(key->fpr, strlen(key->fpr),
1074+ "replace");
1075+ else {
1076+ py_fpr = Py_None;
1077+ Py_INCREF(py_fpr);
1078+ }
1079 err = pygpgme_error_object(key->reason);
1080- item = Py_BuildValue("(zN)", key->fpr, err);
1081+ item = Py_BuildValue("(NN)", py_fpr, err);
1082 PyList_Append(list, item);
1083 Py_DECREF(item);
1084 }
1085 PyObject_SetAttrString(err_value, "invalid_signers", list);
1086 Py_DECREF(list);
1087
1088- list = pygpgme_newsiglist_new(result->signatures);
1089+ list = pygpgme_newsiglist_new(sign_result->signatures);
1090 PyObject_SetAttrString(err_value, "signatures", list);
1091 Py_DECREF(list);
1092- end:
1093+ error_end:
1094 PyErr_Restore(err_type, err_value, err_traceback);
1095- return NULL;
1096+ goto end;
1097 }
1098
1099- if (result)
1100- return pygpgme_newsiglist_new(result->signatures);
1101+ if (sign_result)
1102+ result = pygpgme_newsiglist_new(sign_result->signatures);
1103 else
1104- return PyList_New(0);
1105+ result = PyList_New(0);
1106+
1107+ end:
1108+ if (recp != NULL)
1109+ free(recp);
1110+ Py_XDECREF(recp_seq);
1111+ if (plain != NULL)
1112+ gpgme_data_release(plain);
1113+ if (cipher != NULL)
1114+ gpgme_data_release(cipher);
1115+
1116+ return result;
1117 }
1118
1119 static void
1120@@ -619,7 +640,9 @@
1121 goto end;
1122
1123 if (res->unsupported_algorithm) {
1124- value = PyString_FromString(res->unsupported_algorithm);
1125+ value = PyUnicode_DecodeUTF8(res->unsupported_algorithm,
1126+ strlen(res->unsupported_algorithm),
1127+ "replace");
1128 } else {
1129 Py_INCREF(Py_None);
1130 value = Py_None;
1131@@ -655,7 +678,7 @@
1132
1133 if (pygpgme_data_new(&plain, py_plain)) {
1134 gpgme_data_release(cipher);
1135- return NULL;
1136+ return NULL;
1137 }
1138
1139 Py_BEGIN_ALLOW_THREADS;
1140@@ -690,7 +713,7 @@
1141
1142 if (pygpgme_data_new(&plain, py_plain)) {
1143 gpgme_data_release(cipher);
1144- return NULL;
1145+ return NULL;
1146 }
1147
1148 Py_BEGIN_ALLOW_THREADS;
1149@@ -748,11 +771,11 @@
1150 return NULL;
1151
1152 if (pygpgme_data_new(&plain, py_plain))
1153- return NULL;
1154+ return NULL;
1155
1156 if (pygpgme_data_new(&sig, py_sig)) {
1157 gpgme_data_release(plain);
1158- return NULL;
1159+ return NULL;
1160 }
1161
1162 Py_BEGIN_ALLOW_THREADS;
1163@@ -781,10 +804,17 @@
1164
1165 list = PyList_New(0);
1166 for (key = result->invalid_signers; key != NULL; key = key->next) {
1167- PyObject *item, *err;
1168+ PyObject *item, *py_fpr, *err;
1169
1170+ if (key->fpr)
1171+ py_fpr = PyUnicode_DecodeASCII(key->fpr, strlen(key->fpr),
1172+ "replace");
1173+ else {
1174+ py_fpr = Py_None;
1175+ Py_INCREF(py_fpr);
1176+ }
1177 err = pygpgme_error_object(key->reason);
1178- item = Py_BuildValue("(zN)", key->fpr, err);
1179+ item = Py_BuildValue("(NN)", py_fpr, err);
1180 PyList_Append(list, item);
1181 Py_DECREF(item);
1182 }
1183@@ -822,12 +852,12 @@
1184 }
1185 if (pygpgme_data_new(&signed_text, py_signed_text)) {
1186 gpgme_data_release(sig);
1187- return NULL;
1188+ return NULL;
1189 }
1190 if (pygpgme_data_new(&plaintext, py_plaintext)) {
1191 gpgme_data_release(sig);
1192 gpgme_data_release(signed_text);
1193- return NULL;
1194+ return NULL;
1195 }
1196
1197 Py_BEGIN_ALLOW_THREADS;
1198@@ -924,9 +954,9 @@
1199 Py_INCREF(py_pattern);
1200 pattern = NULL;
1201 patterns = NULL;
1202- } else if (PyString_Check(py_pattern)) {
1203+ } else if (PyBytes_Check(py_pattern)) {
1204 Py_INCREF(py_pattern);
1205- pattern = PyString_AsString(py_pattern);
1206+ pattern = PyBytes_AsString(py_pattern);
1207 patterns = NULL;
1208 } else {
1209 py_pattern = PySequence_Fast(py_pattern,
1210@@ -939,14 +969,14 @@
1211 for (i = 0; i < length; i++) {
1212 PyObject *item = PySequence_Fast_GET_ITEM(py_pattern, i);
1213
1214- if (!PyString_Check(item)) {
1215+ if (!PyBytes_Check(item)) {
1216 PyErr_SetString(PyExc_TypeError,
1217 "first argument must be a string or sequence of strings");
1218 free(patterns);
1219 Py_DECREF(py_pattern);
1220 return NULL;
1221 }
1222- patterns[i] = PyString_AsString(item);
1223+ patterns[i] = PyBytes_AsString(item);
1224 }
1225 patterns[i] = NULL;
1226 }
1227@@ -1131,9 +1161,9 @@
1228 Py_INCREF(py_pattern);
1229 pattern = NULL;
1230 patterns = NULL;
1231- } else if (PyString_Check(py_pattern)) {
1232+ } else if (PyBytes_Check(py_pattern)) {
1233 Py_INCREF(py_pattern);
1234- pattern = PyString_AsString(py_pattern);
1235+ pattern = PyBytes_AsString(py_pattern);
1236 patterns = NULL;
1237 } else {
1238 py_pattern = PySequence_Fast(py_pattern,
1239@@ -1146,14 +1176,14 @@
1240 for (i = 0; i < length; i++) {
1241 PyObject *item = PySequence_Fast_GET_ITEM(py_pattern, i);
1242
1243- if (!PyString_Check(item)) {
1244+ if (!PyBytes_Check(item)) {
1245 PyErr_SetString(PyExc_TypeError,
1246 "first argument must be a string or sequence of strings");
1247 free(patterns);
1248 Py_DECREF(py_pattern);
1249 return NULL;
1250 }
1251- patterns[i] = PyString_AsString(item);
1252+ patterns[i] = PyBytes_AsString(item);
1253 }
1254 patterns[i] = NULL;
1255 }
1256@@ -1184,6 +1214,7 @@
1257 // pygpgme_context_trustlist
1258
1259 static PyMethodDef pygpgme_context_methods[] = {
1260+ { "set_engine_info", (PyCFunction)pygpgme_context_set_engine_info, METH_VARARGS },
1261 { "set_locale", (PyCFunction)pygpgme_context_set_locale, METH_VARARGS },
1262 { "get_key", (PyCFunction)pygpgme_context_get_key, METH_VARARGS },
1263 { "encrypt", (PyCFunction)pygpgme_context_encrypt, METH_VARARGS },
1264@@ -1204,8 +1235,7 @@
1265 };
1266
1267 PyTypeObject PyGpgmeContext_Type = {
1268- PyObject_HEAD_INIT(NULL)
1269- 0,
1270+ PyVarObject_HEAD_INIT(NULL, 0)
1271 "gpgme.Context",
1272 sizeof(PyGpgmeContext),
1273 .tp_flags = Py_TPFLAGS_DEFAULT,
1274
1275=== modified file 'src/pygpgme-data.c'
1276--- src/pygpgme-data.c 2006-02-14 04:07:06 +0000
1277+++ src/pygpgme-data.c 2010-03-25 00:48:28 +0000
1278@@ -65,17 +65,17 @@
1279 goto end;
1280 }
1281 /* if we don't have a string return value, consider that an error too */
1282- if (!PyString_Check(result)) {
1283+ if (!PyBytes_Check(result)) {
1284 Py_DECREF(result);
1285 errno = EINVAL;
1286 result_size = -1;
1287 goto end;
1288 }
1289 /* copy the result into the given buffer */
1290- result_size = PyString_Size(result);
1291+ result_size = PyBytes_Size(result);
1292 if (result_size > size)
1293 result_size = size;
1294- memcpy(buffer, PyString_AsString(result), result_size);
1295+ memcpy(buffer, PyBytes_AsString(result), result_size);
1296 Py_DECREF(result);
1297 end:
1298 PyGILState_Release(state);
1299@@ -87,19 +87,25 @@
1300 {
1301 PyGILState_STATE state;
1302 PyObject *fp = handle;
1303- PyObject *result;
1304- ssize_t bytes_written = 0;
1305+ PyObject *py_buffer = NULL;
1306+ PyObject *result = NULL;
1307+ ssize_t bytes_written = -1;
1308
1309 state = PyGILState_Ensure();
1310- result = PyObject_CallMethod(fp, "write", "s#", buffer, (int)size);
1311+ py_buffer = PyBytes_FromStringAndSize(buffer, size);
1312+ if (py_buffer == NULL) {
1313+ set_errno();
1314+ goto end;
1315+ }
1316+ result = PyObject_CallMethod(fp, "write", "O", py_buffer);
1317 if (result == NULL) {
1318 set_errno();
1319- bytes_written = -1;
1320 goto end;
1321 }
1322- Py_DECREF(result);
1323 bytes_written = size;
1324 end:
1325+ Py_XDECREF(result);
1326+ Py_XDECREF(py_buffer);
1327 PyGILState_Release(state);
1328 return bytes_written;
1329 }
1330@@ -171,8 +177,10 @@
1331
1332 error = gpgme_data_new_from_cbs(dh, &python_data_cbs, fp);
1333
1334- if (pygpgme_check_error(error))
1335+ if (pygpgme_check_error(error)) {
1336+ *dh = NULL;
1337 return -1;
1338+ }
1339
1340 /* if no error, then the new gpgme_data_t object owns a reference to
1341 * the python object */
1342
1343=== modified file 'src/pygpgme-error.c'
1344--- src/pygpgme-error.c 2006-02-14 04:07:06 +0000
1345+++ src/pygpgme-error.c 2010-03-25 00:48:28 +0000
1346@@ -26,34 +26,62 @@
1347 pygpgme_error_object(gpgme_error_t err)
1348 {
1349 char buf[256] = { '\0' };
1350- PyObject *exc, *attr;
1351+ PyObject *exc = NULL, *source = NULL, *code = NULL, *strerror = NULL;
1352
1353 if (err == GPG_ERR_NO_ERROR)
1354 Py_RETURN_NONE;
1355
1356+ if (!(source = PyInt_FromLong(gpgme_err_source(err))))
1357+ goto end;
1358+
1359+ if (!(code = PyInt_FromLong(gpgme_err_code(err))))
1360+ goto end;
1361+
1362 /* get the error string */
1363- if (gpgme_strerror_r(err, buf, 255) != 0)
1364+ if (gpgme_strerror_r(err, buf, sizeof(buf) - 1) != 0)
1365 strcpy(buf, "Unknown");
1366+ if (!(strerror = PyUnicode_DecodeUTF8(buf, strlen(buf), "replace")))
1367+ goto end;
1368
1369- exc = PyObject_CallFunction(pygpgme_error, "lls",
1370- (long)gpgme_err_source(err),
1371- (long)gpgme_err_code(err),
1372- buf);
1373+ exc = PyObject_CallFunction(pygpgme_error, "OOO", source, code, strerror);
1374 if (!exc)
1375- return NULL;
1376+ goto end;
1377+
1378 /* set the source and code as attributes of the exception object: */
1379- attr = PyInt_FromLong(gpgme_err_source(err));
1380- PyObject_SetAttrString(exc, "source", attr);
1381- Py_DECREF(attr);
1382-
1383- attr = PyInt_FromLong(gpgme_err_code(err));
1384- PyObject_SetAttrString(exc, "code", attr);
1385- Py_DECREF(attr);
1386-
1387- attr = PyString_FromString(buf);
1388- PyObject_SetAttrString(exc, "message", attr);
1389- Py_DECREF(attr);
1390-
1391+ PyObject_SetAttrString(exc, "source", source);
1392+ PyObject_SetAttrString(exc, "code", code);
1393+ PyObject_SetAttrString(exc, "strerror", strerror);
1394+
1395+ /* pygpgme 0.1 set the "message" attribute on exceptions, but
1396+ * Python 2.6 classes this exception attribute as deprecated (even
1397+ * though we weren't using it in the deprecated fashion).
1398+ *
1399+ * We now set the "strerror" attribute for this information, which
1400+ * is similar to IOError/OSError.
1401+ *
1402+ * For backward compatibility, we still set "message" on Python
1403+ * versions before 3.0. The hack below is to avoid issuing a
1404+ * deprecation warning.
1405+ */
1406+#if PY_VERSION_HEX < 0x03000000
1407+# if PY_VERSION_HEX >= 0x02060000
1408+ {
1409+ PyBaseExceptionObject *base_exc = (PyBaseExceptionObject *)exc;
1410+ PyObject *old_message = base_exc->message;
1411+
1412+ Py_INCREF(strerror);
1413+ base_exc->message = strerror;
1414+ Py_XDECREF(old_message);
1415+ }
1416+# else
1417+ PyObject_SetAttrString(exc, "message", strerror);
1418+# endif
1419+#endif
1420+
1421+ end:
1422+ Py_XDECREF(strerror);
1423+ Py_XDECREF(code);
1424+ Py_XDECREF(source);
1425 return exc;
1426 }
1427
1428@@ -98,7 +126,7 @@
1429 source = PyTuple_GetItem(args, 0);
1430 if (source == NULL)
1431 goto end;
1432-
1433+
1434 if (PyErr_GivenExceptionMatches(err_type, pygpgme_error)) {
1435 code = PyTuple_GetItem(args, 1);
1436 if (code == NULL)
1437
1438=== modified file 'src/pygpgme-genkey.c'
1439--- src/pygpgme-genkey.c 2008-10-16 07:44:55 +0000
1440+++ src/pygpgme-genkey.c 2010-03-25 00:48:28 +0000
1441@@ -30,15 +30,14 @@
1442 }
1443
1444 static PyMemberDef pygpgme_genkey_result_members[] = {
1445- { "primary", T_OBJECT, offsetof(PyGpgmeGenkeyResult, primary), RO},
1446- { "sub", T_OBJECT, offsetof(PyGpgmeGenkeyResult, sub), RO},
1447- { "fpr", T_OBJECT, offsetof(PyGpgmeGenkeyResult, fpr), RO},
1448+ { "primary", T_OBJECT, offsetof(PyGpgmeGenkeyResult, primary), READONLY},
1449+ { "sub", T_OBJECT, offsetof(PyGpgmeGenkeyResult, sub), READONLY},
1450+ { "fpr", T_OBJECT, offsetof(PyGpgmeGenkeyResult, fpr), READONLY},
1451 { NULL, 0, 0, 0}
1452 };
1453
1454 PyTypeObject PyGpgmeGenkeyResult_Type = {
1455- PyObject_HEAD_INIT(NULL)
1456- 0,
1457+ PyVarObject_HEAD_INIT(NULL, 0)
1458 "gpgme.GenkeyResult",
1459 sizeof(PyGpgmeGenkeyResult),
1460 .tp_flags = Py_TPFLAGS_DEFAULT,
1461@@ -65,7 +64,8 @@
1462 self->primary = PyBool_FromLong(result->primary);
1463 self->sub = PyBool_FromLong(result->sub);
1464 if (result->fpr)
1465- self->fpr = PyString_FromString(result->fpr);
1466+ self->fpr = PyUnicode_DecodeASCII(result->fpr, strlen(result->fpr),
1467+ "replace");
1468 else {
1469 Py_INCREF(Py_None);
1470 self->fpr = Py_None;
1471
1472=== modified file 'src/pygpgme-import.c'
1473--- src/pygpgme-import.c 2006-02-14 04:07:06 +0000
1474+++ src/pygpgme-import.c 2010-03-25 00:48:28 +0000
1475@@ -42,33 +42,32 @@
1476 }
1477
1478 static PyMemberDef pygpgme_import_members[] = {
1479- { "considered", T_OBJECT, offsetof(PyGpgmeImportResult, considered), RO},
1480- { "no_user_id", T_OBJECT, offsetof(PyGpgmeImportResult, no_user_id), RO},
1481- { "imported", T_OBJECT, offsetof(PyGpgmeImportResult, imported), RO},
1482- { "imported_rsa", T_OBJECT, offsetof(PyGpgmeImportResult, imported_rsa), RO},
1483- { "unchanged", T_OBJECT, offsetof(PyGpgmeImportResult, unchanged), RO},
1484- { "new_user_ids", T_OBJECT, offsetof(PyGpgmeImportResult, new_user_ids), RO},
1485- { "new_sub_keys", T_OBJECT, offsetof(PyGpgmeImportResult, new_sub_keys), RO},
1486- { "new_signatures", T_OBJECT, offsetof(PyGpgmeImportResult, new_signatures), RO},
1487+ { "considered", T_OBJECT, offsetof(PyGpgmeImportResult, considered), READONLY},
1488+ { "no_user_id", T_OBJECT, offsetof(PyGpgmeImportResult, no_user_id), READONLY},
1489+ { "imported", T_OBJECT, offsetof(PyGpgmeImportResult, imported), READONLY},
1490+ { "imported_rsa", T_OBJECT, offsetof(PyGpgmeImportResult, imported_rsa), READONLY},
1491+ { "unchanged", T_OBJECT, offsetof(PyGpgmeImportResult, unchanged), READONLY},
1492+ { "new_user_ids", T_OBJECT, offsetof(PyGpgmeImportResult, new_user_ids), READONLY},
1493+ { "new_sub_keys", T_OBJECT, offsetof(PyGpgmeImportResult, new_sub_keys), READONLY},
1494+ { "new_signatures", T_OBJECT, offsetof(PyGpgmeImportResult, new_signatures), READONLY},
1495 { "new_revocations", T_OBJECT,
1496- offsetof(PyGpgmeImportResult, new_revocations), RO},
1497+ offsetof(PyGpgmeImportResult, new_revocations), READONLY},
1498 { "secret_read", T_OBJECT,
1499- offsetof(PyGpgmeImportResult, secret_read), RO},
1500+ offsetof(PyGpgmeImportResult, secret_read), READONLY},
1501 { "secret_imported", T_OBJECT,
1502- offsetof(PyGpgmeImportResult, secret_imported), RO},
1503+ offsetof(PyGpgmeImportResult, secret_imported), READONLY},
1504 { "secret_unchanged", T_OBJECT,
1505- offsetof(PyGpgmeImportResult, secret_unchanged), RO},
1506+ offsetof(PyGpgmeImportResult, secret_unchanged), READONLY},
1507 { "skipped_new_keys", T_OBJECT,
1508- offsetof(PyGpgmeImportResult, skipped_new_keys), RO},
1509+ offsetof(PyGpgmeImportResult, skipped_new_keys), READONLY},
1510 { "not_imported", T_OBJECT,
1511- offsetof(PyGpgmeImportResult, not_imported), RO},
1512- { "imports", T_OBJECT, offsetof(PyGpgmeImportResult, imports), RO},
1513+ offsetof(PyGpgmeImportResult, not_imported), READONLY},
1514+ { "imports", T_OBJECT, offsetof(PyGpgmeImportResult, imports), READONLY},
1515 { NULL, 0, 0, 0}
1516 };
1517
1518 PyTypeObject PyGpgmeImportResult_Type = {
1519- PyObject_HEAD_INIT(NULL)
1520- 0,
1521+ PyVarObject_HEAD_INIT(NULL, 0)
1522 "gpgme.Import",
1523 sizeof(PyGpgmeImportResult),
1524 .tp_flags = Py_TPFLAGS_DEFAULT,
1525@@ -115,10 +114,17 @@
1526 if (!self->imports)
1527 return NULL;
1528 for (status = result->imports; status != NULL; status = status->next) {
1529- PyObject *item;
1530+ PyObject *py_fpr, *item;
1531
1532- item = Py_BuildValue("(zNi)",
1533- status->fpr,
1534+ if (status->fpr)
1535+ py_fpr = PyUnicode_DecodeASCII(status->fpr, strlen(status->fpr),
1536+ "replace");
1537+ else {
1538+ py_fpr = Py_None;
1539+ Py_INCREF(py_fpr);
1540+ }
1541+ item = Py_BuildValue("(NNi)",
1542+ py_fpr,
1543 pygpgme_error_object(status->result),
1544 status->status);
1545 if (!item) {
1546
1547=== modified file 'src/pygpgme-key.c'
1548--- src/pygpgme-key.c 2006-02-14 04:07:06 +0000
1549+++ src/pygpgme-key.c 2010-03-25 00:48:28 +0000
1550@@ -99,7 +99,8 @@
1551 pygpgme_subkey_get_keyid(PyGpgmeSubkey *self)
1552 {
1553 if (self->subkey->keyid)
1554- return PyString_FromString(self->subkey->keyid);
1555+ return PyUnicode_DecodeASCII(self->subkey->keyid,
1556+ strlen(self->subkey->keyid), "replace");
1557 else
1558 Py_RETURN_NONE;
1559 }
1560@@ -108,7 +109,8 @@
1561 pygpgme_subkey_get_fpr(PyGpgmeSubkey *self)
1562 {
1563 if (self->subkey->fpr)
1564- return PyString_FromString(self->subkey->fpr);
1565+ return PyUnicode_DecodeASCII(self->subkey->fpr,
1566+ strlen(self->subkey->fpr), "replace");
1567 else
1568 Py_RETURN_NONE;
1569 }
1570@@ -145,8 +147,7 @@
1571 };
1572
1573 PyTypeObject PyGpgmeSubkey_Type = {
1574- PyObject_HEAD_INIT(NULL)
1575- 0,
1576+ PyVarObject_HEAD_INIT(NULL, 0)
1577 "gpgme.Subkey",
1578 sizeof(PyGpgmeSubkey),
1579 .tp_flags = Py_TPFLAGS_DEFAULT,
1580@@ -198,7 +199,8 @@
1581 pygpgme_key_sig_get_keyid(PyGpgmeKeySig *self)
1582 {
1583 if (self->key_sig->keyid)
1584- return PyString_FromString(self->key_sig->keyid);
1585+ return PyUnicode_DecodeASCII(self->key_sig->keyid,
1586+ strlen(self->key_sig->keyid), "replace");
1587 else
1588 Py_RETURN_NONE;
1589 }
1590@@ -225,7 +227,8 @@
1591 pygpgme_key_sig_get_uid(PyGpgmeKeySig *self)
1592 {
1593 if (self->key_sig->uid)
1594- return PyString_FromString(self->key_sig->uid);
1595+ return PyUnicode_DecodeUTF8(self->key_sig->uid,
1596+ strlen(self->key_sig->uid), "replace");
1597 else
1598 Py_RETURN_NONE;
1599 }
1600@@ -234,7 +237,8 @@
1601 pygpgme_key_sig_get_name(PyGpgmeKeySig *self)
1602 {
1603 if (self->key_sig->name)
1604- return PyString_FromString(self->key_sig->name);
1605+ return PyUnicode_DecodeUTF8(self->key_sig->name,
1606+ strlen(self->key_sig->name), "replace");
1607 else
1608 Py_RETURN_NONE;
1609 }
1610@@ -243,7 +247,8 @@
1611 pygpgme_key_sig_get_email(PyGpgmeKeySig *self)
1612 {
1613 if (self->key_sig->email)
1614- return PyString_FromString(self->key_sig->email);
1615+ return PyUnicode_DecodeUTF8(self->key_sig->email,
1616+ strlen(self->key_sig->email), "replace");
1617 else
1618 Py_RETURN_NONE;
1619 }
1620@@ -252,7 +257,8 @@
1621 pygpgme_key_sig_get_comment(PyGpgmeKeySig *self)
1622 {
1623 if (self->key_sig->comment)
1624- return PyString_FromString(self->key_sig->comment);
1625+ return PyUnicode_DecodeUTF8(self->key_sig->comment,
1626+ strlen(self->key_sig->comment), "replace");
1627 else
1628 Py_RETURN_NONE;
1629 }
1630@@ -282,8 +288,7 @@
1631 };
1632
1633 PyTypeObject PyGpgmeKeySig_Type = {
1634- PyObject_HEAD_INIT(NULL)
1635- 0,
1636+ PyVarObject_HEAD_INIT(NULL, 0)
1637 "gpgme.KeySig",
1638 sizeof(PyGpgmeKeySig),
1639 .tp_flags = Py_TPFLAGS_DEFAULT,
1640@@ -323,7 +328,8 @@
1641 pygpgme_user_id_get_uid(PyGpgmeUserId *self)
1642 {
1643 if (self->user_id->uid)
1644- return PyString_FromString(self->user_id->uid);
1645+ return PyUnicode_DecodeUTF8(self->user_id->uid,
1646+ strlen(self->user_id->uid), "replace");
1647 else
1648 Py_RETURN_NONE;
1649 }
1650@@ -332,7 +338,8 @@
1651 pygpgme_user_id_get_name(PyGpgmeUserId *self)
1652 {
1653 if (self->user_id->name)
1654- return PyString_FromString(self->user_id->name);
1655+ return PyUnicode_DecodeUTF8(self->user_id->name,
1656+ strlen(self->user_id->name), "replace");
1657 else
1658 Py_RETURN_NONE;
1659 }
1660@@ -341,7 +348,8 @@
1661 pygpgme_user_id_get_email(PyGpgmeUserId *self)
1662 {
1663 if (self->user_id->email)
1664- return PyString_FromString(self->user_id->email);
1665+ return PyUnicode_DecodeUTF8(self->user_id->email,
1666+ strlen(self->user_id->email), "replace");
1667 else
1668 Py_RETURN_NONE;
1669 }
1670@@ -350,7 +358,8 @@
1671 pygpgme_user_id_get_comment(PyGpgmeUserId *self)
1672 {
1673 if (self->user_id->comment)
1674- return PyString_FromString(self->user_id->comment);
1675+ return PyUnicode_DecodeUTF8(self->user_id->comment,
1676+ strlen(self->user_id->comment), "replace");
1677 else
1678 Py_RETURN_NONE;
1679 }
1680@@ -394,8 +403,7 @@
1681 };
1682
1683 PyTypeObject PyGpgmeUserId_Type = {
1684- PyObject_HEAD_INIT(NULL)
1685- 0,
1686+ PyVarObject_HEAD_INIT(NULL, 0)
1687 "gpgme.UserId",
1688 sizeof(PyGpgmeUserId),
1689 .tp_flags = Py_TPFLAGS_DEFAULT,
1690@@ -476,7 +484,10 @@
1691 pygpgme_key_get_issuer_serial(PyGpgmeKey *self)
1692 {
1693 if (self->key->issuer_serial)
1694- return PyString_FromString(self->key->issuer_serial);
1695+ /* Haven't tested this, so perhaps it should be UTF8 */
1696+ return PyUnicode_DecodeASCII(self->key->issuer_serial,
1697+ strlen(self->key->issuer_serial),
1698+ "replace");
1699 else
1700 Py_RETURN_NONE;
1701 }
1702@@ -485,7 +496,9 @@
1703 pygpgme_key_get_issuer_name(PyGpgmeKey *self)
1704 {
1705 if (self->key->issuer_name)
1706- return PyString_FromString(self->key->issuer_name);
1707+ return PyUnicode_DecodeUTF8(self->key->issuer_name,
1708+ strlen(self->key->issuer_name),
1709+ "replace");
1710 else
1711 Py_RETURN_NONE;
1712 }
1713@@ -494,7 +507,9 @@
1714 pygpgme_key_get_chain_id(PyGpgmeKey *self)
1715 {
1716 if (self->key->chain_id)
1717- return PyString_FromString(self->key->chain_id);
1718+ /* Haven't tested this, so perhaps it should be UTF8 */
1719+ return PyUnicode_DecodeASCII(self->key->chain_id,
1720+ strlen(self->key->chain_id), "replace");
1721 else
1722 Py_RETURN_NONE;
1723 }
1724@@ -585,8 +600,7 @@
1725 };
1726
1727 PyTypeObject PyGpgmeKey_Type = {
1728- PyObject_HEAD_INIT(NULL)
1729- 0,
1730+ PyVarObject_HEAD_INIT(NULL, 0)
1731 "gpgme.Key",
1732 sizeof(PyGpgmeKey),
1733 .tp_flags = Py_TPFLAGS_DEFAULT,
1734
1735=== modified file 'src/pygpgme-keyiter.c'
1736--- src/pygpgme-keyiter.c 2006-02-14 04:07:06 +0000
1737+++ src/pygpgme-keyiter.c 2010-03-25 00:48:28 +0000
1738@@ -73,8 +73,7 @@
1739 }
1740
1741 PyTypeObject PyGpgmeKeyIter_Type = {
1742- PyObject_HEAD_INIT(NULL)
1743- 0,
1744+ PyVarObject_HEAD_INIT(NULL, 0)
1745 "gpgme.KeyIter",
1746 sizeof(PyGpgmeKeyIter),
1747 .tp_flags = Py_TPFLAGS_DEFAULT,
1748
1749=== modified file 'src/pygpgme-signature.c'
1750--- src/pygpgme-signature.c 2006-02-14 04:07:06 +0000
1751+++ src/pygpgme-signature.c 2010-03-25 00:48:28 +0000
1752@@ -33,18 +33,17 @@
1753 }
1754
1755 static PyMemberDef pygpgme_newsig_members[] = {
1756- { "type", T_OBJECT, offsetof(PyGpgmeNewSignature, type), RO},
1757- { "pubkey_algo", T_OBJECT, offsetof(PyGpgmeNewSignature, pubkey_algo), RO},
1758- { "hash_algo", T_OBJECT, offsetof(PyGpgmeNewSignature, hash_algo), RO},
1759- { "timestamp", T_OBJECT, offsetof(PyGpgmeNewSignature, timestamp), RO},
1760- { "fpr", T_OBJECT, offsetof(PyGpgmeNewSignature, fpr), RO},
1761- { "sig_class", T_OBJECT, offsetof(PyGpgmeNewSignature, sig_class), RO},
1762+ { "type", T_OBJECT, offsetof(PyGpgmeNewSignature, type), READONLY},
1763+ { "pubkey_algo", T_OBJECT, offsetof(PyGpgmeNewSignature, pubkey_algo), READONLY},
1764+ { "hash_algo", T_OBJECT, offsetof(PyGpgmeNewSignature, hash_algo), READONLY},
1765+ { "timestamp", T_OBJECT, offsetof(PyGpgmeNewSignature, timestamp), READONLY},
1766+ { "fpr", T_OBJECT, offsetof(PyGpgmeNewSignature, fpr), READONLY},
1767+ { "sig_class", T_OBJECT, offsetof(PyGpgmeNewSignature, sig_class), READONLY},
1768 { NULL, 0, 0, 0}
1769 };
1770
1771 PyTypeObject PyGpgmeNewSignature_Type = {
1772- PyObject_HEAD_INIT(NULL)
1773- 0,
1774+ PyVarObject_HEAD_INIT(NULL, 0)
1775 "gpgme.NewSignature",
1776 sizeof(PyGpgmeNewSignature),
1777 .tp_flags = Py_TPFLAGS_DEFAULT,
1778@@ -72,7 +71,8 @@
1779 item->hash_algo = PyInt_FromLong(sig->hash_algo);
1780 item->timestamp = PyInt_FromLong(sig->timestamp);
1781 if (sig->fpr) {
1782- item->fpr = PyString_FromString(sig->fpr);
1783+ item->fpr = PyUnicode_DecodeASCII(sig->fpr, strlen(sig->fpr),
1784+ "replace");
1785 } else {
1786 Py_INCREF(Py_None);
1787 item->fpr = Py_None;
1788@@ -105,24 +105,23 @@
1789 }
1790
1791 static PyMemberDef pygpgme_sig_members[] = {
1792- { "summary", T_OBJECT, offsetof(PyGpgmeSignature, summary), RO},
1793- { "fpr", T_OBJECT, offsetof(PyGpgmeSignature, fpr), RO},
1794- { "status", T_OBJECT, offsetof(PyGpgmeSignature, status), RO},
1795- { "notations", T_OBJECT, offsetof(PyGpgmeSignature, notations), RO},
1796- { "timestamp", T_OBJECT, offsetof(PyGpgmeSignature, timestamp), RO},
1797+ { "summary", T_OBJECT, offsetof(PyGpgmeSignature, summary), READONLY},
1798+ { "fpr", T_OBJECT, offsetof(PyGpgmeSignature, fpr), READONLY},
1799+ { "status", T_OBJECT, offsetof(PyGpgmeSignature, status), READONLY},
1800+ { "notations", T_OBJECT, offsetof(PyGpgmeSignature, notations), READONLY},
1801+ { "timestamp", T_OBJECT, offsetof(PyGpgmeSignature, timestamp), READONLY},
1802 { "exp_timestamp", T_OBJECT,
1803- offsetof(PyGpgmeSignature, exp_timestamp), RO},
1804+ offsetof(PyGpgmeSignature, exp_timestamp), READONLY},
1805 { "wrong_key_usage", T_OBJECT,
1806- offsetof(PyGpgmeSignature, wrong_key_usage), RO},
1807- { "validity", T_OBJECT, offsetof(PyGpgmeSignature, validity), RO},
1808+ offsetof(PyGpgmeSignature, wrong_key_usage), READONLY},
1809+ { "validity", T_OBJECT, offsetof(PyGpgmeSignature, validity), READONLY},
1810 { "validity_reason", T_OBJECT,
1811- offsetof(PyGpgmeSignature, validity_reason), RO},
1812+ offsetof(PyGpgmeSignature, validity_reason), READONLY},
1813 { NULL, 0, 0, 0}
1814 };
1815
1816 PyTypeObject PyGpgmeSignature_Type = {
1817- PyObject_HEAD_INIT(NULL)
1818- 0,
1819+ PyVarObject_HEAD_INIT(NULL, 0)
1820 "gpgme.Signature",
1821 sizeof(PyGpgmeSignature),
1822 .tp_flags = Py_TPFLAGS_DEFAULT,
1823@@ -148,7 +147,8 @@
1824 }
1825 item->summary = PyInt_FromLong(sig->summary);
1826 if (sig->fpr) {
1827- item->fpr = PyString_FromString(sig->fpr);
1828+ item->fpr = PyUnicode_DecodeASCII(sig->fpr, strlen(sig->fpr),
1829+ "replace");
1830 } else {
1831 Py_INCREF(Py_None);
1832 item->fpr = Py_None;
1833@@ -156,12 +156,17 @@
1834 item->status = pygpgme_error_object(sig->status);
1835 item->notations = PyList_New(0);
1836 for (not = sig->notations; not != NULL; not = not->next) {
1837- PyObject *pynot = Py_BuildValue("(zz)", not->name, not->value);
1838-
1839- if (!pynot)
1840+ PyObject *py_name, *py_value, *py_not;
1841+
1842+ py_name = PyUnicode_DecodeUTF8(not->name, not->name_len,
1843+ "replace");
1844+ py_value = PyBytes_FromStringAndSize(not->value, not->value_len);
1845+ py_not = Py_BuildValue("(NN)", py_name, py_value);
1846+
1847+ if (!py_not)
1848 break;
1849- PyList_Append(item->notations, pynot);
1850- Py_DECREF(pynot);
1851+ PyList_Append(item->notations, py_not);
1852+ Py_DECREF(py_not);
1853 }
1854 item->timestamp = PyInt_FromLong(sig->timestamp);
1855 item->exp_timestamp = PyInt_FromLong(sig->exp_timestamp);
1856
1857=== modified file 'src/pygpgme.h'
1858--- src/pygpgme.h 2008-10-15 21:36:35 +0000
1859+++ src/pygpgme.h 2010-03-25 00:48:28 +0000
1860@@ -23,6 +23,8 @@
1861 #include <Python.h>
1862 #include <gpgme.h>
1863
1864+#include "pycompat.h"
1865+
1866 #define HIDDEN __attribute__((visibility("hidden")))
1867
1868 typedef struct {

Subscribers

People subscribed via source and target branches