diff --git a/hobo/middleware/cookies_samesite.py b/hobo/middleware/cookies_samesite.py
index 2b455cd..c53edc2 100644
--- a/hobo/middleware/cookies_samesite.py
+++ b/hobo/middleware/cookies_samesite.py
@@ -15,7 +15,6 @@
# along with this program. If not, see .
from django.conf import settings
-from django.utils import six
from django.utils.deprecation import MiddlewareMixin
@@ -34,10 +33,6 @@ class CookiesSameSiteFixMiddleware(MiddlewareMixin):
return response
-if six.PY2:
- import Cookie
- Cookie.Morsel._reserved.setdefault('samesite', 'SameSite')
-else:
- # required for Python <3.8
- import http.cookies
- http.cookies.Morsel._reserved.setdefault('samesite', 'SameSite')
+# required for Python <3.8
+import http.cookies
+http.cookies.Morsel._reserved.setdefault('samesite', 'SameSite')
diff --git a/hobo/multitenant/threads.py b/hobo/multitenant/threads.py
index bac5b2b..18c44b9 100644
--- a/hobo/multitenant/threads.py
+++ b/hobo/multitenant/threads.py
@@ -14,167 +14,41 @@
# You should have received a copy of the GNU Affero General Public License
# along with this program. If not, see .
-import sys
import threading
-from django.utils import six
+
+_Thread_bootstrap_inner = threading.Thread._bootstrap_inner
+_Thread__init__ = threading.Thread.__init__
-if six.PY2:
- class TenantAwareThread(threading.Thread):
- def __init__(self, *args, **kwargs):
- from django.db import connection
- try:
- if hasattr(connection, 'get_tenant'):
- self.tenant = connection.get_tenant()
- else:
- self.tenant = None
- except RuntimeError:
- # this happens when ImportError is raised at startup; ignore
- # the error to let the real one be displayed.
- self.tenant = None
- super(TenantAwareThread, self).__init__(*args, **kwargs)
-
- def run(self):
- if self.tenant is not None:
- from django.db import connection
- old_tenant = connection.get_tenant()
- connection.set_tenant(self.tenant)
- try:
- super(TenantAwareThread, self).run()
- finally:
- connection.set_tenant(old_tenant)
- connection.close()
- else:
- super(TenantAwareThread, self).run()
-
- class _Timer(TenantAwareThread):
- """Call a function after a specified number of seconds:
-
- t = Timer(30.0, f, args=[], kwargs={})
- t.start()
- t.cancel() # stop the timer's action if it's still waiting
-
- """
-
- def __init__(self, interval, function, args=[], kwargs={}):
- super(_Timer, self).__init__()
- self.interval = interval
- self.function = function
- self.args = args
- self.kwargs = kwargs
- self.finished = threading.Event()
-
- def cancel(self):
- """Stop the timer if it hasn't finished yet"""
- self.finished.set()
-
- def run(self):
- self.finished.wait(self.interval)
- if not self.finished.is_set():
- self.function(*self.args, **self.kwargs)
- self.finished.set()
-
- class _MainThread(TenantAwareThread):
-
- def __init__(self):
- if six.PY3:
- super(_MainThread, self).__init__(name="MainThread", daemon=False)
- self._set_tstate_lock()
- self._started.set()
- self._set_ident()
- with threading._active_limbo_lock:
- threading._active[self._ident] = self
- else:
- super(_MainThread, self).__init__(name="MainThread")
- self._Thread__started.set()
- self._set_ident()
- with threading._active_limbo_lock:
- threading._active[threading._get_ident()] = self
-
- def _set_daemon(self):
- return False
-
- def _exitfunc(self):
- self._Thread__stop()
- t = threading._pickSomeNonDaemonThread()
- if t:
- if __debug__:
- self._note("%s: waiting for other threads", self)
- while t:
- t.join()
- t = threading._pickSomeNonDaemonThread()
- if __debug__:
- self._note("%s: exiting", self)
- self._Thread__delete()
-
- class _DummyThread(TenantAwareThread):
- def __init__(self):
- if six.PY3:
- super(_DummyThread, self).__init__(name=threading._newname("Dummy-%d"), daemon=True)
- self._started.set()
- self._set_ident()
- with threading._active_limbo_lock:
- threading._active[self._ident] = self
- return
-
- super(_DummyThread, self).__init__(name=threading._newname("Dummy-%d"))
-
- # Thread.__block consumes an OS-level locking primitive, which
- # can never be used by a _DummyThread. Since a _DummyThread
- # instance is immortal, that's bad, so release this resource.
- del self._Thread__block
-
- self._Thread__started.set()
- self._set_ident()
- with threading._active_limbo_lock:
- threading._active[threading._get_ident()] = self
-
- def _set_daemon(self):
- return True
-
- def join(self, timeout=None):
- assert False, "cannot join a dummy thread"
-
- def install_tenant_aware_threads():
- if getattr(threading, 'multitenant', False):
- return
- # Install tenant aware Thread class
- threading.Thread = TenantAwareThread
- threading._DummyThread = _DummyThread
- threading._MainThread = _MainThread
- threading._Timer = _Timer
- threading.multitenant = True
-else:
- _Thread_bootstrap_inner = threading.Thread._bootstrap_inner
- _Thread__init__ = threading.Thread.__init__
-
- def _new__init__(self, *args, **kwargs):
- from django.db import connection
- try:
- if hasattr(connection, 'get_tenant'):
- self.tenant = connection.get_tenant()
- else:
- self.tenant = None
- except RuntimeError:
- # this happens when ImportError is raised at startup; ignore
- # the error to let the real one be displayed.
- self.tenant = None
- _Thread__init__(self, *args, **kwargs)
-
- def _new_bootstrap_inner(self):
- if self.tenant is not None:
- from django.db import connection
- old_tenant = connection.get_tenant()
- connection.set_tenant(self.tenant)
- try:
- _Thread_bootstrap_inner(self)
- finally:
- connection.set_tenant(old_tenant)
- connection.close()
+def _new__init__(self, *args, **kwargs):
+ from django.db import connection
+ try:
+ if hasattr(connection, 'get_tenant'):
+ self.tenant = connection.get_tenant()
else:
- _Thread_bootstrap_inner(self)
+ self.tenant = None
+ except RuntimeError:
+ # this happens when ImportError is raised at startup; ignore
+ # the error to let the real one be displayed.
+ self.tenant = None
+ _Thread__init__(self, *args, **kwargs)
- def install_tenant_aware_threads():
- threading.Thread.__init__ = _new__init__
- threading.Thread._bootstrap_inner = _new_bootstrap_inner
+
+def _new_bootstrap_inner(self):
+ if self.tenant is not None:
+ from django.db import connection
+ old_tenant = connection.get_tenant()
+ connection.set_tenant(self.tenant)
+ try:
+ _Thread_bootstrap_inner(self)
+ finally:
+ connection.set_tenant(old_tenant)
+ connection.close()
+ else:
+ _Thread_bootstrap_inner(self)
+
+
+def install_tenant_aware_threads():
+ threading.Thread.__init__ = _new__init__
+ threading.Thread._bootstrap_inner = _new_bootstrap_inner
diff --git a/hobo/signature.py b/hobo/signature.py
index 8ac3fea..61a7ec6 100644
--- a/hobo/signature.py
+++ b/hobo/signature.py
@@ -77,10 +77,6 @@ def check_string(s, signature, key, algo='sha256'):
if len(signature2) != len(signature):
return False
res = 0
- if six.PY3:
- for a, b in zip(signature, signature2):
- res |= a ^ b
- else:
- for a, b in zip(signature, signature2):
- res |= ord(a) ^ ord(b)
+ for a, b in zip(signature, signature2):
+ res |= a ^ b
return res == 0
diff --git a/tests/test_emails.py b/tests/test_emails.py
index fd163f9..e6a3724 100644
--- a/tests/test_emails.py
+++ b/tests/test_emails.py
@@ -12,7 +12,6 @@ import socket
import threading
from django.core.exceptions import ValidationError
-from django.utils import six
from django.utils.encoding import force_text
from hobo.emails.validators import validate_email_address
@@ -62,12 +61,8 @@ def dns_resolver(monkeypatch, port_available):
def smtp_server(monkeypatch, port_available):
class RecipientValidatingSMTPChannel(smtpd.SMTPChannel):
def smtp_RCPT(self, arg):
- if six.PY2:
- address = self._SMTPChannel__getaddr('TO:', arg)
- domain = address.split('@')[-1]
- else:
- address = self._getaddr(arg)
- domain = address[1].split('@')[-1][:-1]
+ address = self._getaddr(arg)
+ domain = address[1].split('@')[-1][:-1]
if domain in ('example.com', 'example-spf.com', 'example-spf-allow-all.com', 'example-invalid-spf.com'):
self._SMTPChannel__rcpttos.append(address)
self.push('250 Ok')
diff --git a/tests/test_hobo_deploy.py b/tests/test_hobo_deploy.py
index 6ada766..c0a5aa3 100644
--- a/tests/test_hobo_deploy.py
+++ b/tests/test_hobo_deploy.py
@@ -8,7 +8,6 @@ import pytest
from mock import call, patch, Mock
from requests import Response, exceptions
-from django.utils import six
from django.utils.six import StringIO
from hobo.agent.common.management.commands.hobo_deploy import (
@@ -65,12 +64,8 @@ def test_handle_from_scratch():
command.deploy.reset_mock()
with patch('hobo.agent.common.management.commands.hobo_deploy.open') as mocked_open:
mocked_open.side_effect = [StringIO('malformated JSON')]
- if six.PY2:
- with pytest.raises(ValueError, match='No JSON object could be decoded'):
- command.handle('https://combo.dev.publik.love/', 'env.json')
- else:
- with pytest.raises(json.decoder.JSONDecodeError):
- command.handle('https://combo.dev.publik.love/', 'env.json')
+ with pytest.raises(json.decoder.JSONDecodeError):
+ command.handle('https://combo.dev.publik.love/', 'env.json')
assert command.deploy.mock_calls == []
# missing args
diff --git a/tests_multitenant/test_agent_worker.py b/tests_multitenant/test_agent_worker.py
index f70ece6..9abec6e 100644
--- a/tests_multitenant/test_agent_worker.py
+++ b/tests_multitenant/test_agent_worker.py
@@ -4,7 +4,6 @@ import json
import mock
import os
import pytest
-import six
from django.utils.encoding import force_text
@@ -118,10 +117,7 @@ def test_deploy_host_with_agent_patterns(mocked_subprocess, mocked_exists, local
mocked_subprocess.Popen = mock.Mock(return_value=mocked_opened)
# load AGENT_HOST_PATTERNS from local_settings fixture
- if six.PY2:
- reload(settings)
- else:
- importlib.reload(settings)
+ importlib.reload(settings)
deploy(ENVIRONMENT)
# process called
mock_calls = set(x[1][0] for x in mocked_subprocess.Popen.mock_calls)
diff --git a/tests_multitenant/test_tenant_command.py b/tests_multitenant/test_tenant_command.py
index 131b5cf..5fc8064 100644
--- a/tests_multitenant/test_tenant_command.py
+++ b/tests_multitenant/test_tenant_command.py
@@ -7,7 +7,6 @@ import sys
from django.core.management import BaseCommand, call_command, load_command_class
from django.utils.encoding import force_bytes
-from django.utils import six
from django.core.management.base import CommandError
from hobo.multitenant.models import Tenant
@@ -124,10 +123,7 @@ def test_tenant_command_all_tenants_errors(tenants, monkeypatch, capsys):
klass.run_from_argv(['manage.py', 'tenant_command', 'bytes-error', '--all-tenants'])
captured = capsys.readouterr()
- if six.PY2:
- assert u'héhé' in captured.err
- else:
- assert repr(force_bytes('héhé')) in captured.err
+ assert repr(force_bytes('héhé')) in captured.err
with pytest.raises(SystemExit):
klass.run_from_argv(['manage.py', 'tenant_command', 'mix-error', '--all-tenants'])