Le python-magic (en fait le paquet "file") de Debian est vraiment trop vieux…
[progfou.git] / ctypes / iconv.py
1 #!/usr/bin/env python
2 # -*- coding: utf-8 -*-
3 """
4 Module de support iconv pour Python.
5
6 Copyright : Agence universitaire de la Francophonie
7 Licence : GNU General Public Licence, version 2
8 Auteur : Jean Christophe André
9 Date de création : 20 mars 2009
10 """
11
12 from ctypes import *
13 from ctypes.util import find_library
14
15 # on n'exporte que la fonction iconv ('a marche pô ?!)
16 __all__ = ["iconv"]
17
18 # la librairie C
19 _libc = CDLL(find_library("c"))
20
21 # un type spécifique à iconv (pour stoquer l'état de son automate)
22 _iconv_t = c_void_p
23
24 # prototype de la fonction iconv_open(3)
25 _iconv_open = _libc.iconv_open
26 _iconv_open.argtypes = [c_char_p, c_char_p]
27 _iconv_open.restype = _iconv_t
28
29 # prototype de la fonction iconv(3)
30 _iconv = _libc.iconv
31 _iconv.argtypes = [_iconv_t,
32 POINTER(POINTER(ARRAY(c_char, 1024))), POINTER(c_size_t),
33 POINTER(POINTER(ARRAY(c_char, 4096))), POINTER(c_size_t)]
34 _iconv.restype = c_size_t
35
36 # prototype de la fonction iconv_close(3)
37 _iconv_close = _libc.iconv_close
38 _iconv_close.argtypes = [_iconv_t]
39 _iconv_close.restype = c_int
40
41 def iconv(from_code, to_code, string):
42 """
43 from_code : encodage d'origine de string
44 to_code : encodage souhaité en retour
45 string : la chaîne dont il faut convertir l'encodage
46
47 On pourra utiliser to_code='ascii//TRANSLIT' pour supprimer les accents.
48 Attention : ça ne fonctionne pas à 100% !
49
50 Plus de détails dans la page de manuel de iconv(1).
51 """
52
53 # on commence par créer un contexte de conversion
54 cp = _iconv_open(c_char_p(to_code), c_char_p(from_code))
55
56 # on prépare les structures de données à transmettres
57 inbuf = create_string_buffer(string, 1024)
58 inbytesleft = c_size_t(len(inbuf))
59 outbuf = create_string_buffer(4096)
60 outbytesleft = c_size_t(len(outbuf))
61
62 # on effectue la conversion
63 _iconv(cp, byref(pointer(inbuf)), byref(inbytesleft),
64 byref(pointer(outbuf)), byref(outbytesleft))
65 result = outbuf.value[:outbytesleft.value]
66
67 # on détruit le contexte de conversion et on retourne le résultat
68 _iconv_close(cp)
69 return result
70
71 if __name__ == "__main__":
72 # on précise la translitération via un environnement linguistique
73 from locale import setlocale, LC_ALL
74 setlocale(LC_ALL, 'en_US.UTF-8')
75
76 # test de cas limites (en français, vietnamien et japonais)
77 from unicodedata import normalize
78 t = u"fête cœur français tiếng việt đường プログフ"
79 i = iconv("utf-8", "ascii//TRANSLIT", t.encode('utf-8'))
80 u = normalize("NFKD", t).encode('ascii','ignore')
81 print u"TEST: texte original: '%s'" % t
82 print u"TEST: iconv(utf8..ascii//TRANSLIT): '%s'" % i
83 print u"TEST: normalize(NFKD).encode(ascii,ignore): '%s'" % u
84