apache / libcloud

@@ -346,16 +346,21 @@
Loading
346 346
347 347
    def set_http_proxy(self, proxy_url):
348 348
        """
349 -
        Set a HTTP proxy which will be used with this connection.
349 +
        Set a HTTP / HTTPS proxy which will be used with this connection.
350 350
351 351
        :param proxy_url: Proxy URL (e.g. http://<hostname>:<port> without
352 352
                          authentication and
353 -
                          http://<username>:<password>@<hostname>:<port> for
354 -
                          basic auth authentication information.
353 +
                          <scheme>://<username>:<password>@<hostname>:<port>
354 +
                          for basic auth authentication information.
355 355
        :type proxy_url: ``str``
356 356
        """
357 357
        self.proxy_url = proxy_url
358 358
359 +
        # NOTE: Because of the way connection instantion works, we need to call
360 +
        # self.connection.set_http_proxy() here. Just setting "self.proxy_url"
361 +
        # won't work.
362 +
        self.connection.set_http_proxy(proxy_url=proxy_url)
363 +
359 364
    def set_context(self, context):
360 365
        if not isinstance(context, dict):
361 366
            raise TypeError('context needs to be a dictionary')

@@ -52,6 +52,14 @@
Loading
52 52
        self.assertIsNone(result[3])
53 53
        self.assertIsNone(result[4])
54 54
55 +
        proxy_url = 'https://127.0.0.2:3129'
56 +
        result = conn._parse_proxy_url(proxy_url=proxy_url)
57 +
        self.assertEqual(result[0], 'https')
58 +
        self.assertEqual(result[1], '127.0.0.2')
59 +
        self.assertEqual(result[2], 3129)
60 +
        self.assertIsNone(result[3])
61 +
        self.assertIsNone(result[4])
62 +
55 63
        proxy_url = 'http://user1:pass1@127.0.0.1:3128'
56 64
        result = conn._parse_proxy_url(proxy_url=proxy_url)
57 65
        self.assertEqual(result[0], 'http')
@@ -60,11 +68,13 @@
Loading
60 68
        self.assertEqual(result[3], 'user1')
61 69
        self.assertEqual(result[4], 'pass1')
62 70
63 -
        proxy_url = 'https://127.0.0.1:3128'
64 -
        expected_msg = 'Only http proxies are supported'
65 -
        assertRaisesRegex(self, ValueError, expected_msg,
66 -
                          conn._parse_proxy_url,
67 -
                          proxy_url=proxy_url)
71 +
        proxy_url = 'https://user1:pass1@127.0.0.2:3129'
72 +
        result = conn._parse_proxy_url(proxy_url=proxy_url)
73 +
        self.assertEqual(result[0], 'https')
74 +
        self.assertEqual(result[1], '127.0.0.2')
75 +
        self.assertEqual(result[2], 3129)
76 +
        self.assertEqual(result[3], 'user1')
77 +
        self.assertEqual(result[4], 'pass1')
68 78
69 79
        proxy_url = 'http://127.0.0.1'
70 80
        expected_msg = 'proxy_url must be in the following format'
@@ -91,6 +101,9 @@
Loading
91 101
        self.assertEqual(conn.proxy_scheme, 'http')
92 102
        self.assertEqual(conn.proxy_host, '127.0.0.2')
93 103
        self.assertEqual(conn.proxy_port, 3128)
104 +
        self.assertEqual(conn.session.proxies, {
105 +
            'http': 'http://127.0.0.2:3128'
106 +
        })
94 107
95 108
        _ = os.environ.pop('http_proxy', None)
96 109
        conn = LibcloudConnection(host='localhost', port=80)
@@ -103,6 +116,9 @@
Loading
103 116
        self.assertEqual(conn.proxy_scheme, 'http')
104 117
        self.assertEqual(conn.proxy_host, '127.0.0.3')
105 118
        self.assertEqual(conn.proxy_port, 3128)
119 +
        self.assertEqual(conn.session.proxies, {
120 +
            'http': 'http://127.0.0.3:3128'
121 +
        })
106 122
107 123
        proxy_url = 'http://127.0.0.4:3128'
