Gentoo Archives: gentoo-commits

From: Louis Sautier <sbraz@g.o>
To: gentoo-commits@l.g.o
Subject: [gentoo-commits] repo/gentoo:master commit in: dev-python/websockify/, dev-python/websockify/files/
Date: Tue, 29 Sep 2020 12:13:46
Message-Id: 1601381523.2f08b0dbe5e632631acd5a426b523455c0654524.sbraz@gentoo
1 commit: 2f08b0dbe5e632631acd5a426b523455c0654524
2 Author: Louis Sautier <sbraz <AT> gentoo <DOT> org>
3 AuthorDate: Tue Sep 29 12:12:03 2020 +0000
4 Commit: Louis Sautier <sbraz <AT> gentoo <DOT> org>
5 CommitDate: Tue Sep 29 12:12:03 2020 +0000
6 URL: https://gitweb.gentoo.org/repo/gentoo.git/commit/?id=2f08b0db
7
8 dev-python/websockify: add Python 3.{8,9} support, tests, manpage
9
10 Package-Manager: Portage-3.0.8, Repoman-3.0.1
11 Signed-off-by: Louis Sautier <sbraz <AT> gentoo.org>
12
13 .../files/websockify-0.9.0-mock-tests.patch | 392 +++++++++++++++++++++
14 dev-python/websockify/websockify-0.9.0-r1.ebuild | 31 ++
15 2 files changed, 423 insertions(+)
16
17 diff --git a/dev-python/websockify/files/websockify-0.9.0-mock-tests.patch b/dev-python/websockify/files/websockify-0.9.0-mock-tests.patch
18 new file mode 100644
19 index 00000000000..a6af9508e07
20 --- /dev/null
21 +++ b/dev-python/websockify/files/websockify-0.9.0-mock-tests.patch
22 @@ -0,0 +1,392 @@
23 +From 992e09eac484f25871b7fcfc6d11b8e5beac9edb Mon Sep 17 00:00:00 2001
24 +From: Pierre Ossman <ossman@××××××.se>
25 +Date: Fri, 21 Aug 2020 10:50:11 +0200
26 +Subject: [PATCH] Convert tests from mox to mock
27 +
28 +mox is deprecated upstream in favour of mock
29 +---
30 + test-requirements.txt | 2 +-
31 + tests/test_websocketproxy.py | 34 ++++------
32 + tests/test_websockifyserver.py | 111 +++++++++++++--------------------
33 + 3 files changed, 58 insertions(+), 89 deletions(-)
34 +
35 +diff --git a/test-requirements.txt b/test-requirements.txt
36 +index a63a15e..8e01437 100644
37 +--- a/test-requirements.txt
38 ++++ b/test-requirements.txt
39 +@@ -1,4 +1,4 @@
40 +-mox3
41 ++mock
42 + nose
43 + jwcrypto;python_version>="2.7"
44 + redis;python_version>="2.7"
45 +diff --git a/tests/test_websocketproxy.py b/tests/test_websocketproxy.py
46 +index c0a8d93..d8a4916 100644
47 +--- a/tests/test_websocketproxy.py
48 ++++ b/tests/test_websocketproxy.py
49 +@@ -20,10 +20,11 @@
50 + import unittest
51 + import unittest
52 + import socket
53 ++try:
54 ++ from mock import patch
55 ++except ImportError:
56 ++ from unittest.mock import patch
57 +
58 +-from mox3 import stubout
59 +-
60 +-from websockify import websockifyserver
61 + from websockify import websocketproxy
62 + from websockify import token_plugins
63 + from websockify import auth_plugins
64 +@@ -74,16 +75,14 @@ def __init__(self):
65 + class ProxyRequestHandlerTestCase(unittest.TestCase):
66 + def setUp(self):
67 + super(ProxyRequestHandlerTestCase, self).setUp()
68 +- self.stubs = stubout.StubOutForTesting()
69 + self.handler = websocketproxy.ProxyRequestHandler(
70 + FakeSocket(''), "127.0.0.1", FakeServer())
71 + self.handler.path = "https://localhost:6080/websockify?token=blah"
72 + self.handler.headers = None
73 +- self.stubs.Set(websockifyserver.WebSockifyServer, 'socket',
74 +- staticmethod(lambda *args, **kwargs: None))
75 ++ patch('websockify.websockifyserver.WebSockifyServer.socket').start()
76 +
77 + def tearDown(self):
78 +- self.stubs.UnsetAll()
79 ++ patch.stopall()
80 + super(ProxyRequestHandlerTestCase, self).tearDown()
81 +
82 + def test_get_target(self):
83 +@@ -120,8 +119,7 @@ class TestPlugin(token_plugins.BasePlugin):
84 + def lookup(self, token):
85 + return (self.source + token).split(',')
86 +
87 +- self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error',
88 +- staticmethod(lambda *args, **kwargs: None))
89 ++ patcher = patch('websockify.websocketproxy.ProxyRequestHandler.send_auth_error').start()
90 +
91 + self.handler.server.token_plugin = TestPlugin("somehost,")
92 + self.handler.validate_connection()
93 +@@ -138,8 +136,7 @@ def test_asymmetric_jws_token_plugin(self):
94 + jwt_token.make_signed_token(key)
95 + self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format(jwt_token=jwt_token.serialize())
96 +
97 +- self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error',
98 +- staticmethod(lambda *args, **kwargs: None))
99 ++ patcher = patch('websockify.websocketproxy.ProxyRequestHandler.send_auth_error').start()
100 +
101 + self.handler.server.token_plugin = token_plugins.JWTTokenApi("./tests/fixtures/public.pem")
102 + self.handler.validate_connection()
103 +@@ -155,8 +152,7 @@ def test_asymmetric_jws_token_plugin_with_illigal_key_exception(self):
104 + jwt_token.make_signed_token(key)
105 + self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format(jwt_token=jwt_token.serialize())
106 +
107 +- self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error',
108 +- staticmethod(lambda *args, **kwargs: None))
109 ++ patcher = patch('websockify.websocketproxy.ProxyRequestHandler.send_auth_error').start()
110 +
111 + self.handler.server.token_plugin = token_plugins.JWTTokenApi("wrong.pub")
112 + self.assertRaises(self.handler.server.EClose,
113 +@@ -171,8 +167,7 @@ def test_symmetric_jws_token_plugin(self):
114 + jwt_token.make_signed_token(key)
115 + self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format(jwt_token=jwt_token.serialize())
116 +
117 +- self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error',
118 +- staticmethod(lambda *args, **kwargs: None))
119 ++ patcher = patch('websockify.websocketproxy.ProxyRequestHandler.send_auth_error').start()
120 +
121 + self.handler.server.token_plugin = token_plugins.JWTTokenApi("./tests/fixtures/symmetric.key")
122 + self.handler.validate_connection()
123 +@@ -188,8 +183,7 @@ def test_symmetric_jws_token_plugin_with_illigal_key_exception(self):
124 + jwt_token.make_signed_token(key)
125 + self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format(jwt_token=jwt_token.serialize())
126 +
127 +- self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error',
128 +- staticmethod(lambda *args, **kwargs: None))
129 ++ patcher = patch('websockify.websocketproxy.ProxyRequestHandler.send_auth_error').start()
130 +
131 + self.handler.server.token_plugin = token_plugins.JWTTokenApi("wrong_sauce")
132 + self.assertRaises(self.handler.server.EClose,
133 +@@ -210,8 +204,7 @@ def test_asymmetric_jwe_token_plugin(self):
134 +
135 + self.handler.path = "https://localhost:6080/websockify?token={jwt_token}".format(jwt_token=jwe_token.serialize())
136 +
137 +- self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error',
138 +- staticmethod(lambda *args, **kwargs: None))
139 ++ patcher = patch('websockify.websocketproxy.ProxyRequestHandler.send_auth_error').start()
140 +
141 + self.handler.server.token_plugin = token_plugins.JWTTokenApi("./tests/fixtures/private.pem")
142 + self.handler.validate_connection()
143 +@@ -225,8 +218,7 @@ def authenticate(self, headers, target_host, target_port):
144 + if target_host == self.source:
145 + raise auth_plugins.AuthenticationError(response_msg="some_error")
146 +
147 +- self.stubs.Set(websocketproxy.ProxyRequestHandler, 'send_auth_error',
148 +- staticmethod(lambda *args, **kwargs: None))
149 ++ patcher = patch('websockify.websocketproxy.ProxyRequestHandler.send_auth_error').start()
150 +
151 + self.handler.server.auth_plugin = TestPlugin("somehost")
152 + self.handler.server.target_host = "somehost"
153 +diff --git a/tests/test_websockifyserver.py b/tests/test_websockifyserver.py
154 +index b9312dc..a089f55 100644
155 +--- a/tests/test_websockifyserver.py
156 ++++ b/tests/test_websockifyserver.py
157 +@@ -22,7 +22,10 @@
158 + import shutil
159 + import socket
160 + import ssl
161 +-from mox3 import stubout
162 ++try:
163 ++ from mock import patch, MagicMock, ANY
164 ++except ImportError:
165 ++ from unittest.mock import patch, MagicMock, ANY
166 + import sys
167 + import tempfile
168 + import unittest
169 +@@ -73,22 +76,13 @@ def makefile(self, mode='r', buffsize=None):
170 + class WebSockifyRequestHandlerTestCase(unittest.TestCase):
171 + def setUp(self):
172 + super(WebSockifyRequestHandlerTestCase, self).setUp()
173 +- self.stubs = stubout.StubOutForTesting()
174 + self.tmpdir = tempfile.mkdtemp('-websockify-tests')
175 + # Mock this out cause it screws tests up
176 +- self.stubs.Set(os, 'chdir', lambda *args, **kwargs: None)
177 +- self.stubs.Set(BaseHTTPRequestHandler, 'send_response',
178 +- lambda *args, **kwargs: None)
179 +-
180 +- def fake_send_error(self, code, message=None, explain=None):
181 +- self.last_code = code
182 +-
183 +- self.stubs.Set(BaseHTTPRequestHandler, 'send_error',
184 +- fake_send_error)
185 ++ patch('os.chdir').start()
186 +
187 + def tearDown(self):
188 + """Called automatically after each test."""
189 +- self.stubs.UnsetAll()
190 ++ patch.stopall()
191 + os.rmdir(self.tmpdir)
192 + super(WebSockifyRequestHandlerTestCase, self).tearDown()
193 +
194 +@@ -101,47 +95,36 @@ def _get_server(self, handler_class=websockifyserver.WebSockifyRequestHandler,
195 + record=self.tmpdir, daemon=False, ssl_only=0, idle_timeout=1,
196 + **kwargs)
197 +
198 +- def test_normal_get_with_only_upgrade_returns_error(self):
199 ++ @patch('websockify.websockifyserver.WebSockifyRequestHandler.send_error')
200 ++ def test_normal_get_with_only_upgrade_returns_error(self, send_error):
201 + server = self._get_server(web=None)
202 + handler = websockifyserver.WebSockifyRequestHandler(
203 + FakeSocket('GET /tmp.txt HTTP/1.1'), '127.0.0.1', server)
204 +
205 +- def fake_send_response(self, code, message=None):
206 +- self.last_code = code
207 +-
208 +- self.stubs.Set(BaseHTTPRequestHandler, 'send_response',
209 +- fake_send_response)
210 +-
211 + handler.do_GET()
212 +- self.assertEqual(handler.last_code, 405)
213 ++ send_error.assert_called_with(405, ANY)
214 +
215 +- def test_list_dir_with_file_only_returns_error(self):
216 ++ @patch('websockify.websockifyserver.WebSockifyRequestHandler.send_error')
217 ++ def test_list_dir_with_file_only_returns_error(self, send_error):
218 + server = self._get_server(file_only=True)
219 + handler = websockifyserver.WebSockifyRequestHandler(
220 + FakeSocket('GET / HTTP/1.1'), '127.0.0.1', server)
221 +
222 +- def fake_send_response(self, code, message=None):
223 +- self.last_code = code
224 +-
225 +- self.stubs.Set(BaseHTTPRequestHandler, 'send_response',
226 +- fake_send_response)
227 +-
228 + handler.path = '/'
229 + handler.do_GET()
230 +- self.assertEqual(handler.last_code, 404)
231 ++ send_error.assert_called_with(404, ANY)
232 +
233 +
234 + class WebSockifyServerTestCase(unittest.TestCase):
235 + def setUp(self):
236 + super(WebSockifyServerTestCase, self).setUp()
237 +- self.stubs = stubout.StubOutForTesting()
238 + self.tmpdir = tempfile.mkdtemp('-websockify-tests')
239 + # Mock this out cause it screws tests up
240 +- self.stubs.Set(os, 'chdir', lambda *args, **kwargs: None)
241 ++ patch('os.chdir').start()
242 +
243 + def tearDown(self):
244 + """Called automatically after each test."""
245 +- self.stubs.UnsetAll()
246 ++ patch.stopall()
247 + os.rmdir(self.tmpdir)
248 + super(WebSockifyServerTestCase, self).tearDown()
249 +
250 +@@ -154,10 +137,10 @@ def _get_server(self, handler_class=websockifyserver.WebSockifyRequestHandler,
251 +
252 + def test_daemonize_raises_error_while_closing_fds(self):
253 + server = self._get_server(daemon=True, ssl_only=1, idle_timeout=1)
254 +- self.stubs.Set(os, 'fork', lambda *args: 0)
255 +- self.stubs.Set(signal, 'signal', lambda *args: None)
256 +- self.stubs.Set(os, 'setsid', lambda *args: None)
257 +- self.stubs.Set(os, 'close', raise_oserror)
258 ++ patch('os.fork').start().return_value = 0
259 ++ patch('signal.signal').start()
260 ++ patch('os.setsid').start()
261 ++ patch('os.close').start().side_effect = raise_oserror
262 + self.assertRaises(OSError, server.daemonize, keepfd=None, chdir='./')
263 +
264 + def test_daemonize_ignores_ebadf_error_while_closing_fds(self):
265 +@@ -165,11 +148,11 @@ def raise_oserror_ebadf(fd):
266 + raise OSError(errno.EBADF, 'fake error')
267 +
268 + server = self._get_server(daemon=True, ssl_only=1, idle_timeout=1)
269 +- self.stubs.Set(os, 'fork', lambda *args: 0)
270 +- self.stubs.Set(os, 'setsid', lambda *args: None)
271 +- self.stubs.Set(signal, 'signal', lambda *args: None)
272 +- self.stubs.Set(os, 'close', raise_oserror_ebadf)
273 +- self.stubs.Set(os, 'open', raise_oserror)
274 ++ patch('os.fork').start().return_value = 0
275 ++ patch('signal.signal').start()
276 ++ patch('os.setsid').start()
277 ++ patch('os.close').start().side_effect = raise_oserror_ebadf
278 ++ patch('os.open').start().side_effect = raise_oserror
279 + self.assertRaises(OSError, server.daemonize, keepfd=None, chdir='./')
280 +
281 + def test_handshake_fails_on_not_ready(self):
282 +@@ -178,7 +161,7 @@ def test_handshake_fails_on_not_ready(self):
283 + def fake_select(rlist, wlist, xlist, timeout=None):
284 + return ([], [], [])
285 +
286 +- self.stubs.Set(select, 'select', fake_select)
287 ++ patch('select.select').start().side_effect = fake_select
288 + self.assertRaises(
289 + websockifyserver.WebSockifyServer.EClose, server.do_handshake,
290 + FakeSocket(), '127.0.0.1')
291 +@@ -191,7 +174,7 @@ def test_empty_handshake_fails(self):
292 + def fake_select(rlist, wlist, xlist, timeout=None):
293 + return ([sock], [], [])
294 +
295 +- self.stubs.Set(select, 'select', fake_select)
296 ++ patch('select.select').start().side_effect = fake_select
297 + self.assertRaises(
298 + websockifyserver.WebSockifyServer.EClose, server.do_handshake,
299 + sock, '127.0.0.1')
300 +@@ -208,7 +191,7 @@ def test_handshake_ssl_only_without_ssl_raises_error(self):
301 + def fake_select(rlist, wlist, xlist, timeout=None):
302 + return ([sock], [], [])
303 +
304 +- self.stubs.Set(select, 'select', fake_select)
305 ++ patch('select.select').start().side_effect = fake_select
306 + self.assertRaises(
307 + websockifyserver.WebSockifyServer.EClose, server.do_handshake,
308 + sock, '127.0.0.1')
309 +@@ -230,7 +213,7 @@ def __init__(self, *args, **kwargs):
310 + def fake_select(rlist, wlist, xlist, timeout=None):
311 + return ([sock], [], [])
312 +
313 +- self.stubs.Set(select, 'select', fake_select)
314 ++ patch('select.select').start().side_effect = fake_select
315 + self.assertEqual(server.do_handshake(sock, '127.0.0.1'), sock)
316 + self.assertTrue(FakeHandler.CALLED, True)
317 +
318 +@@ -251,7 +234,7 @@ def test_do_handshake_ssl_without_cert_raises_error(self):
319 + def fake_select(rlist, wlist, xlist, timeout=None):
320 + return ([sock], [], [])
321 +
322 +- self.stubs.Set(select, 'select', fake_select)
323 ++ patch('select.select').start().side_effect = fake_select
324 + self.assertRaises(
325 + websockifyserver.WebSockifyServer.EClose, server.do_handshake,
326 + sock, '127.0.0.1')
327 +@@ -280,13 +263,13 @@ def load_verify_locations(self, cafile):
328 + def wrap_socket(self, *args, **kwargs):
329 + raise ssl.SSLError(ssl.SSL_ERROR_EOF)
330 +
331 +- self.stubs.Set(select, 'select', fake_select)
332 ++ patch('select.select').start().side_effect = fake_select
333 + if (hasattr(ssl, 'create_default_context')):
334 + # for recent versions of python
335 +- self.stubs.Set(ssl, 'create_default_context', fake_create_default_context)
336 ++ patch('ssl.create_default_context').start().side_effect = fake_create_default_context
337 + else:
338 + # for fallback for old versions of python
339 +- self.stubs.Set(ssl, 'wrap_socket', fake_wrap_socket)
340 ++ patch('ssl.warp_socket').start().side_effect = fake_wrap_socket
341 + self.assertRaises(
342 + websockifyserver.WebSockifyServer.EClose, server.do_handshake,
343 + sock, '127.0.0.1')
344 +@@ -321,10 +304,10 @@ def wrap_socket(self, *args, **kwargs):
345 + def set_ciphers(self, ciphers_to_set):
346 + fake_create_default_context.CIPHERS = ciphers_to_set
347 +
348 +- self.stubs.Set(select, 'select', fake_select)
349 ++ patch('select.select').start().side_effect = fake_select
350 + if (hasattr(ssl, 'create_default_context')):
351 + # for recent versions of python
352 +- self.stubs.Set(ssl, 'create_default_context', fake_create_default_context)
353 ++ patch('ssl.create_default_context').start().side_effect = fake_create_default_context
354 + server.do_handshake(sock, '127.0.0.1')
355 + self.assertEqual(fake_create_default_context.CIPHERS, test_ciphers)
356 + else:
357 +@@ -365,10 +348,10 @@ def set_options(self, val):
358 + fake_create_default_context.OPTIONS = val
359 + options = property(get_options, set_options)
360 +
361 +- self.stubs.Set(select, 'select', fake_select)
362 ++ patch('select.select').start().side_effect = fake_select
363 + if (hasattr(ssl, 'create_default_context')):
364 + # for recent versions of python
365 +- self.stubs.Set(ssl, 'create_default_context', fake_create_default_context)
366 ++ patch('ssl.create_default_context').start().side_effect = fake_create_default_context
367 + server.do_handshake(sock, '127.0.0.1')
368 + self.assertEqual(fake_create_default_context.OPTIONS, test_options)
369 + else:
370 +@@ -387,11 +370,9 @@ def test_start_server_error(self):
371 + def fake_select(rlist, wlist, xlist, timeout=None):
372 + raise Exception("fake error")
373 +
374 +- self.stubs.Set(websockifyserver.WebSockifyServer, 'socket',
375 +- lambda *args, **kwargs: sock)
376 +- self.stubs.Set(websockifyserver.WebSockifyServer, 'daemonize',
377 +- lambda *args, **kwargs: None)
378 +- self.stubs.Set(select, 'select', fake_select)
379 ++ patch('websockify.websockifyserver.WebSockifyServer.socket').start()
380 ++ patch('websockify.websockifyserver.WebSockifyServer.daemonize').start()
381 ++ patch('select.select').start().side_effect = fake_select
382 + server.start_server()
383 +
384 + def test_start_server_keyboardinterrupt(self):
385 +@@ -401,11 +382,9 @@ def test_start_server_keyboardinterrupt(self):
386 + def fake_select(rlist, wlist, xlist, timeout=None):
387 + raise KeyboardInterrupt
388 +
389 +- self.stubs.Set(websockifyserver.WebSockifyServer, 'socket',
390 +- lambda *args, **kwargs: sock)
391 +- self.stubs.Set(websockifyserver.WebSockifyServer, 'daemonize',
392 +- lambda *args, **kwargs: None)
393 +- self.stubs.Set(select, 'select', fake_select)
394 ++ patch('websockify.websockifyserver.WebSockifyServer.socket').start()
395 ++ patch('websockify.websockifyserver.WebSockifyServer.daemonize').start()
396 ++ patch('select.select').start().side_effect = fake_select
397 + server.start_server()
398 +
399 + def test_start_server_systemexit(self):
400 +@@ -415,11 +394,9 @@ def test_start_server_systemexit(self):
401 + def fake_select(rlist, wlist, xlist, timeout=None):
402 + sys.exit()
403 +
404 +- self.stubs.Set(websockifyserver.WebSockifyServer, 'socket',
405 +- lambda *args, **kwargs: sock)
406 +- self.stubs.Set(websockifyserver.WebSockifyServer, 'daemonize',
407 +- lambda *args, **kwargs: None)
408 +- self.stubs.Set(select, 'select', fake_select)
409 ++ patch('websockify.websockifyserver.WebSockifyServer.socket').start()
410 ++ patch('websockify.websockifyserver.WebSockifyServer.daemonize').start()
411 ++ patch('select.select').start().side_effect = fake_select
412 + server.start_server()
413 +
414 + def test_socket_set_keepalive_options(self):
415
416 diff --git a/dev-python/websockify/websockify-0.9.0-r1.ebuild b/dev-python/websockify/websockify-0.9.0-r1.ebuild
417 new file mode 100644
418 index 00000000000..9e822032c71
419 --- /dev/null
420 +++ b/dev-python/websockify/websockify-0.9.0-r1.ebuild
421 @@ -0,0 +1,31 @@
422 +# Copyright 1999-2020 Gentoo Authors
423 +# Distributed under the terms of the GNU General Public License v2
424 +
425 +EAPI=7
426 +
427 +PYTHON_COMPAT=( python3_{6..9} )
428 +# entry_points is used
429 +DISTUTILS_USE_SETUPTOOLS=rdepend
430 +
431 +inherit distutils-r1
432 +
433 +SRC_URI="https://github.com/kanaka/${PN}/archive/v${PV}.tar.gz -> ${P}.tar.gz"
434 +DESCRIPTION="WebSockets support for any application/server"
435 +HOMEPAGE="https://github.com/kanaka/websockify"
436 +
437 +LICENSE="LGPL-3"
438 +SLOT="0"
439 +KEYWORDS="~amd64 ~x86"
440 +
441 +RDEPEND="dev-python/numpy[${PYTHON_USEDEP}]"
442 +BDEPEND="test? ( dev-python/jwcrypto[${PYTHON_USEDEP}] )"
443 +
444 +# Backport a patch removing the need for mox3
445 +PATCHES=( "${FILESDIR}/${P}-mock-tests.patch" )
446 +
447 +distutils_enable_tests nose
448 +
449 +python_install_all() {
450 + doman docs/${PN}.1
451 + distutils-r1_python_install_all
452 +}