root / trunk / twisted / python / compat.py

Revision 22278, 5.6 kB (checked in by therve, 1 year ago)

Merge set-compat-2761-3

Author: therve
Reviewers: exarkun, ralphm
Fixes #2761

Add twisted.python.compat.set and twisted.python.compat.frozenset, to be used
for keeping compatibility when the builtins is not available (ie, Python 2.3).

Line 
1 # -*- test-case-name: twisted.test.test_compat -*-
2 #
3 # Copyright (c) 2001-2007 Twisted Matrix Laboratories.
4 # See LICENSE for details.
5
6
7 """
8 Compatibility module to provide backwards compatibility for useful Python
9 features.
10
11 This is mainly for use of internal Twisted code. We encourage you to use
12 the latest version of Python directly from your code, if possible.
13 """
14
15 import sys, string, socket, struct
16
17 def inet_pton(af, addr):
18     if af == socket.AF_INET:
19         return socket.inet_aton(addr)
20     elif af == getattr(socket, 'AF_INET6', 'AF_INET6'):
21         if [x for x in addr if x not in string.hexdigits + ':.']:
22             raise ValueError("Illegal characters: %r" % (''.join(x),))
23
24         parts = addr.split(':')
25         elided = parts.count('')
26         ipv4Component = '.' in parts[-1]
27
28         if len(parts) > (8 - ipv4Component) or elided > 3:
29             raise ValueError("Syntactically invalid address")
30
31         if elided == 3:
32             return '\x00' * 16
33
34         if elided:
35             zeros = ['0'] * (8 - len(parts) - ipv4Component + elided)
36
37             if addr.startswith('::'):
38                 parts[:2] = zeros
39             elif addr.endswith('::'):
40                 parts[-2:] = zeros
41             else:
42                 idx = parts.index('')
43                 parts[idx:idx+1] = zeros
44
45             if len(parts) != 8 - ipv4Component:
46                 raise ValueError("Syntactically invalid address")
47         else:
48             if len(parts) != (8 - ipv4Component):
49                 raise ValueError("Syntactically invalid address")
50
51         if ipv4Component:
52             if parts[-1].count('.') != 3:
53                 raise ValueError("Syntactically invalid address")
54             rawipv4 = socket.inet_aton(parts[-1])
55             unpackedipv4 = struct.unpack('!HH', rawipv4)
56             parts[-1:] = [hex(x)[2:] for x in unpackedipv4]
57
58         parts = [int(x, 16) for x in parts]
59         return struct.pack('!8H', *parts)
60     else:
61         raise socket.error(97, 'Address family not supported by protocol')
62
63 def inet_ntop(af, addr):
64     if af == socket.AF_INET:
65         return socket.inet_ntoa(addr)
66     elif af == socket.AF_INET6:
67         if len(addr) != 16:
68             raise ValueError("address length incorrect")
69         parts = struct.unpack('!8H', addr)
70         curBase = bestBase = None
71         for i in range(8):
72             if not parts[i]:
73                 if curBase is None:
74                     curBase = i
75                     curLen = 0
76                 curLen += 1
77             else:
78                 if curBase is not None:
79                     if bestBase is None or curLen > bestLen:
80                         bestBase = curBase
81                         bestLen = curLen
82                     curBase = None
83         if curBase is not None and (bestBase is None or curLen > bestLen):
84             bestBase = curBase
85             bestLen = curLen
86         parts = [hex(x)[2:] for x in parts]
87         if bestBase is not None:
88             parts[bestBase:bestBase + bestLen] = ['']
89         if parts[0] == '':
90             parts.insert(0, '')
91         if parts[-1] == '':
92             parts.insert(len(parts) - 1, '')
93         return ':'.join(parts)
94     else:
95         raise socket.error(97, 'Address family not supported by protocol')
96
97 try:
98     socket.inet_pton(socket.AF_INET6, "::")
99 except (AttributeError, NameError, socket.error):
100     socket.inet_pton = inet_pton
101     socket.inet_ntop = inet_ntop
102     socket.AF_INET6 = 'AF_INET6'
103
104 adict = dict
105
106 # OpenSSL/__init__.py imports OpenSSL.tsafe.  OpenSSL/tsafe.py imports
107 # threading.  threading imports thread.  All to make this stupid threadsafe
108 # version of its Connection class.  We don't even care about threadsafe
109 # Connections.  In the interest of not screwing over some crazy person
110 # calling into OpenSSL from another thread and trying to use Twisted's SSL
111 # support, we don't totally destroy OpenSSL.tsafe, but we will replace it
112 # with our own version which imports threading as late as possible.
113
114 class tsafe(object):
115     class Connection:
116         """
117         OpenSSL.tsafe.Connection, defined in such a way as to not blow.
118         """
119         __module__ = 'OpenSSL.tsafe'
120
121         def __init__(self, *args):
122             from OpenSSL import SSL as _ssl
123             self._ssl_conn = apply(_ssl.Connection, args)
124             from threading import _RLock
125             self._lock = _RLock()
126
127         for f in ('get_context', 'pending', 'send', 'write', 'recv',
128                   'read', 'renegotiate', 'bind', 'listen', 'connect',
129                   'accept', 'setblocking', 'fileno', 'shutdown',
130                   'close', 'get_cipher_list', 'getpeername',
131                   'getsockname', 'getsockopt', 'setsockopt',
132                   'makefile', 'get_app_data', 'set_app_data',
133                   'state_string', 'sock_shutdown',
134                   'get_peer_certificate', 'want_read', 'want_write',
135                   'set_connect_state', 'set_accept_state',
136                   'connect_ex', 'sendall'):
137
138             exec """def %s(self, *args):
139                 self._lock.acquire()
140                 try:
141                     return apply(self._ssl_conn.%s, args)
142                 finally:
143                     self._lock.release()\n""" % (f, f)
144 sys.modules['OpenSSL.tsafe'] = tsafe
145
146 import operator
147 try:
148     operator.attrgetter
149 except AttributeError:
150     class attrgetter(object):
151         def __init__(self, name):
152             self.name = name
153         def __call__(self, obj):
154             return getattr(obj, self.name)
155     operator.attrgetter = attrgetter
156
157
158 try:
159     set = set
160 except NameError:
161     from sets import Set as set
162
163
164 try:
165     frozenset = frozenset
166 except NameError:
167     from sets import ImmutableSet as frozenset
168
Note: See TracBrowser for help on using the browser.