108 124
        conn = LibcloudConnection(host='localhost', port=80,
@@ -110,6 +126,9 @@
Loading
110 126
        self.assertEqual(conn.proxy_scheme, 'http')
111 127
        self.assertEqual(conn.proxy_host, '127.0.0.4')
112 128
        self.assertEqual(conn.proxy_port, 3128)
129 +
        self.assertEqual(conn.session.proxies, {
130 +
            'http': 'http://127.0.0.4:3128'
131 +
        })
113 132
114 133
        os.environ['http_proxy'] = proxy_url
115 134
        proxy_url = 'http://127.0.0.5:3128'
@@ -118,6 +137,20 @@
Loading
118 137
        self.assertEqual(conn.proxy_scheme, 'http')
119 138
        self.assertEqual(conn.proxy_host, '127.0.0.5')
120 139
        self.assertEqual(conn.proxy_port, 3128)
140 +
        self.assertEqual(conn.session.proxies, {
141 +
            'http': 'http://127.0.0.5:3128'
142 +
        })
143 +
144 +
        os.environ['http_proxy'] = proxy_url
145 +
        proxy_url = 'https://127.0.0.6:3129'
146 +
        conn = LibcloudConnection(host='localhost', port=80,
147 +
                                  proxy_url=proxy_url)
148 +
        self.assertEqual(conn.proxy_scheme, 'https')
149 +
        self.assertEqual(conn.proxy_host, '127.0.0.6')
150 +
        self.assertEqual(conn.proxy_port, 3129)
151 +
        self.assertEqual(conn.session.proxies, {
152 +
            'https': 'https://127.0.0.6:3129'
153 +
        })
121 154
122 155
    def test_connection_to_unusual_port(self):
123 156
        conn = LibcloudConnection(host='localhost', port=8080)
@@ -393,5 +426,6 @@
Loading
393 426
        self.assertTrue(isinstance(adapter, SignedHTTPSAdapter))
394 427
        self.assertEqual(adapter.cert_file, 'test.pem')
395 428
429 +
396 430
if __name__ == '__main__':
397 431
    sys.exit(unittest.main())

@@ -94,13 +94,15 @@
Loading
94 94
95 95
        if self.http_proxy_used:
96 96
            if self.proxy_username and self.proxy_password:
97 -
                proxy_url = 'http://%s:%s@%s:%s' % (self.proxy_username,
98 -
                                                    self.proxy_password,
99 -
                                                    self.proxy_host,
100 -
                                                    self.proxy_port)
97 +
                proxy_url = '%s://%s:%s@%s:%s' % (self.proxy_scheme,
98 +
                                                  self.proxy_username,
99 +
                                                  self.proxy_password,
100 +
                                                  self.proxy_host,
101 +
                                                  self.proxy_port)
101 102
            else:
102 -
                proxy_url = 'http://%s:%s' % (self.proxy_host,
103 -
                                              self.proxy_port)
103 +
                proxy_url = '%s://%s:%s' % (self.proxy_scheme,
104 +
                                            self.proxy_host,
105 +
                                            self.proxy_port)
104 106
            proxy_url = pquote(proxy_url)
105 107
            cmd.extend(['--proxy', proxy_url])
106 108

@@ -36,6 +36,7 @@
Loading
36 36
ALLOW_REDIRECTS = 1
37 37
38 38
HTTP_PROXY_ENV_VARIABLE_NAME = 'http_proxy'
39 +
HTTPS_PROXY_ENV_VARIABLE_NAME = 'https_proxy'
39 40
40 41
41 42
class SignedHTTPSAdapter(HTTPAdapter):
@@ -86,6 +87,7 @@
Loading
86 87
        :type proxy_url: ``str``
87 88
        """
88 89
        result = self._parse_proxy_url(proxy_url=proxy_url)
90 +
89 91
        scheme = result[0]
90 92
        host = result[1]
91 93
        port = result[2]
@@ -114,12 +116,12 @@
Loading
114 116
        """
115 117
        parsed = urlparse.urlparse(proxy_url)
116 118
117 -
        if parsed.scheme != 'http':
118 -
            raise ValueError('Only http proxies are supported')
119 +
        if parsed.scheme not in ('http', 'https'):
120 +
            raise ValueError('Only http and https proxies are supported')
119 121
120 122
        if not parsed.hostname or not parsed.port:
121 123
            raise ValueError('proxy_url must be in the following format: '
122 -
                             'http://<proxy host>:<proxy port>')
124 +
                             '<scheme>://<proxy host>:<proxy port>')
123 125
124 126
        proxy_scheme = parsed.scheme
125 127
        proxy_host, proxy_port = parsed.hostname, parsed.port
@@ -183,9 +185,16 @@
Loading
183 185
            host,
184 186
            ":{0}".format(port) if port not in (80, 443) else ""
185 187
        )
186 -
        # Support for HTTP proxy
187 -
        proxy_url_env = os.environ.get(HTTP_PROXY_ENV_VARIABLE_NAME, None)
188 -
        proxy_url = kwargs.pop('proxy_url', proxy_url_env)
188 +
189 +
        # Support for HTTP(s) proxy
190 +
        # NOTE: We always only use a single proxy (either HTTP or HTTPS)
191 +
        https_proxy_url_env = os.environ.get(HTTPS_PROXY_ENV_VARIABLE_NAME,
192 +
                                             None)
193 +
        http_proxy_url_env = os.environ.get(HTTP_PROXY_ENV_VARIABLE_NAME,
194 +
                                            https_proxy_url_env)
195 +
196 +
        # Connection argument rgument has precedence over environment variables
197 +
        proxy_url = kwargs.pop('proxy_url', http_proxy_url_env)
189 198
190 199
        self._setup_verify()
191 200
        self._setup_ca_cert()
Files Coverage
libcloud 85.90%
Project Totals (365 files) 85.90%
4756.11
TRAVIS_PYTHON_VERSION=2.7
TRAVIS_OS_NAME=linux
1
codecov:
2
  #notify:
3
    #require_ci_to_pass: yes
4

5
coverage:
6
  precision: 2         # decimal places to display: 0 <= value <= 4
7
  round: nearest
8
  range: 50...90      # custom range of coverage colors from red -> yellow -> green
9

10
  status:
11
    project:
12
      default:
13
        threshold: 2%
14
    patch: yes
15
    changes: no
16

17
comment:
18
  layout: "header, diff, tree"
19
  behavior: default
20
  require_changes: false  # if true: only post the comment if coverage changes
21
  branches: null
22
  flags: null
23
  paths: null
Sunburst
The inner-most circle is the entire project, moving away from the center are folders then, finally, a single file. The size and color of each slice is representing the number of statements and the coverage, respectively.
Icicle
The top section represents the entire project. Proceeding with folders and finally individual files. The size and color of each slice is representing the number of statements and the coverage, respectively.
Grid
Each block represents a single file in the project. The size and color of each block is represented by the number of statements and the coverage, respectively.
Loading