add skeleton for variant type support
[pywinlite.git] / variant.py
blob5636b6728996b3ee4bc6fd8a4903a232f05f3cf4
1 #Copyright (c) 2009 Vincent Povirk
3 #Permission is hereby granted, free of charge, to any person
4 #obtaining a copy of this software and associated documentation
5 #files (the "Software"), to deal in the Software without
6 #restriction, including without limitation the rights to use,
7 #copy, modify, merge, publish, distribute, sublicense, and/or sell
8 #copies of the Software, and to permit persons to whom the
9 #Software is furnished to do so, subject to the following
10 #conditions:
12 #The above copyright notice and this permission notice shall be
13 #included in all copies or substantial portions of the Software.
15 #THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16 #EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
17 #OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18 #NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
19 #HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
20 #WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
21 #FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
22 #OTHER DEALINGS IN THE SOFTWARE.
24 # variant and related types
26 from ctypes import Structure, c_void_p, windll, POINTER, HRESULT, byref
27 from windef import USHORT, WORD
28 from winliteutils import get_symbols
30 VARTYPE = USHORT
32 VT_EMPTY = 0
33 VT_NULL = 1
34 VT_I2 = 2
35 VT_I4 = 3
36 VT_R4 = 4
37 VT_R8 = 5
38 VT_CY = 6
39 VT_DATE = 7
40 VT_BSTR = 8
41 VT_DISPATCH = 9
42 VT_ERROR = 10
43 VT_BOOL = 11
44 VT_VARIANT = 12
45 VT_UNKNOWN = 13
46 VT_DECIMAL = 14
47 VT_I1 = 16
48 VT_UI1 = 17
49 VT_UI2 = 18
50 VT_UI4 = 19
51 VT_I8 = 20
52 VT_UI8 = 21
53 VT_INT = 22
54 VT_UINT = 23
55 VT_VOID = 24
56 VT_HRESULT = 25
57 VT_PTR = 26
58 VT_SAFEARRAY = 27
59 VT_CARRAY = 28
60 VT_USERDEFINED = 29
61 VT_LPSTR = 30
62 VT_LPWSTR = 31
63 VT_RECORD = 36
64 VT_INT_PTR = 37
65 VT_UINT_PTR = 38
66 VT_FILETIME = 64
67 VT_BLOB = 65
68 VT_STREAM = 66
69 VT_STORAGE = 67
70 VT_STREAMED_OBJECT = 68
71 VT_STORED_OBJECT = 69
72 VT_BLOB_OBJECT = 70
73 VT_CF = 71
74 VT_CLSID = 72
75 VT_VERSIONED_STREAM = 73
76 VT_BSTR_BLOB = 0x0fff
77 VT_VECTOR = 0x1000
78 VT_ARRAY = 0x2000
79 VT_BYREF = 0x4000
80 VT_RESERVED = 0x8000
81 VT_ILLEGAL = 0xffff
82 VT_ILLEGALMASKED = 0x0fff
83 VT_TYPEMASK = 0x0fff
85 _oleaut32 = windll.oleaut32
86 get_symbols(globals(), _oleaut32, ['VariantClear', 'VariantInit'])
88 class _VARIANT_VAL(Structure):
89 _fields_ = [('p1', c_void_p),
90 ('p2', c_void_p),
93 class VARIANT(Structure):
94 _fields_ = [('vt', VARTYPE),
95 ('wReserved1', WORD),
96 ('wReserved2', WORD),
97 ('wReserved3', WORD),
98 ('_value', _VARIANT_VAL),
101 def __init__(self):
102 VariantInit(byref(self))
104 def _set_value(self, value):
105 try:
106 setter = value.__setvariant__
107 except AttributeError:
108 try:
109 setter = _variant_setters[type(value)]
110 except KeyError:
111 raise TypeError("variable of type %s cannot be converted to variant" % str(type(value)))
112 else:
113 setter[0](self, value, *setter[1:])
114 else:
115 setter(self)
117 def _get_value(self):
118 try:
119 getter = _variant_getters[self.vt]
120 except KeyError:
121 raise TypeError("getting variant type %s not supported" % self.vt)
122 else:
123 return getter[0](self, *getter[1:])
125 value = property(_get_value, _set_value)
127 def __del__(self):
128 VariantClear(byref(self))
130 VARIANTARG = VARIANT
131 LPVARIANTARG = LPVARIANT = POINTER(VARIANT)
133 VariantClear.argtypes = [LPVARIANTARG]
134 VariantClear.restype = HRESULT
136 VariantInit.argtypes = [LPVARIANTARG]
137 VariantInit.restype = None
139 def _get_empty(variant):
140 return None
142 def _set_empty(variant, value):
143 VariantClear(byref(var))
145 class _SQL_NULL(object):
146 def __setvariant__(self, var):
147 VariantClear(byref(var))
148 var.vt = VT_NULL
150 sql_null = _SQL_NULL()
152 def _get_null(variant):
153 return sql_null
155 _variant_getters = {
156 VT_EMPTY: (_get_empty,),
157 VT_NULL: (_get_null,),
160 _variant_setters = {
161 type(None): (_set_empty,),