18
18
# ------------------------------------------------------------------------
19
19
20
20
import os
21
+ import xmlrpclib , httplib
21
22
from argparse import ArgumentParser
22
23
from version import VERSION
24
+ try :
25
+ import gzip
26
+ except ImportError :
27
+ gzip = None #python can be built without zlib/gzip support
28
+
29
+
30
+ class ProxiedTransport (xmlrpclib .Transport ):
31
+ def __init__ (self ):
32
+ xmlrpclib .Transport .__init__ (self )
33
+ self .realhost = None
34
+ self .proxy = None
35
+
36
+ def set_proxy (self , proxy ):
37
+ """Define HTTP proxy (with optional basic auth)
38
+
39
+ :param str proxy: Proxy string
40
+ """
41
+ cproxy , auth , x509 = self .get_host_info (proxy )
42
+ self .proxy = cproxy
43
+ if auth :
44
+ auth = [ ('Proxy-Authorization' , auth [0 ][1 ]) ]
45
+ if self ._extra_headers :
46
+ self ._extra_headers .extend (auth )
47
+ else :
48
+ self ._extra_headers = auth
49
+
50
+ def make_connection (self , host ):
51
+ """return an existing connection if possible. This allows HTTP/1.1 keep-alive.
52
+
53
+ :param str|(str, {}) host: Host descriptor (URL or (URL, x509 info) tuple)
54
+ :return httplib.HTTPConnection:
55
+ """
56
+ if self ._connection and host == self ._connection [0 ]:
57
+ return self ._connection [1 ]
58
+
59
+ # create a HTTP connection object from a host descriptor
60
+ chost , auth , x509 = self .get_host_info (host )
61
+ if auth :
62
+ if self ._extra_headers :
63
+ self ._extra_headers .extend (auth )
64
+ else :
65
+ self ._extra_headers = auth
66
+ self .realhost = host
67
+ self ._connection = host , httplib .HTTPConnection (self .proxy )
68
+ return self ._connection [1 ]
69
+
70
+ def send_request (self , connection , handler , request_body ):
71
+ """Send request header
72
+
73
+ :param httplib.HTTPConnection connection: Connection handle
74
+ :param str handler: Target RPC handler
75
+ :param str request_body:XML-RPC body
76
+ """
77
+ if self .accept_gzip_encoding and gzip :
78
+ connection .putrequest ("POST" , 'http://%s%s' % (self .realhost , handler ), skip_accept_encoding = True )
79
+ connection .putheader ("Accept-Encoding" , "gzip" )
80
+ else :
81
+ connection .putrequest ("POST" , 'http://%s%s' % (self .realhost , handler ))
82
+
83
+ def send_host (self , connection , host ):
84
+ """Send host name
85
+
86
+ Note: This function doesn't actually add the "Host"
87
+ header anymore, it is done as part of the connection.putrequest() in
88
+ send_request() above.
89
+
90
+ :param httplib.HTTPConnection connection: Connection handle
91
+ :param str host: Host name
92
+ """
93
+ extra_headers = self ._extra_headers
94
+ if extra_headers :
95
+ if isinstance (extra_headers , dict ()):
96
+ extra_headers = extra_headers .items ()
97
+ for key , value in extra_headers :
98
+ connection .putheader (key , value )
23
99
24
100
25
101
class TestLinkHelper (object ):
@@ -52,24 +128,25 @@ class TestLinkHelper(object):
52
128
to http://localhost/testlink/lib/api/xmlrpc/v1/xmlrpc.php
53
129
"""
54
130
55
- __slots__ = ['_server_url' , '_devkey' ]
131
+ __slots__ = ['_server_url' , '_devkey' , '_proxy' ]
56
132
57
- ENVNAME_SERVER_URL = 'TESTLINK_API_PYTHON_SERVER_URL'
58
- ENVNAME_DEVKEY = 'TESTLINK_API_PYTHON_DEVKEY'
59
- DEFAULT_SERVER_URL = 'http://localhost/testlink/lib/api/xmlrpc.php'
60
- DEFAULT_DEVKEY = '42'
133
+ ENVNAME_SERVER_URL = 'TESTLINK_API_PYTHON_SERVER_URL'
134
+ ENVNAME_DEVKEY = 'TESTLINK_API_PYTHON_DEVKEY'
135
+ DEFAULT_SERVER_URL = 'http://localhost/testlink/lib/api/xmlrpc.php'
136
+ DEFAULT_DEVKEY = '42'
61
137
DEFAULT_DESCRIPTION = 'Python XML-RPC client for the TestLink API v%s' \
62
138
% VERSION
63
139
64
- def __init__ (self , server_url = None , devkey = None ):
140
+ def __init__ (self , server_url = None , devkey = None , proxy = None ):
65
141
""" fill slots _server_url and _devkey
66
142
Priority:
67
143
1. init args
68
144
2. environment variables
69
145
3. default values
70
146
"""
71
147
self ._server_url = server_url
72
- self ._devkey = devkey
148
+ self ._devkey = devkey
149
+ self ._proxy = proxy
73
150
self ._setParamsFromEnv ()
74
151
75
152
def _setParamsFromEnv (self ):
@@ -79,12 +156,15 @@ def _setParamsFromEnv(self):
79
156
80
157
If environment variables are not defined, defaults values are set.
81
158
"""
82
- if self ._server_url == None :
159
+ if not self ._server_url :
83
160
self ._server_url = os .getenv (self .ENVNAME_SERVER_URL ,
84
161
self .DEFAULT_SERVER_URL )
85
- if self ._devkey == None :
162
+ if not self ._devkey :
86
163
self ._devkey = os .getenv (self .ENVNAME_DEVKEY , self .DEFAULT_DEVKEY )
87
164
165
+ if not self ._proxy :
166
+ self ._proxy = os .getenv ('http_proxy' )
167
+
88
168
def _createArgparser (self , usage ):
89
169
""" returns a parser for command line arguments """
90
170
@@ -96,22 +176,29 @@ def _createArgparser(self, usage):
96
176
# must be set individual for each user
97
177
a_parser .add_argument ('--devKey' , default = self ._devkey ,
98
178
help = 'Users devKey generated by TestLink (default: %(default)s) ' )
179
+ a_parser .add_argument ('--proxy' , default = self ._proxy ,
180
+ help = 'HTTP Proxy (default: %(default)s) ' )
99
181
return a_parser
100
182
101
183
def setParamsFromArgs (self , usage = DEFAULT_DESCRIPTION , args = None ):
102
184
""" fill slots _server_url and _devkey from command line arguments
103
185
_server_url <- --server_url
104
186
_devkey <- --devKey
105
-
187
+ _proxy <- --proxy
188
+
106
189
uses current values of these slots as default values
107
190
"""
108
- a_parser = self ._createArgparser (usage )
109
- args = a_parser .parse_args (args )
191
+ if not args :
192
+ a_parser = self ._createArgparser (usage )
193
+ args = a_parser .parse_args ()
110
194
self ._server_url = args .server_url
111
- self ._devkey = args .devKey
112
-
113
-
114
- def connect (self , tl_api_class ):
195
+ self ._devkey = args .devKey
196
+ self . _proxy = args . proxy
197
+
198
+ def connect (self , tl_api_class , ** kwargs ):
115
199
""" returns a new instance of TL_API_CLASS """
116
- return tl_api_class (self ._server_url , self ._devkey )
117
-
200
+ if self ._proxy :
201
+ p = ProxiedTransport ()
202
+ p .set_proxy (self ._proxy )
203
+ kwargs ['transport' ] = p
204
+ return tl_api_class (self ._server_url , self ._devkey , ** kwargs )
0 commit comments