diff --git a/askbot/admin.py b/askbot/admin.py
index c5e2ce6555..61103f832d 100644
--- a/askbot/admin.py
+++ b/askbot/admin.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
"""
:synopsis: connector to standard Django admin interface
diff --git a/askbot/bin/generate_modules.py b/askbot/bin/generate_modules.py
index ddaf557d12..fcba59060e 100755
--- a/askbot/bin/generate_modules.py
+++ b/askbot/bin/generate_modules.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# Miville
# Copyright (C) 2008 Société des arts technologiques (SAT)
# http://www.sat.qc.ca
@@ -39,7 +38,7 @@
def create_file_name(base, opts):
"""Create file name from base name, path and suffix"""
- return os.path.join(opts.destdir, "%s.%s" % (base, opts.suffix))
+ return os.path.join(opts.destdir, f"{base}.{opts.suffix}")
def write_automodule_directive(module):
@@ -61,13 +60,13 @@ def write_heading(module, kind='Module'):
def write_sub(module, kind='Module'):
"""Create the module subtitle"""
- sub = title_line('The :mod:`%s` %s' % (module, kind), '-')
+ sub = title_line(f'The :mod:`{module}` {kind}', '-')
return sub
def title_line(title, char):
""" Underline the title with the character pass, with the right length."""
- return ':mod:`%s`\n%s\n\n' % (title, len(title) * char)
+ return f':mod:`{title}`\n{len(title) * char}\n\n'
def create_module_content(module):
@@ -108,7 +107,7 @@ def create_package_content(package, py_files, sub_packages):
# __init__.py of the current module
continue
py_file = os.path.splitext(py_file)[0]
- text += '* :ref:`%s.%s`\n' % (package, py_file)
+ text += f'* :ref:`{package}.{py_file}`\n'
text += '\n'
# create links to sub-packages
@@ -119,7 +118,7 @@ def create_package_content(package, py_files, sub_packages):
text += '\n'
for sub in sub_packages:
# TODO - add description here
- text += '* :ref:`%s.%s`\n' % (package, sub)
+ text += f'* :ref:`{package}.{sub}`\n'
return text
# build toctree for the package page
# text += '.. toctree::\n\n'
@@ -149,7 +148,7 @@ def check_for_code(module):
"""
Check if there's at least one class or one function in the module.
"""
- fd = open(module, 'r')
+ fd = open(module)
for line in fd:
if line.startswith('def ') or line.startswith('class '):
fd.close()
diff --git a/askbot/conf/settings_wrapper.py b/askbot/conf/settings_wrapper.py
index 194b67eedb..2f26491f4f 100644
--- a/askbot/conf/settings_wrapper.py
+++ b/askbot/conf/settings_wrapper.py
@@ -45,7 +45,7 @@ def assert_setting_info_correct(info):
assert isinstance(info[2], bool)
-class ConfigSettings(object):
+class ConfigSettings:
"""A very simple Singleton wrapper for settings
a limitation is that all settings names using this class
must be distinct, even though they might belong
@@ -139,7 +139,7 @@ def get_setting_url(self, data):
'livesettings_group',
setting_name, # TODO: better use description
kwargs={'group': group_name},
- anchor='id_%s__%s__%s' % (group_name, setting_name, get_language())
+ anchor=f'id_{group_name}__{setting_name}__{get_language()}'
)
if len(data) == 4:
return force_str(format_lazy('{} ({})',link, data[3]))
@@ -227,7 +227,7 @@ def prime_cache(cls, cache_key, **kwargs):
else:
setting_value = cls.__instance[key]
if setting_value.localized:
- db_key = '{}_{}'.format(key, format_setting_name(get_language()))
+ db_key = f'{key}_{format_setting_name(get_language())}'
else:
db_key = key
diff --git a/askbot/const/__init__.py b/askbot/const/__init__.py
index 02a535d447..c1ab40ffc6 100644
--- a/askbot/const/__init__.py
+++ b/askbot/const/__init__.py
@@ -1,4 +1,3 @@
-# encoding:utf-8
"""
All constants could be used in other modules
For reasons that models, views can't have unicode
@@ -179,7 +178,7 @@
TAG_CHARS = r'\wp{M}+.#-'
TAG_FIRST_CHARS = r'[\wp{M}]'
TAG_FORBIDDEN_FIRST_CHARS = r'#'
-TAG_REGEX_BARE = r'%s[%s]+' % (TAG_FIRST_CHARS, TAG_CHARS)
+TAG_REGEX_BARE = rf'{TAG_FIRST_CHARS}[{TAG_CHARS}]+'
TAG_REGEX = r'^%s$' % TAG_REGEX_BARE
TAG_STRIP_CHARS = ', '
diff --git a/askbot/deployment/deployers/file_deployer.py b/askbot/deployment/deployers/file_deployer.py
index aaab8b9976..f41c710127 100644
--- a/askbot/deployment/deployers/file_deployer.py
+++ b/askbot/deployment/deployers/file_deployer.py
@@ -27,7 +27,7 @@ def get_template_parameters(self): # pylint: disable=no-self-use
def get_template(self):
"""Returns string representation of the template"""
- return open(get_askbot_module_path(self.template_path), 'r').read()
+ return open(get_askbot_module_path(self.template_path)).read()
def deploy_file(self, contents):
"""Writes contents into the target file"""
diff --git a/askbot/deployment/deployers/settings_py_admins_snippet.py b/askbot/deployment/deployers/settings_py_admins_snippet.py
index caef9fc77d..a3424f5b5f 100644
--- a/askbot/deployment/deployers/settings_py_admins_snippet.py
+++ b/askbot/deployment/deployers/settings_py_admins_snippet.py
@@ -9,4 +9,4 @@ def render(self):
"""--admin-settings override the default"""
if self.params['admin_settings']:
return self.params['admin_settings']
- return super(SettingsPyAdminsSnippet, self).render()
+ return super().render()
diff --git a/askbot/deployment/deployers/settings_py_caching_snippet.py b/askbot/deployment/deployers/settings_py_caching_snippet.py
index d8a073534a..51d1dbf828 100644
--- a/askbot/deployment/deployers/settings_py_caching_snippet.py
+++ b/askbot/deployment/deployers/settings_py_caching_snippet.py
@@ -7,4 +7,4 @@ class SettingsPyCachingSnippet(FileDeployer): # pylint: disable=missing-class-do
def render(self):
if self.params['caching_settings']:
return self.params['caching_settings']
- return super(SettingsPyCachingSnippet, self).render()
+ return super().render()
diff --git a/askbot/deployment/deployers/settings_py_databases_snippet.py b/askbot/deployment/deployers/settings_py_databases_snippet.py
index 29112ea048..e253f01def 100644
--- a/askbot/deployment/deployers/settings_py_databases_snippet.py
+++ b/askbot/deployment/deployers/settings_py_databases_snippet.py
@@ -10,4 +10,4 @@ def render(self):
`database_settings` parameter"""
if self.params['database_settings']:
return self.params['database_settings']
- return super(SettingsPyDatabasesSnippet, self).render()
+ return super().render()
diff --git a/askbot/deployment/deployers/settings_py_email_snippet.py b/askbot/deployment/deployers/settings_py_email_snippet.py
index 20edfa263c..018445ca13 100644
--- a/askbot/deployment/deployers/settings_py_email_snippet.py
+++ b/askbot/deployment/deployers/settings_py_email_snippet.py
@@ -11,4 +11,4 @@ def render(self):
parameter"""
if self.params['email_settings']:
return self.params['email_settings']
- return super(SettingsPyEmailSnippet, self).render()
+ return super().render()
diff --git a/askbot/deployment/deployers/settings_py_languages_snippet.py b/askbot/deployment/deployers/settings_py_languages_snippet.py
index 948553638d..499f7940ee 100644
--- a/askbot/deployment/deployers/settings_py_languages_snippet.py
+++ b/askbot/deployment/deployers/settings_py_languages_snippet.py
@@ -9,4 +9,4 @@ def render(self):
the override with the `language_settings` parameter"""
if self.params['language_settings']:
return self.params['language_settings']
- return super(SettingsPyLanguagesSnippet, self).render()
+ return super().render()
diff --git a/askbot/deployment/deployers/settings_py_logging_snippet.py b/askbot/deployment/deployers/settings_py_logging_snippet.py
index 2ea902174a..e646a2cc9e 100644
--- a/askbot/deployment/deployers/settings_py_logging_snippet.py
+++ b/askbot/deployment/deployers/settings_py_logging_snippet.py
@@ -9,4 +9,4 @@ def render(self):
allows override with the --logging-settings parameter"""
if self.params['logging_settings']:
return self.params['logging_settings']
- return super(SettingsPyLoggingSnippet, self).render()
+ return super().render()
diff --git a/askbot/deployment/path_utils.py b/askbot/deployment/path_utils.py
index dd015f07d9..5ab035a47a 100644
--- a/askbot/deployment/path_utils.py
+++ b/askbot/deployment/path_utils.py
@@ -17,7 +17,7 @@ def dir_has_django_project(directory):
if file_name.endswith(os.path.sep + 'manage.py'):
#a hack allowing to install into the project directory
continue
- with open(file_name, 'r') as py_file:
+ with open(file_name) as py_file:
for line in py_file:
if IMPORT_RE1.match(line) or IMPORT_RE2.match(line):
return True
diff --git a/askbot/deployment/validators/proj_dir_validator.py b/askbot/deployment/validators/proj_dir_validator.py
index 9e3b985b26..c89fa382b5 100644
--- a/askbot/deployment/validators/proj_dir_validator.py
+++ b/askbot/deployment/validators/proj_dir_validator.py
@@ -8,7 +8,7 @@ class ProjDirValidator(DirValidator):
"""Implements the .clean method for the proj_name parameter"""
def __init__(self, console, parser, root_dir):
- super(ProjDirValidator, self).__init__(console, parser)
+ super().__init__(console, parser)
self.user_prompt = f'Enter {const.PROJ_NAME_HELP}.'
self.option_name = 'proj_name'
self.root_dir = root_dir
diff --git a/askbot/deployment/validators/root_dir_validator.py b/askbot/deployment/validators/root_dir_validator.py
index b3e89da30e..1474972fdc 100644
--- a/askbot/deployment/validators/root_dir_validator.py
+++ b/askbot/deployment/validators/root_dir_validator.py
@@ -10,7 +10,7 @@ class RootDirValidator(DirValidator):
by providing the .clean method"""
def __init__(self, console, parser):
- super(RootDirValidator, self).__init__(console, parser)
+ super().__init__(console, parser)
self.user_prompt = f'Enter {const.ROOT_DIR_HELP}.'
self.option_name = 'root_dir'
self.default = './' + const.DEFAULT_PROJECT_NAME
diff --git a/askbot/deps/django_authopenid/__init__.py b/askbot/deps/django_authopenid/__init__.py
index d854887892..3940cc6137 100644
--- a/askbot/deps/django_authopenid/__init__.py
+++ b/askbot/deps/django_authopenid/__init__.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# Copyright (c) 2007, 2008, Benoît Chesneau
#
# All rights reserved.
diff --git a/askbot/deps/django_authopenid/admin.py b/askbot/deps/django_authopenid/admin.py
index c8ec1aa448..2d4154ed71 100644
--- a/askbot/deps/django_authopenid/admin.py
+++ b/askbot/deps/django_authopenid/admin.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
from django.contrib import admin
from askbot.deps.django_authopenid.models import UserAssociation
diff --git a/askbot/deps/django_authopenid/backends.py b/askbot/deps/django_authopenid/backends.py
index b0e594cb7a..d0b2eab362 100644
--- a/askbot/deps/django_authopenid/backends.py
+++ b/askbot/deps/django_authopenid/backends.py
@@ -18,7 +18,7 @@
LOG = logging.getLogger(__name__)
-class AuthBackend(object):
+class AuthBackend:
"""Authenticator's authentication backend class
for more info, see django doc page:
http://docs.djangoproject.com/en/dev/topics/auth/#writing-an-authentication-backend
@@ -31,7 +31,7 @@ class AuthBackend(object):
"""
def __init__(self, *args, **kwargs):
self.login_providers = util.get_enabled_login_providers()
- super(AuthBackend, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
def authenticate(self, request, method=None, provider_name=None, **kwargs):
"""this authentication function supports many login methods"""
@@ -143,7 +143,7 @@ def auth_by_external_password(self, provider_name, username, password, request):
else:
#have username collision - so make up a more unique user name
#bug: - if user already exists with the new username - we are in trouble
- new_username = '%s@%s' % (username, provider_name)
+ new_username = f'{username}@{provider_name}'
user = User.objects.create_user(new_username, '', password)
user_registered.send(None, user=user, request=request)
message = _(
diff --git a/askbot/deps/django_authopenid/forms.py b/askbot/deps/django_authopenid/forms.py
index b0c7112f6f..a3c625f36d 100644
--- a/askbot/deps/django_authopenid/forms.py
+++ b/askbot/deps/django_authopenid/forms.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# Copyright (c) 2007, 2008, Benoît Chesneau
#
# All rights reserved.
@@ -53,7 +52,7 @@
class ConsentField(forms.BooleanField):
def __init__(self, *args, **kwargs):
- super(ConsentField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.label = _('I have read and agree with the terms of service')
self.required = True
self.error_messages['required'] = _(
@@ -68,7 +67,7 @@ class LoginProviderField(forms.CharField):
def __init__(self, *args, **kwargs):
kwargs['max_length'] = 64
- super(LoginProviderField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
def clean(self, value):
"""makes sure that login provider name
@@ -301,7 +300,7 @@ class RegistrationForm(forms.Form):
def __init__(self, *args, **kwargs):
self.request = kwargs.pop('request', None)
- super(RegistrationForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
email_required = not askbot_settings.BLANK_EMAIL_ALLOWED
self.fields['email'] = UserEmailField(required=email_required)
if askbot_settings.TERMS_CONSENT_REQUIRED:
@@ -313,7 +312,7 @@ def __init__(self, *args, **kwargs):
def clean(self):
if askbot_settings.NEW_REGISTRATIONS_DISABLED:
raise forms.ValidationError(askbot_settings.NEW_REGISTRATIONS_DISABLED_MESSAGE)
- return super(RegistrationForm, self).clean()
+ return super().clean()
class PasswordRegistrationForm(RegistrationForm, SetPasswordForm):
@@ -361,7 +360,7 @@ class ChangeEmailForm(forms.Form):
""" change email form """
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None, \
initial=None, user=None):
- super(ChangeEmailForm, self).__init__(data, files, auto_id,
+ super().__init__(data, files, auto_id,
prefix, initial)
email_required = not askbot_settings.BLANK_EMAIL_ALLOWED
self.fields['email'] = UserEmailField(skip_clean=True, required=email_required)
@@ -416,7 +415,7 @@ class ChangeopenidForm(forms.Form):
def __init__(self, data=None, user=None, *args, **kwargs):
if user is None:
raise TypeError("Keyword argument 'user' must be supplied")
- super(ChangeopenidForm, self).__init__(data, *args, **kwargs)
+ super().__init__(data, *args, **kwargs)
self.user = user
@@ -428,7 +427,7 @@ class DeleteForm(forms.Form):
def __init__(self, data=None, files=None, auto_id='id_%s',
prefix=None, initial=None, user=None):
- super(DeleteForm, self).__init__(data, files, auto_id, prefix, initial)
+ super().__init__(data, files, auto_id, prefix, initial)
self.test_openid = False
self.user = user
@@ -449,7 +448,7 @@ class EmailPasswordForm(forms.Form):
def __init__(self, data=None, files=None, auto_id='id_%s', prefix=None,
initial=None):
- super(EmailPasswordForm, self).__init__(data, files, auto_id,
+ super().__init__(data, files, auto_id,
prefix, initial)
self.user_cache = None
diff --git a/askbot/deps/django_authopenid/ldap_auth.py b/askbot/deps/django_authopenid/ldap_auth.py
index ee11a3c6e6..7d7c3e7f7c 100644
--- a/askbot/deps/django_authopenid/ldap_auth.py
+++ b/askbot/deps/django_authopenid/ldap_auth.py
@@ -187,7 +187,7 @@ def ldap_create_user_default(user_info, request):
user.is_active = True
user.save()
user_registered.send(None, user=user, request=request)
- LOG.info('Created New User : [{0}]'.format(user_info['ldap_username']))
+ LOG.info('Created New User : [{}]'.format(user_info['ldap_username']))
assoc = UserAssociation()
assoc.user = user
diff --git a/askbot/deps/django_authopenid/middleware.py b/askbot/deps/django_authopenid/middleware.py
index 8439ba5073..85f63e4752 100644
--- a/askbot/deps/django_authopenid/middleware.py
+++ b/askbot/deps/django_authopenid/middleware.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
from askbot.deps.django_authopenid import mimeparse
from django.http import HttpResponseRedirect
from django.urls import reverse
@@ -6,7 +5,7 @@
__all__ = ["OpenIDMiddleware"]
-class OpenIDMiddleware(object):
+class OpenIDMiddleware:
"""
Populate request.openid. This comes either from cookie or from
session, depending on the presence of OPENID_USE_SESSIONS.
diff --git a/askbot/deps/django_authopenid/models.py b/askbot/deps/django_authopenid/models.py
index 2b8432842b..c8eb5727de 100644
--- a/askbot/deps/django_authopenid/models.py
+++ b/askbot/deps/django_authopenid/models.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
import datetime
from django.conf import settings
@@ -36,7 +35,7 @@ class Association(models.Model):
assoc_type = models.TextField(max_length=64)
def __str__(self):
- return "Association: %s, %s" % (self.server_url, self.handle)
+ return f"Association: {self.server_url}, {self.handle}"
class UserAssociation(models.Model):
"""
@@ -52,14 +51,14 @@ class UserAssociation(models.Model):
provider_name = models.CharField(max_length=64, default='unknown')
last_used_timestamp = models.DateTimeField(null=True)
- class Meta(object):
+ class Meta:
unique_together = (
('user','provider_name'),
('openid_url', 'provider_name')
)
def __str__(self):
- return "Openid %s with user %s" % (self.openid_url, self.user)
+ return f"Openid {self.openid_url} with user {self.user}"
def update_timestamp(self):
self.last_used_timestamp = datetime.datetime.now()
@@ -72,7 +71,7 @@ def get_new_confirm_key(self):
# The random module is seeded when this Apache child is created.
# Use SECRET_KEY as added salt.
while 1:
- confirm_key = hashlib.md5("%s%s%s%s" % (
+ confirm_key = hashlib.md5("{}{}{}{}".format(
random.randint(0, sys.maxsize - 1), os.getpid(),
time.time(), settings.SECRET_KEY)).hexdigest()
try:
@@ -108,7 +107,7 @@ def save(self, *args, **kwargs):
self.expires_on = timezone.now() + \
datetime.timedelta(VERIFIER_EXPIRE_DAYS)
- super(UserEmailVerifier, self).save(*args, **kwargs)
+ super().save(*args, **kwargs)
def has_expired(self):
now = timezone.now()
diff --git a/askbot/deps/django_authopenid/protocols/base.py b/askbot/deps/django_authopenid/protocols/base.py
index 42761b16f7..319b56be04 100644
--- a/askbot/deps/django_authopenid/protocols/base.py
+++ b/askbot/deps/django_authopenid/protocols/base.py
@@ -1,4 +1,4 @@
-class BaseProtocol(object):
+class BaseProtocol:
"""Base class for all authentication protocols"""
def __iter__(self):
diff --git a/askbot/deps/django_authopenid/protocols/oauth1.py b/askbot/deps/django_authopenid/protocols/oauth1.py
index bbd00633c0..9646f79bfc 100644
--- a/askbot/deps/django_authopenid/protocols/oauth1.py
+++ b/askbot/deps/django_authopenid/protocols/oauth1.py
@@ -123,9 +123,9 @@ def send_request(self, client=None, url=None, method='GET', params=None, **kwarg
if parsed_response:
return parsed_response
else:
- raise OAuthError('error obtaining request token {0}'.format(content))
+ raise OAuthError(f'error obtaining request token {content}')
else:
- raise OAuthError('response is {0}'.format(response))
+ raise OAuthError(f'response is {response}')
def get_token(self):
return self.request_token
diff --git a/askbot/deps/django_authopenid/providers/discourse.py b/askbot/deps/django_authopenid/providers/discourse.py
index 9f86c2a435..c357c572fe 100644
--- a/askbot/deps/django_authopenid/providers/discourse.py
+++ b/askbot/deps/django_authopenid/providers/discourse.py
@@ -32,7 +32,7 @@ def get_sso_login_url(request, success_url):
# (where the Discourse will redirect user after verification).
# Payload should look like: nonce=NONCE&return_sso_url=RETURN_URL
return_url = site_url(reverse('user_complete_discourse_signin'))
- payload = 'nonce={}&return_sso_url={}'.format(nonce, return_url)
+ payload = f'nonce={nonce}&return_sso_url={return_url}'
# Base64 encode the above raw payload. -> BASE64_PAYLOAD
base64_payload = base64.b64encode(payload)
# URL encode the above BASE64_PAYLOAD.
@@ -52,7 +52,7 @@ class DiscourseSsoForm(forms.Form):
def __init__(self, *args, **kwargs):
self.expected_nonce = kwargs.pop('nonce', None)
- super(DiscourseSsoForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
def clean(self):
sso = self.cleaned_data['sso']
diff --git a/askbot/deps/django_authopenid/urls.py b/askbot/deps/django_authopenid/urls.py
index 4b55111eb2..e5e4a3ab95 100644
--- a/askbot/deps/django_authopenid/urls.py
+++ b/askbot/deps/django_authopenid/urls.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
from django.conf import settings as django_settings
from django.urls import re_path
@@ -18,11 +17,11 @@
re_path(r'^%s$' % pgettext('urls', 'signout/'), OpenidViews.signout, name='user_signout'),
#this view is "complete-openid" signin
re_path(
- r'^%s%s$' % (pgettext('urls', 'signin/'), pgettext('urls', 'complete/')),
+ r'^{}{}$'.format(pgettext('urls', 'signin/'), pgettext('urls', 'complete/')),
OpenidViews.complete_openid_signin,
name='user_complete_openid_signin'),
re_path(
- r'^%s%s$' % (pgettext('urls', 'signin/'), pgettext('urls', 'complete-cas/')),
+ r'^{}{}$'.format(pgettext('urls', 'signin/'), pgettext('urls', 'complete-cas/')),
OpenidViews.complete_cas_signin,
name='user_complete_cas_signin'),
re_path(
diff --git a/askbot/deps/django_authopenid/util.py b/askbot/deps/django_authopenid/util.py
index 52487a2af0..6fdcc02561 100644
--- a/askbot/deps/django_authopenid/util.py
+++ b/askbot/deps/django_authopenid/util.py
@@ -184,7 +184,7 @@ def get_provider_name_by_endpoint(openid_url):
providers. Returns None if no matching url was found.
"""
parsed_uri = urllib.parse.urlparse(openid_url)
- base_url = '{uri.scheme}://{uri.netloc}'.format(uri=parsed_uri)
+ base_url = f'{parsed_uri.scheme}://{parsed_uri.netloc}'
enabled_providers = get_enabled_login_providers()
for provider_data in enabled_providers.values():
openid_url_match = (provider_data['type'].startswith('openid') and
@@ -961,7 +961,7 @@ class OAuthConnection:
def __new__(cls, provider_name):
if provider_name == 'mediawiki':
return providers.mediawiki.Provider()
- return super(OAuthConnection, cls).__new__(cls)
+ return super().__new__(cls)
def __init__(self, provider_name):
"""initializes oauth connection"""
diff --git a/askbot/deps/django_authopenid/views.py b/askbot/deps/django_authopenid/views.py
index 38de894a44..2bdb4bf428 100644
--- a/askbot/deps/django_authopenid/views.py
+++ b/askbot/deps/django_authopenid/views.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
# Copyright (c) 2007, 2008, Benoît Chesneau
# Copyright (c) 2007 Simon Willison, original work on django-openid
#
@@ -192,7 +191,7 @@ def ask_openid(
auth_request = consumer.begin(openid_url)
except DiscoveryFailure:
openid_url = html.escape(openid_url)
- msg = _("OpenID %(openid_url)s is invalid" % {'openid_url':openid_url}) # pylint: disable=consider-using-f-string
+ msg = _("OpenID {openid_url} is invalid".format(openid_url=openid_url)) # pylint: disable=consider-using-f-string
logging.debug(msg)
return signin_failure(request, msg)
@@ -486,7 +485,7 @@ def signin(request):
if next_url == reverse('user_signin'):
# the sticky signin page
- next_url = '%(next_url)s?next=%(next_jwt)s' % {'next_url': next_url, 'next_jwt': next_jwt}
+ next_url = f'{next_url}?next={next_jwt}'
login_form = forms.LoginForm(initial={'next': next_jwt})
diff --git a/askbot/deps/group_messaging/disabled_tests.py b/askbot/deps/group_messaging/disabled_tests.py
index 3eb3641014..2a7a7f577b 100644
--- a/askbot/deps/group_messaging/disabled_tests.py
+++ b/askbot/deps/group_messaging/disabled_tests.py
@@ -11,7 +11,7 @@
from django.contrib.auth.models import User, Group
from django.test import TestCase
from django.utils import timezone
-from mock import Mock
+from unittest.mock import Mock
import time
import urllib.parse
diff --git a/askbot/deps/group_messaging/models.py b/askbot/deps/group_messaging/models.py
index b6851e7eb6..58b2e2f94e 100644
--- a/askbot/deps/group_messaging/models.py
+++ b/askbot/deps/group_messaging/models.py
@@ -224,7 +224,7 @@ def create(self, **kwargs):
kwargs['headline'] = headline[:MAX_HEADLINE_LENGTH]
kwargs['html'] = parse_message(kwargs['text'])
- message = super(MessageManager, self).create(**kwargs)
+ message = super().create(**kwargs)
#creator of message saw it by definition
#crate a "seen" memo for the sender, because we
#don't want to inform the user about his/her own post
diff --git a/askbot/deps/group_messaging/views.py b/askbot/deps/group_messaging/views.py
index 5cb289e4ce..c6b0100330 100644
--- a/askbot/deps/group_messaging/views.py
+++ b/askbot/deps/group_messaging/views.py
@@ -214,7 +214,7 @@ class DeleteOrRestoreThread(ThreadsList):
def __init__(self, action, *args, **kwargs):
self.thread_action = action or 'delete'
- super(DeleteOrRestoreThread, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
def post(self, request, thread_id=None):
"""process the post request:
diff --git a/askbot/doc/source/conf.py b/askbot/doc/source/conf.py
index 2813025e76..f0ac876202 100644
--- a/askbot/doc/source/conf.py
+++ b/askbot/doc/source/conf.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
#
# Askbot documentation build configuration file, created by
# sphinx-quickstart on Wed Jun 16 19:22:51 2010.
diff --git a/askbot/exceptions.py b/askbot/exceptions.py
index 61587c576f..b8cc10d019 100644
--- a/askbot/exceptions.py
+++ b/askbot/exceptions.py
@@ -13,7 +13,7 @@ class LoginRequired(exceptions.PermissionDenied):
def __init__(self, msg=None):
if msg is None:
msg = _('Sorry, but anonymous visitors cannot access this function')
- super(LoginRequired, self).__init__(msg)
+ super().__init__(msg)
class InsufficientReputation(exceptions.PermissionDenied):
diff --git a/askbot/feed.py b/askbot/feed.py
index ffda2f6c8d..36486ee510 100644
--- a/askbot/feed.py
+++ b/askbot/feed.py
@@ -102,9 +102,9 @@ def item_title(self, item):
if item.post_type == "question":
title = item.thread.title
elif item.post_type == "answer":
- title = 'Answer by %s for %s ' % (item.author, item.thread._question_post().summary)
+ title = f'Answer by {item.author} for {item.thread._question_post().summary} '
elif item.post_type == "comment":
- title = 'Comment by %s for %s' % (item.author, item.parent.summary)
+ title = f'Comment by {item.author} for {item.parent.summary}'
return title
def item_description(self, item):
@@ -196,4 +196,4 @@ def items(self, item):
# hack to get the request object into the Feed class
def get_feed(self, obj, request):
self.request = request
- return super(RssLastestQuestionsFeed, self).get_feed(obj, request)
+ return super().get_feed(obj, request)
diff --git a/askbot/forms.py b/askbot/forms.py
index 2954ec7919..1c45d4672c 100644
--- a/askbot/forms.py
+++ b/askbot/forms.py
@@ -192,7 +192,7 @@ def __init__(self, *args, **kwargs):
country_choices = (('unknown', _('select country')),) + tuple(country_choices)
kwargs['choices'] = kwargs.pop('choices', country_choices)
kwargs['label'] = kwargs.pop('label', _('Country'))
- super(CountryField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
def clean(self, value):
"""Handles case of 'unknown' country selection
@@ -213,7 +213,7 @@ def __init__(self, min_words=0, max_words=9999, field_name=None,
self.min_words = min_words
self.max_words = max_words
self.field_name = field_name
- super(CountedWordsField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
def clean(self, value):
# TODO: this field must be adapted to work with Chinese, etc.
@@ -244,7 +244,7 @@ class AskbotReCaptchaField(ReCaptchaField):
def __init__(self, *args, **kwargs):
kwargs.setdefault('private_key', askbot_settings.RECAPTCHA_SECRET)
kwargs.setdefault('public_key', askbot_settings.RECAPTCHA_KEY)
- super(AskbotReCaptchaField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
class LanguageField(forms.ChoiceField):
@@ -252,7 +252,7 @@ class LanguageField(forms.ChoiceField):
def __init__(self, *args, **kwargs):
kwargs['choices'] = django_settings.LANGUAGES
kwargs['label'] = _('Select language')
- super(LanguageField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
class LanguageForm(forms.Form):
@@ -275,7 +275,7 @@ class TranslateUrlForm(forms.Form):
class SuppressEmailField(forms.BooleanField):
def __init__(self):
- super(SuppressEmailField, self).__init__()
+ super().__init__()
self.required = False
self.label = _("minor edit (don't send alerts)")
@@ -298,7 +298,7 @@ def clean(self, value):
class TitleField(forms.CharField):
"""Field receiving question title"""
def __init__(self, *args, **kwargs):
- super(TitleField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.required = kwargs.get('required', True)
self.widget = forms.TextInput(
attrs={'size': 70, 'autocomplete': 'off'})
@@ -353,7 +353,7 @@ def __init__(self, *args, **kwargs):
widget_attrs = kwargs.pop('attrs', {})
widget_attrs.setdefault('id', 'editor')
- super(EditorField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.required = True
if askbot_settings.EDITOR_TYPE == 'markdown':
self.widget = forms.Textarea(attrs=widget_attrs)
@@ -389,7 +389,7 @@ class QuestionEditorField(EditorField):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
- super(QuestionEditorField, self).__init__(
+ super().__init__(
user=user, *args, **kwargs)
self.min_length = askbot_settings.MIN_QUESTION_BODY_LENGTH
@@ -398,7 +398,7 @@ class AnswerEditorField(EditorField):
"""Editor field for answers"""
def __init__(self, *args, **kwargs):
- super(AnswerEditorField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.min_length = askbot_settings.MIN_ANSWER_BODY_LENGTH
@@ -447,7 +447,7 @@ class TagNamesField(forms.CharField):
"""field that receives AskBot tag names"""
def __init__(self, *args, **kwargs):
- super(TagNamesField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.required = kwargs.get('required',
askbot_settings.TAGS_ARE_REQUIRED)
self.widget = forms.TextInput(
@@ -469,7 +469,7 @@ def __init__(self, *args, **kwargs):
def clean(self, value):
from askbot import models
- value = super(TagNamesField, self).clean(value)
+ value = super().clean(value)
data = value.strip(const.TAG_STRIP_CHARS)
if not data:
if askbot_settings.TAGS_ARE_REQUIRED:
@@ -516,7 +516,7 @@ class WikiField(forms.BooleanField):
"""
def __init__(self, *args, **kwargs):
- super(WikiField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.required = False
self.initial = False
self.label = _(
@@ -532,7 +532,7 @@ class PageField(forms.IntegerField):
def __init__(self, *args, **kwargs):
self.required = False
- super(PageField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
def clean(self, value):
try:
@@ -545,7 +545,7 @@ def clean(self, value):
class SortField(forms.ChoiceField):
def __init__(self, *args, **kwargs):
self.default = kwargs.pop('default', '')
- super(SortField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
def clean(self, value):
value = value or self.default
@@ -557,7 +557,7 @@ def clean(self, value):
class SummaryField(forms.CharField):
def __init__(self, *args, **kwargs):
- super(SummaryField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.required = False
self.widget = forms.TextInput(
attrs={'size': 50, 'autocomplete': 'off'})
@@ -575,7 +575,7 @@ class EditorForm(forms.Form):
in the __init__() function"""
def __init__(self, attrs=None, user=None, editor_attrs=None):
- super(EditorForm, self).__init__()
+ super().__init__()
editor_attrs = editor_attrs or {}
self.fields['editor'] = EditorField(attrs=attrs,
editor_attrs=editor_attrs,
@@ -602,7 +602,7 @@ class ShowQuestionForm(forms.Form):
page = PageField()
def __init__(self, *args, **kwargs):
- super(ShowQuestionForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
# uses livesettings for the default so the 'sort' field
# must be added in the __init__
self.fields['sort'] = SortField(
@@ -724,7 +724,7 @@ def __init__(self, *arg, **kwarg):
moderator = kwarg.pop('moderator')
subject = kwarg.pop('subject')
- super(ChangeUserStatusForm, self).__init__(*arg, **kwarg)
+ super().__init__(*arg, **kwarg)
# Select user_status_choices depending on status of the moderator
if moderator.is_authenticated:
@@ -827,7 +827,7 @@ class FeedbackForm(forms.Form):
next = NextUrlField()
def __init__(self, user=None, *args, **kwargs):
- super(FeedbackForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.user = user
if should_use_recaptcha(user):
self.fields['recaptcha'] = AskbotReCaptchaField()
@@ -846,7 +846,7 @@ def clean_name(self):
return name
def clean(self):
- super(FeedbackForm, self).clean()
+ super().clean()
if self.user and self.user.is_anonymous:
need_email = not bool(self.cleaned_data.get('no_email', False))
email = self.cleaned_data.get('email', '').strip()
@@ -857,7 +857,7 @@ def clean(self):
return self.cleaned_data
-class FormWithHideableFields(object):
+class FormWithHideableFields:
"""allows to swap a field widget to HiddenInput() and back"""
def hide_field(self, name):
@@ -889,7 +889,7 @@ class PostPrivatelyForm(forms.Form, FormWithHideableFields):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
self._user = user
- super(PostPrivatelyForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
if self.allows_post_privately() == False:
self.hide_field('post_privately')
@@ -1002,7 +1002,7 @@ class AskForm(PostAsSomeoneForm, PostPrivatelyForm):
def __init__(self, *args, **kwargs):
user = kwargs.get('user', None)
- super(AskForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
# It's important that this field is set up dynamically
self.fields['title'] = TitleField()
self.fields['tags'] = TagNamesField()
@@ -1048,7 +1048,7 @@ class AskWidgetForm(forms.Form, FormWithHideableFields):
def __init__(self, include_text=True, *args, **kwargs):
user = kwargs.pop('user', None)
- super(AskWidgetForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.fields['title'] = TitleField()
# hide ask_anonymously field
if user.is_anonymous or not askbot_settings.ALLOW_ASK_ANONYMOUSLY:
@@ -1073,7 +1073,7 @@ class CreateAskWidgetForm(forms.Form, FormWithHideableFields):
def __init__(self, *args, **kwargs):
from askbot.models import Group, Tag
- super(CreateAskWidgetForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.fields['group'] = forms.ModelChoiceField(
queryset=Group.objects.exclude_personal(), required=False)
self.fields['tag'] = forms.ModelChoiceField(
@@ -1094,7 +1094,7 @@ class CreateQuestionWidgetForm(forms.Form, FormWithHideableFields):
def __init__(self, *args, **kwargs):
from askbot.models import Group
- super(CreateQuestionWidgetForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.fields['tagnames'] = TagNamesField()
self.fields['group'] = forms.ModelChoiceField(
queryset=Group.objects.exclude(name__startswith='_internal'),
@@ -1130,7 +1130,7 @@ class AskByEmailForm(forms.Form):
def __init__(self, *args, **kwargs):
user = kwargs.pop('user', None)
- super(AskByEmailForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.fields['body_text'] = QuestionEditorField(user=user)
def clean_sender(self):
@@ -1191,7 +1191,7 @@ class AnswerForm(PostAsSomeoneForm, PostPrivatelyForm):
widget=forms.TextInput(attrs={'size': 40, 'class': 'openid-input'}))
def __init__(self, *args, **kwargs):
- super(AnswerForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
user = kwargs['user']
# empty label on purpose
self.fields['text'] = AnswerEditorField(label='', user=user)
@@ -1233,7 +1233,7 @@ def clean_cancel_vote(self):
class CloseForm(forms.Form):
def __init__(self, *args, **kwargs):
- super(CloseForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
reasons = askbot_settings.QUESTION_CLOSE_REASONS
close_choices = tuple([tuple([reason, reason]) for reason in reasons])
self.fields['reason'] = forms.ChoiceField(choices=close_choices)
@@ -1243,7 +1243,7 @@ class RetagQuestionForm(forms.Form):
def __init__(self, question, *args, **kwargs):
"""initialize the default values"""
- super(RetagQuestionForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.fields['tags'] = TagNamesField()
self.fields['tags'].initial = question.thread.tagnames
@@ -1255,15 +1255,14 @@ class RevisionForm(forms.Form):
revision = forms.ChoiceField(widget=forms.Select())
def __init__(self, post, latest_revision, *args, **kwargs):
- super(RevisionForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
revisions = post.revisions.values_list(
'revision', 'author__username', 'revised_at', 'summary'
)
date_format = '%c'
rev_choices = list()
for r in revisions:
- rev_details = '%s - %s (%s) %s' % (
- r[0], r[1], r[2].strftime(date_format), r[3])
+ rev_details = f'{r[0]} - {r[1]} ({r[2].strftime(date_format)}) {r[3]}'
rev_choices.append((r[0], rev_details))
self.fields['revision'].choices = rev_choices
@@ -1278,7 +1277,7 @@ class EditAnswerForm(PostAsSomeoneForm, PostPrivatelyForm):
def __init__(self, answer, revision, *args, **kwargs):
self.answer = answer
user = kwargs.get('user', None)
- super(EditAnswerForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
# it is important to add this field dynamically
# label is empty on purpose
self.fields['text'] = AnswerEditorField(label='', user=user)
@@ -1289,7 +1288,7 @@ def __init__(self, answer, revision, *args, **kwargs):
self.fields['recaptcha'] = AskbotReCaptchaField()
def has_changed(self):
- if super(EditAnswerForm, self).has_changed():
+ if super().has_changed():
return True
if askbot_settings.GROUPS_ENABLED:
return self.answer.is_private() \
@@ -1336,7 +1335,7 @@ class EditUserForm(forms.Form):
widget=forms.TextInput(attrs={'size': 35}))
def __init__(self, user, *args, **kwargs):
- super(EditUserForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
logging.debug('initializing the form')
if askbot_settings.EDITABLE_SCREEN_NAME:
@@ -1396,7 +1395,7 @@ class TagFilterSelectionForm(forms.ModelForm):
widget=forms.RadioSelect)
def __init__(self, *args, **kwargs):
- super(TagFilterSelectionForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
choices = get_tag_email_filter_strategy_choices()
self.fields['email_tag_filter_strategy'].choices = choices
@@ -1406,7 +1405,7 @@ class Meta:
def save(self):
before = self.instance.email_tag_filter_strategy
- super(TagFilterSelectionForm, self).save()
+ super().save()
after = self.instance.email_tag_filter_strategy
return before != after
@@ -1415,7 +1414,7 @@ class EmailFeedSettingField(forms.ChoiceField):
def __init__(self, *arg, **kwarg):
kwarg['choices'] = kwarg.get('choices', const.NOTIFICATION_DELIVERY_SCHEDULE_CHOICES)
kwarg['widget'] = forms.RadioSelect
- super(EmailFeedSettingField, self).__init__(*arg, **kwarg)
+ super().__init__(*arg, **kwarg)
class EditUserEmailFeedsForm(forms.Form):
@@ -1445,7 +1444,7 @@ class EditUserEmailFeedsForm(forms.Form):
}
def __init__(self, *args, **kwargs):
- super(EditUserEmailFeedsForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.fields = OrderedDict((
('asked_by_me', EmailFeedSettingField(label=askbot_settings.WORDS_ASKED_BY_ME)),
('answered_by_me', EmailFeedSettingField(label=askbot_settings.WORDS_ANSWERED_BY_ME)),
@@ -1548,13 +1547,13 @@ def __init__(self, **kwargs):
('n', _('no %(sitename)s email please, thanks')
% {'sitename': askbot_settings.APP_SHORT_NAME})
)
- super(SubscribeForEmailUpdatesField, self).__init__(**kwargs)
+ super().__init__(**kwargs)
class SimpleEmailSubscribeForm(forms.Form):
def __init__(self, *args, **kwargs):
- super(SimpleEmailSubscribeForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.fields['subscribe'] = SubscribeForEmailUpdatesField()
def save(self, user=None):
@@ -1628,7 +1627,7 @@ class BulkTagSubscriptionForm(forms.Form):
def __init__(self, *args, **kwargs):
from askbot.models import BulkTagSubscription, Tag, Group
- super(BulkTagSubscriptionForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.fields['users'] = forms.ModelMultipleChoiceField(queryset=User.objects.all())
self.fields['tags'] = TagNamesField(label=_("Tags"), help_text=' ')
if askbot_settings.GROUPS_ENABLED:
@@ -1696,7 +1695,7 @@ class NewCommentForm(forms.Form):
avatar_size = forms.IntegerField()
def __init__(self, *args, **kwargs):
- super(NewCommentForm, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
self.fields['comment'] = forms.CharField(
max_length=askbot_settings.MAX_COMMENT_LENGTH)
diff --git a/askbot/importers/stackexchange/management/__init__.py b/askbot/importers/stackexchange/management/__init__.py
index 3c575cb6b1..2858194e65 100644
--- a/askbot/importers/stackexchange/management/__init__.py
+++ b/askbot/importers/stackexchange/management/__init__.py
@@ -6,7 +6,7 @@
class ImporterThread(threading.Thread):
def __init__(self, dump_file = None):
self.dump_file = dump_file
- super(ImporterThread, self).__init__()
+ super().__init__()
def run(self):
management.call_command('load_stackexchange', self.dump_file)
diff --git a/askbot/importers/stackexchange/management/commands/load_stackexchange.py b/askbot/importers/stackexchange/management/commands/load_stackexchange.py
index 4b1cca9231..6725d94d46 100644
--- a/askbot/importers/stackexchange/management/commands/load_stackexchange.py
+++ b/askbot/importers/stackexchange/management/commands/load_stackexchange.py
@@ -63,7 +63,7 @@
COMMENT = {}
NUMBERED_NAME_RE = re.compile(r'^(.*)\*(\d+)\*$')
-class X(object):#
+class X:#
"""class with methods for handling some details
of SE --> ASKBOT mapping
"""
@@ -155,7 +155,7 @@ def get_message_text(cls, se_m):
if se_m.user.id == -1:
return None
url = cls.get_user(se_m.user).get_profile_url()
- return '%s' % (url,text)
+ return f'{text}'
return None
@classmethod
@@ -199,7 +199,7 @@ def get_post_revision_group_types(cls, rev_group):
if len(rev_types) > 1 and all([t in exclusive for t in rev_types]):
tstr = ','.join(rev_types)
gstr = ','.join([str(rev.id) for rev in rev_group])
- msg = 'incompatible revision types %s in PostHistory %s' % (tstr,gstr)
+ msg = f'incompatible revision types {tstr} in PostHistory {gstr}'
raise Exception(msg)
return rev_types
@@ -872,7 +872,7 @@ def load_xml_file(self, item):
xml_data = self.zipfile.read(xml_path)
tree = et.fromstring(xml_data)
- print('loading from %s to %s' % (xml_path, table_name))
+ print(f'loading from {xml_path} to {table_name}')
model = models.get_model('stackexchange', table_name)
i = 0
rows = tree.findall('.//row')
@@ -915,7 +915,7 @@ def transfer_users(self):
if se_u.password_id is not None:
pw = se.Password.objects.get(id = se_u.password_id)
- u.password = 'sha1$%s$%s' % (pw.salt, pw.password)
+ u.password = f'sha1${pw.salt}${pw.password}'
else:
u.set_unusable_password()
diff --git a/askbot/importers/stackexchange/parse_models.py b/askbot/importers/stackexchange/parse_models.py
index c521631af6..052744de9e 100644
--- a/askbot/importers/stackexchange/parse_models.py
+++ b/askbot/importers/stackexchange/parse_models.py
@@ -50,7 +50,7 @@ def get_table_name(name):
out += '2'.join(bits)
return out
-class DjangoModel(object):
+class DjangoModel:
def __init__(self, name):
self.name = get_table_name(name)
self.fields = []
@@ -63,7 +63,7 @@ def __str__(self):
out += ' %s\n' % str(f)
return out
-class DjangoField(object):
+class DjangoField:
def __init__(self, name, type, restriction = None):
self.name = camel_to_python(name)
if self.name == 'class':
@@ -74,10 +74,10 @@ def __init__(self, name, type, restriction = None):
self.relation = None
def __str__(self):
- out = '%s = %s(' % (self.name, types[self.type])
+ out = f'{self.name} = {types[self.type]}('
if self.type == 'FK':
out += "'%s'" % self.relation
- out += ", related_name='%s_by_%s_set'" % (self.table.name, self.name)
+ out += f", related_name='{self.table.name}_by_{self.name}_set'"
out += ', null=True'#nullable to make life easier
elif self.type == 'PK':
out += 'primary_key=True'
@@ -105,7 +105,7 @@ def __init__(self, source_name):
bits = source_name.split('Id')
if len(bits) == 2 and bits[1] == '':
name = bits[0]
- super(DjangoFK, self).__init__(name, 'FK')
+ super().__init__(name, 'FK')
self.set_relation(name)
def set_relation(self, name):
diff --git a/askbot/importers/zendesk/management/commands/import_zendesk.py b/askbot/importers/zendesk/management/commands/import_zendesk.py
index 9e326c7f44..8af8ef5ddc 100644
--- a/askbot/importers/zendesk/management/commands/import_zendesk.py
+++ b/askbot/importers/zendesk/management/commands/import_zendesk.py
@@ -712,7 +712,7 @@ def read_xml_file(self,
todo: support blank values vs. nulls for strings
"""
cursor = connection.cursor()
- cursor.execute('TRUNCATE TABLE "{0}" CASCADE'.format(model._meta.db_table))
+ cursor.execute(f'TRUNCATE TABLE "{model._meta.db_table}" CASCADE')
xml = self.get_file(file_name)
items_saved = 0
for xml_entry in xml.findall(entry_name):
@@ -999,7 +999,7 @@ def import_forums(self, forums, tags, date_filter):
if tags:
print("Filtering forum posts by tags: %s" % tags)
if date_filter:
- print("Filtering forum post by dates between %s and %s" % (date_filter[0], date_filter[1]))
+ print(f"Filtering forum post by dates between {date_filter[0]} and {date_filter[1]}")
print("Importing forums... ")
print("="*64)
for forum in forums:
@@ -1069,7 +1069,7 @@ def import_tickets(self, tags, date_filter):
if tags:
print("Filtering tickets by tags: %s" % tags)
if date_filter:
- print("Filtering tickets by dates between %s and %s" % (date_filter[0], date_filter[1]))
+ print(f"Filtering tickets by dates between {date_filter[0]} and {date_filter[1]}")
sys.stdout.write("Importing tickets: ")
ticket_count = 0
for ticket in zendesk_models.Ticket.objects.all():
diff --git a/askbot/mail/__init__.py b/askbot/mail/__init__.py
index cc7674fae3..83ad2a90b2 100644
--- a/askbot/mail/__init__.py
+++ b/askbot/mail/__init__.py
@@ -218,7 +218,7 @@ def process_attachment(attachment):
file storage object
"""
file_url = store_file(attachment.name, attachment)
- markdown_link = '[%s](%s) ' % (attachment.name, file_url)
+ markdown_link = f'[{attachment.name}]({file_url}) '
file_extension = os.path.splitext(attachment.name)[1]
#todo: this is a hack - use content type
if file_extension.lower() in ('.png', '.jpg', '.jpeg', '.gif'):
diff --git a/askbot/mail/messages.py b/askbot/mail/messages.py
index 5006e96726..cf8538d8be 100644
--- a/askbot/mail/messages.py
+++ b/askbot/mail/messages.py
@@ -29,7 +29,7 @@ def get_question():
return Post.objects.filter(post_type='question')[0]
-class BaseEmail(object):
+class BaseEmail:
"""Base class for templated emails.
Besides sending formatted emails,
@@ -303,27 +303,27 @@ def get_thread_headers(self, post, orig_post, update):
that emails appear as threaded conversations in gmail"""
suffix_id = django_settings.SERVER_EMAIL
if update == const.TYPE_ACTIVITY_ASK_QUESTION:
- msg_id = "" % (post.id, suffix_id)
+ msg_id = f""
headers = {'Message-ID': msg_id}
elif update == const.TYPE_ACTIVITY_ANSWER:
- msg_id = "" % (post.id, suffix_id)
- orig_id = "" % (orig_post.id, suffix_id)
+ msg_id = f""
+ orig_id = f""
headers = {'Message-ID': msg_id, 'In-Reply-To': orig_id}
elif update == const.TYPE_ACTIVITY_UPDATE_QUESTION:
- msg_id = "" % (post.id, post.last_edited_at, suffix_id)
- orig_id = "" % (orig_post.id, suffix_id)
+ msg_id = f""
+ orig_id = f""
headers = {'Message-ID': msg_id, 'In-Reply-To': orig_id}
elif update == const.TYPE_ACTIVITY_COMMENT_QUESTION:
- msg_id = "" % (post.id, suffix_id)
- orig_id = "" % (orig_post.id, suffix_id)
+ msg_id = f""
+ orig_id = f""
headers = {'Message-ID': msg_id, 'In-Reply-To': orig_id}
elif update == const.TYPE_ACTIVITY_UPDATE_ANSWER:
- msg_id = "" % (post.id, post.last_edited_at, suffix_id)
- orig_id = "" % (orig_post.id, suffix_id)
+ msg_id = f""
+ orig_id = f""
headers = {'Message-ID': msg_id, 'In-Reply-To': orig_id}
elif update == const.TYPE_ACTIVITY_COMMENT_ANSWER:
- msg_id = "" % (post.id, suffix_id)
- orig_id = "" % (orig_post.id, suffix_id)
+ msg_id = f""
+ orig_id = f""
headers = {'Message-ID': msg_id, 'In-Reply-To': orig_id}
else:
# Unknown type -> Can't set headers
diff --git a/askbot/mail/parsing.py b/askbot/mail/parsing.py
index 2653075213..25874f66b4 100644
--- a/askbot/mail/parsing.py
+++ b/askbot/mail/parsing.py
@@ -125,7 +125,7 @@ def strip_leading_empties(text):
def strip_trailing_sender_references(text, email_address):
server_email = 'ask@' + askbot_settings.REPLY_BY_EMAIL_HOSTNAME
- email_pattern = '(%s|%s)' % (email_address, server_email)
+ email_pattern = f'({email_address}|{server_email})'
pattern = r'\n[^\n]*%s[^\n]*$' % email_pattern
return re.sub(pattern, '', text, re.IGNORECASE)
diff --git a/askbot/management/commands/apply_hinted_tags.py b/askbot/management/commands/apply_hinted_tags.py
index b2c777745c..2b68ba8726 100644
--- a/askbot/management/commands/apply_hinted_tags.py
+++ b/askbot/management/commands/apply_hinted_tags.py
@@ -32,7 +32,7 @@ def handle(self, *args, **kwargs):
raise CommandError('parameter --tags-file is required')
try:
tags_input = open(kwargs['tags_file']).read()
- except IOError:
+ except OSError:
raise CommandError('file "%s" not found' % kwargs['tags_file'])
tags_list = [v.strip() for v in tags_input.split('\n')]
diff --git a/askbot/management/commands/askbot_add_osqa_content.py b/askbot/management/commands/askbot_add_osqa_content.py
index 0630f25f49..15e9fdda48 100644
--- a/askbot/management/commands/askbot_add_osqa_content.py
+++ b/askbot/management/commands/askbot_add_osqa_content.py
@@ -108,7 +108,7 @@ def handle(self, *args, **options):
self.redirect_format = self.get_redirect_format(options['redirect_format'])
dump_file_name = options['xml_file']
- xml = open(dump_file_name, 'r').read()
+ xml = open(dump_file_name).read()
self.soup = BeautifulSoup(xml, ['lxml', 'xml', 'lxml-xml'])
# site settings
diff --git a/askbot/management/commands/askbot_add_test_content.py b/askbot/management/commands/askbot_add_test_content.py
index 53b2007696..63f44abecf 100644
--- a/askbot/management/commands/askbot_add_test_content.py
+++ b/askbot/management/commands/askbot_add_test_content.py
@@ -165,7 +165,7 @@ def create_questions(self, users):
tags = tags,
)
- self.print_if_verbose("Created Question '%s' with tags: '%s'" % (
+ self.print_if_verbose("Created Question '{}' with tags: '{}'".format(
active_question.thread.title, tags,)
)
return active_question
diff --git a/askbot/management/commands/askbot_add_user.py b/askbot/management/commands/askbot_add_user.py
index 5e5c0eb6b3..c5ece6eeac 100644
--- a/askbot/management/commands/askbot_add_user.py
+++ b/askbot/management/commands/askbot_add_user.py
@@ -74,8 +74,7 @@ def handle(self, *args, **options):
status = options['status']
if status not in 'wamdsb':
raise CommandError(
- 'Illegal value of --status %s. Allowed user statuses are: %s' \
- % (status, STATUS_INFO)
+ f'Illegal value of --status {status}. Allowed user statuses are: {STATUS_INFO}'
)
user = models.User.objects.create_user(username, email)
diff --git a/askbot/management/commands/askbot_add_xml_content.py b/askbot/management/commands/askbot_add_xml_content.py
index ef50dfc7a3..a28e8fa070 100644
--- a/askbot/management/commands/askbot_add_xml_content.py
+++ b/askbot/management/commands/askbot_add_xml_content.py
@@ -200,7 +200,7 @@ def import_users(self):
#copy the data
if from_user.username != to_user.username:
names = (from_user.username, to_user.username)
- log_info['notify_user'].append('Your user name has changed from %s to %s' % names)
+ log_info['notify_user'].append('Your user name has changed from {} to {}'.format(*names))
self.copy_string_parameter(from_user, to_user, 'first_name')
self.copy_string_parameter(from_user, to_user, 'last_name')
diff --git a/askbot/management/commands/askbot_deduplicate_localized_profiles.py b/askbot/management/commands/askbot_deduplicate_localized_profiles.py
index f3f77cb84b..09b21c5222 100644
--- a/askbot/management/commands/askbot_deduplicate_localized_profiles.py
+++ b/askbot/management/commands/askbot_deduplicate_localized_profiles.py
@@ -26,4 +26,4 @@ def handle(self, *args, **kwargs):
item.delete()
deleted_count += 1
- print('deleted {} items'.format(deleted_count))
+ print(f'deleted {deleted_count} items')
diff --git a/askbot/management/commands/askbot_delete_orphan_group_memberships.py b/askbot/management/commands/askbot_delete_orphan_group_memberships.py
index 6530ffcc16..5b84b4766f 100644
--- a/askbot/management/commands/askbot_delete_orphan_group_memberships.py
+++ b/askbot/management/commands/askbot_delete_orphan_group_memberships.py
@@ -14,7 +14,7 @@ def handle(self, *args, **kwargs): #pylint: disable=unused-argument
group_ids = Group.objects.values_list('pk', flat=True)
#3) calc the diff
missing_group_ids = set(memb_group_ids) - set(group_ids)
- print('Found {} missing groups'.format(len(missing_group_ids)))
+ print(f'Found {len(missing_group_ids)} missing groups')
bad_gms = GroupMembership.objects.filter(group_id__in=missing_group_ids)
print('Deleting bad group memberships')
bad_gms.delete()
diff --git a/askbot/management/commands/askbot_export_user_data.py b/askbot/management/commands/askbot_export_user_data.py
index c3b7b31584..990dab5ffd 100644
--- a/askbot/management/commands/askbot_export_user_data.py
+++ b/askbot/management/commands/askbot_export_user_data.py
@@ -37,7 +37,7 @@ def handle(self, *args, **options): # pylint: disable=too-many-locals
try:
user = User.objects.get(pk=uid)
except User.DoesNotExist: # pylint: disable=no-member
- raise CommandError('User with id {} does not exist'.format(uid))
+ raise CommandError(f'User with id {uid} does not exist')
lang_data = dict()
for profile in user.localized_askbot_profiles.all():
@@ -104,7 +104,7 @@ def zip_tempdir(cls, temp_dir, file_name):
"""Zip contents of the temp directory into the desired
target file"""
if os.path.exists(file_name):
- raise CommandError('File {} already exists'.format(file_name))
+ raise CommandError(f'File {file_name} already exists')
zip_path = os.path.abspath(file_name)
file_paths = list_directory_files(temp_dir)
diff --git a/askbot/management/commands/askbot_fix_thread_points.py b/askbot/management/commands/askbot_fix_thread_points.py
index 64da325361..e9086964a3 100644
--- a/askbot/management/commands/askbot_fix_thread_points.py
+++ b/askbot/management/commands/askbot_fix_thread_points.py
@@ -16,7 +16,7 @@ def handle(self, *args, **kwargs):
.exclude(points=F('thread__points'))
.select_related('thread'))
- self.stdout.write('Fixing {0} threads...'.format(questions.count()))
+ self.stdout.write(f'Fixing {questions.count()} threads...')
for post in questions:
with override(post.thread.language_code):
diff --git a/askbot/management/commands/askbot_import_jive.py b/askbot/management/commands/askbot_import_jive.py
index e31e940a48..d0da01babe 100644
--- a/askbot/management/commands/askbot_import_jive.py
+++ b/askbot/management/commands/askbot_import_jive.py
@@ -148,7 +148,7 @@ def add_arguments(self, parser):
)
def __init__(self, *args, **kwargs):
- super(Command, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
#relax certain settings
askbot_settings.update('LIMIT_ONE_ANSWER_PER_USER', False)
askbot_settings.update('MAX_COMMENT_LENGTH', 1000000)
@@ -165,7 +165,7 @@ def handle(self, *args, **kwargs):
translation.activate(django_settings.LANGUAGE_CODE)
assert len(args) == 1, 'Dump file name is required'
dump_file_name = args[0]
- xml = open(dump_file_name, 'r').read()
+ xml = open(dump_file_name).read()
soup = BeautifulSoup(xml, ['lxml', 'xml'])
self.soup = soup
url_prop = self.soup.find('Property', attrs={'name': 'jiveURL'})
@@ -194,7 +194,7 @@ def add_legacy_links(self):
for question in ProgressBar(questions.iterator(), count, message):
thread_id = question.old_question_id
jive_url = self.jive_url
- old_url = '%s/thread.jspa?threadID=%s' % (jive_url, thread_id)
+ old_url = f'{jive_url}/thread.jspa?threadID={thread_id}'
question.text += template % old_url
question.save()
transaction.commit()
@@ -309,7 +309,7 @@ def add_attachments_to_post(self, post, attachments):
dest_file = os.path.join(django_settings.MEDIA_ROOT, file_name)
shutil.copyfile(source_file, dest_file)
# add link to file to the post text
- post.text += '# [%s|%s%s]\n' % (name, django_settings.MEDIA_URL, file_name)
+ post.text += f'# [{name}|{django_settings.MEDIA_URL}{file_name}]\n'
def import_thread(self, thread, tag_name):
"""import individual thread"""
diff --git a/askbot/management/commands/base.py b/askbot/management/commands/base.py
index 6a0078f5f2..235120ed65 100644
--- a/askbot/management/commands/base.py
+++ b/askbot/management/commands/base.py
@@ -73,7 +73,7 @@ def read_xml_file(self, filename):
"""reads xml data int BeautifulSoup instance"""
if not os.path.isfile(filename):
raise CommandError(f'File {filename} does not exist') % filename
- xml = open(filename, 'r', encoding='utf-8').read()
+ xml = open(filename, encoding='utf-8').read()
self.soup = BeautifulSoup(xml, ['lxml', 'xml'])
def remember_message_ids(self):
diff --git a/askbot/management/commands/build_thread_summary_cache.py b/askbot/management/commands/build_thread_summary_cache.py
index b07950581f..58446471dc 100644
--- a/askbot/management/commands/build_thread_summary_cache.py
+++ b/askbot/management/commands/build_thread_summary_cache.py
@@ -20,7 +20,7 @@ def handle(self, **options):
languages = options['language'] or (django_settings.LANGUAGE_CODE,)
for l in languages:
translation.activate(l)
- message = 'Rebuilding {0} thread summary cache'.format(l.upper())
+ message = f'Rebuilding {l.upper()} thread summary cache'
count = Thread.objects.count()
for thread in ProgressBar(Thread.objects.iterator(),
count, message):
diff --git a/askbot/management/commands/create_tag_synonyms.py b/askbot/management/commands/create_tag_synonyms.py
index 282f1473a4..a4998ba093 100644
--- a/askbot/management/commands/create_tag_synonyms.py
+++ b/askbot/management/commands/create_tag_synonyms.py
@@ -85,8 +85,8 @@ def handle(self, *args, **options):
source_tag = models.Tag.objects.get(name=source_tag_name, language_code=options['lang'])
except models.Tag.DoesNotExist:
if not options.get('is_force', False):
- prompt = """source tag %s doesn't exist, are you sure you want to create a TagSynonym
- %s ==> %s?""" % (source_tag_name, source_tag_name, target_tag_name)
+ prompt = """source tag {} doesn't exist, are you sure you want to create a TagSynonym
+ {} ==> {}?""".format(source_tag_name, source_tag_name, target_tag_name)
choice = console.choice_dialog(prompt, choices=('yes', 'no'))
if choice == 'no':
print('Cancled')
@@ -107,9 +107,8 @@ def handle(self, *args, **options):
language_code=options['lang']
)
if not options.get('is_force', False):
- prompt = """There exists a TagSynonym %s ==> %s,
- hence we will create a tag synonym %s ==> %s instead. Proceed?""" % (tag_synonym_tmp.source_tag_name, tag_synonym_tmp.target_tag_name,
- source_tag_name, tag_synonym_tmp.target_tag_name)
+ prompt = f"""There exists a TagSynonym {tag_synonym_tmp.source_tag_name} ==> {tag_synonym_tmp.target_tag_name},
+ hence we will create a tag synonym {source_tag_name} ==> {tag_synonym_tmp.target_tag_name} instead. Proceed?"""
choice = console.choice_dialog(prompt, choices=('yes', 'no'))
if choice == 'no':
print('Cancled')
diff --git a/askbot/management/commands/export_osqa.py b/askbot/management/commands/export_osqa.py
index 69d3c99fbd..73ee3db702 100644
--- a/askbot/management/commands/export_osqa.py
+++ b/askbot/management/commands/export_osqa.py
@@ -100,7 +100,7 @@ def handle(self, *app_labels, **options):
continue
model = apps.get_model(app_label, model_label)
if model is None:
- raise CommandError("Unknown model: %s.%s" % (app_label, model_label))
+ raise CommandError(f"Unknown model: {app_label}.{model_label}")
if app in list(app_list.keys()):
if app_list[app] and model not in app_list[app]:
@@ -205,7 +205,7 @@ def sort_dependencies(app_list):
skipped.append((model, deps))
if not changed:
raise CommandError("Can't resolve dependencies for %s in serialized app list." %
- ', '.join('%s.%s' % (model._meta.app_label, model._meta.object_name)
+ ', '.join(f'{model._meta.app_label}.{model._meta.object_name}'
for model, deps in sorted(skipped, key=lambda obj: obj[0].__name__))
)
model_dependencies = skipped
diff --git a/askbot/management/commands/fix_inbox_counts.py b/askbot/management/commands/fix_inbox_counts.py
index 09871a16da..42b115cacd 100644
--- a/askbot/management/commands/fix_inbox_counts.py
+++ b/askbot/management/commands/fix_inbox_counts.py
@@ -30,4 +30,4 @@ def __init__(self, *args, **kwargs):
'changed_count_message': 'Corrected records for %d users',
'nothing_changed_message': 'No problems found'
},)
- super(Command, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
diff --git a/askbot/management/commands/fix_superuser_status.py b/askbot/management/commands/fix_superuser_status.py
index 14201217d4..4579b4a3f2 100644
--- a/askbot/management/commands/fix_superuser_status.py
+++ b/askbot/management/commands/fix_superuser_status.py
@@ -37,4 +37,4 @@ def handle(self, *args, **kwargs):
rebuild_profile_caches(profiles)
- self.stdout.write('Fixed the status of {0} users.'.format(fixed))
+ self.stdout.write(f'Fixed the status of {fixed} users.')
diff --git a/askbot/management/commands/jinja2_makemessages.py b/askbot/management/commands/jinja2_makemessages.py
index fb772ed94e..c0278d1ae0 100644
--- a/askbot/management/commands/jinja2_makemessages.py
+++ b/askbot/management/commands/jinja2_makemessages.py
@@ -50,7 +50,7 @@ def handle(self, *args, **options):
trans_real.plural_re.pattern + '|' + r"""^-?\s*pluralize(\s+\w+)?\s*-?$""")
try:
- super(Command, self).handle(*args, **options)
+ super().handle(*args, **options)
finally:
trans_real.endblock_re = old_endblock_re
trans_real.block_re = old_block_re
diff --git a/askbot/management/commands/rename_tags.py b/askbot/management/commands/rename_tags.py
index d9b9a5c342..837186df4e 100644
--- a/askbot/management/commands/rename_tags.py
+++ b/askbot/management/commands/rename_tags.py
@@ -21,9 +21,9 @@ def get_admin(seed_user_id = None):
if admin.id != seed_user_id:
if seed_user_id is None:
- prompt = """You have not provided user id for the moderator
+ prompt = f"""You have not provided user id for the moderator
who to assign as the performer this operation, the default moderator is
-%s, id=%s. Will that work?""" % (admin.username, admin.id)
+{admin.username}, id={admin.id}. Will that work?"""
else:
prompt = """User with id=%s is not a moderator
would you like to select default moderator %s, id=%d
diff --git a/askbot/management/commands/rename_tags_id.py b/askbot/management/commands/rename_tags_id.py
index 41e6143945..beda7826e4 100644
--- a/askbot/management/commands/rename_tags_id.py
+++ b/askbot/management/commands/rename_tags_id.py
@@ -27,8 +27,7 @@ def get_tags_by_ids(tag_ids):
def get_similar_tags_from_strings(tag_strings, tag_name):
"""returns a list of tags, similar to tag_name from a set of questions"""
- grab_pattern = r'\b([%(ch)s]*%(nm)s[%(ch)s]*)\b' % \
- {'ch': const.TAG_CHARS, 'nm': tag_name}
+ grab_pattern = rf'\b([{const.TAG_CHARS}]*{tag_name}[{const.TAG_CHARS}]*)\b'
grab_re = re.compile(grab_pattern, re.IGNORECASE)
similar_tags = set()
@@ -148,13 +147,13 @@ def handle(self, *args, **options):
formatted_to_tag_names = format_tag_name_list(to_tags)
if not options.get('is_force', False):
- prompt = 'Rename tags %s --> %s?' % (formatted_from_tag_names, formatted_to_tag_names)
+ prompt = f'Rename tags {formatted_from_tag_names} --> {formatted_to_tag_names}?'
choice = console.choice_dialog(prompt, choices=('yes', 'no'))
if choice == 'no':
print('Canceled')
sys.exit()
else:
- print('Renaming tags %s --> %s' % (formatted_from_tag_names, formatted_to_tag_names))
+ print(f'Renaming tags {formatted_from_tag_names} --> {formatted_to_tag_names}')
sys.stdout.write('Processing:')
from_tag_names = get_tag_names(from_tags)
@@ -167,7 +166,7 @@ def handle(self, *args, **options):
source_tag_name=to_tag_name,
language_code=lang
)
- raise CommandError('You gave %s as --to argument, but TagSynonym: %s -> %s exists, probably you want to provide %s as --to argument' % (to_tag_name, tag_synonym.source_tag_name, tag_synonym.target_tag_name, tag_synonym.target_tag_name))
+ raise CommandError(f'You gave {to_tag_name} as --to argument, but TagSynonym: {tag_synonym.source_tag_name} -> {tag_synonym.target_tag_name} exists, probably you want to provide {tag_synonym.target_tag_name} as --to argument')
except models.TagSynonym.DoesNotExist:
pass
diff --git a/askbot/management/commands/send_accept_answer_reminders.py b/askbot/management/commands/send_accept_answer_reminders.py
index f6fa7f2c3d..5be861c83a 100644
--- a/askbot/management/commands/send_accept_answer_reminders.py
+++ b/askbot/management/commands/send_accept_answer_reminders.py
@@ -66,7 +66,6 @@ def handle(self, **options):
})
if DEBUG_THIS_COMMAND:
- print("User: %s
\nSubject:%s
\nText: %s
\n" % \
- (user.email, email.render_subject(), email.render_body()))
+ print(f"User: {user.email}
\nSubject:{email.render_subject()}
\nText: {email.render_body()}
\n")
else:
email.send([user.email],)
diff --git a/askbot/management/commands/send_email_alerts.py b/askbot/management/commands/send_email_alerts.py
index f307f1a51e..4cbbb2a6c9 100644
--- a/askbot/management/commands/send_email_alerts.py
+++ b/askbot/management/commands/send_email_alerts.py
@@ -119,14 +119,14 @@ def report_exception(self, user):
print(message)
admin_email = askbot_settings.ADMIN_EMAIL
try:
- subject_line = "Error processing daily/weekly notification for User '%s' for Site '%s'" % (user.username, SITE_ID)
+ subject_line = f"Error processing daily/weekly notification for User '{user.username}' for Site '{SITE_ID}'"
send_mail(
subject_line=subject_line.encode('utf-8'),
body_text=message,
recipient_list=[admin_email,]
)
except:
- message = "ERROR: was unable to report this exception to %s: %s" % (admin_email, traceback.format_exc())
+ message = f"ERROR: was unable to report this exception to {admin_email}: {traceback.format_exc()}"
print(self.format_debug_msg(user, message))
else:
message = "Sent email reporting this exception to %s" % admin_email
diff --git a/askbot/management/commands/send_unanswered_question_reminders.py b/askbot/management/commands/send_unanswered_question_reminders.py
index f1bc9c0c22..6d41dc5f4f 100644
--- a/askbot/management/commands/send_unanswered_question_reminders.py
+++ b/askbot/management/commands/send_unanswered_question_reminders.py
@@ -58,8 +58,7 @@ def send_email(user, questions):
email = UnansweredQuestionsReminder({'recipient_user': user,
'questions': questions})
if DEBUG_THIS_COMMAND:
- print("User: %s
\nSubject:%s
\nText: %s
\n" % \
- (user.email, email.render_subject(), email.render_body()))
+ print(f"User: {user.email}
\nSubject:{email.render_subject()}
\nText: {email.render_body()}
\n")
else:
email.send([user.email,])
diff --git a/askbot/management/commands/update_avatar_data.py b/askbot/management/commands/update_avatar_data.py
index 926b92c198..6fd354fbcf 100644
--- a/askbot/management/commands/update_avatar_data.py
+++ b/askbot/management/commands/update_avatar_data.py
@@ -11,8 +11,7 @@ def handle(self, **options):
users = User.objects.all()
has_avatar = User.objects.exclude(askbot_profile__avatar_type='n').count()
total_users = users.count()
- print('%s users in total, %s have valid avatar' \
- % (total_users, has_avatar))
+ print(f'{total_users} users in total, {has_avatar} have valid avatar')
for count, user in enumerate(users):
users_left = total_users - count
@@ -23,5 +22,4 @@ def handle(self, **options):
print('Updated all the users')
has_avatar = User.objects.exclude(askbot_profile__avatar_type='n').count()
- print('%s users in total, %s have real avatar image' \
- % (total_users, has_avatar))
+ print(f'{total_users} users in total, {has_avatar} have real avatar image')
diff --git a/askbot/middleware/anon_user.py b/askbot/middleware/anon_user.py
index 6e1a5fdba7..e3b275b9e8 100644
--- a/askbot/middleware/anon_user.py
+++ b/askbot/middleware/anon_user.py
@@ -12,7 +12,7 @@
from askbot.user_messages import create_message, get_and_delete_messages
from askbot.conf import settings as askbot_settings
-class AnonymousMessageManager(object):
+class AnonymousMessageManager:
"""message manager for the anonymous user"""
def __init__(self, request):
self.request = request
@@ -41,7 +41,7 @@ def connect_messages_to_anon_user(request):
request.user.message_set.get_and_delete
-class ConnectToSessionMessagesMiddleware(object):
+class ConnectToSessionMessagesMiddleware:
"""Middleware that attaches messages to anonymous users, and
makes sure that anonymous user greeting is shown just once.
Middleware does not do anything if the anonymous user greeting
diff --git a/askbot/middleware/cache.py b/askbot/middleware/cache.py
index e09978b7e6..ba05bd01b0 100644
--- a/askbot/middleware/cache.py
+++ b/askbot/middleware/cache.py
@@ -49,7 +49,7 @@
learn_cache_key, patch_response_headers)
-class UpdateCacheMiddleware(object):
+class UpdateCacheMiddleware:
"""
Response-phase cache middleware that updates the cache if the response is
cacheable.
@@ -127,7 +127,7 @@ def process_response(self, request, response):
return response
-class FetchFromCacheMiddleware(object):
+class FetchFromCacheMiddleware:
"""
Request-phase cache middleware that fetches a page from the cache.
diff --git a/askbot/middleware/cancel.py b/askbot/middleware/cancel.py
index 4d4885bd82..d2b87a12c1 100644
--- a/askbot/middleware/cancel.py
+++ b/askbot/middleware/cancel.py
@@ -3,7 +3,7 @@
from askbot.utils.forms import get_next_url
from askbot.utils.http import get_request_params
-class CancelActionMiddleware(object):
+class CancelActionMiddleware:
"""Django middleware that redirects to the next url
if the request has "cancel" parameter."""
diff --git a/askbot/middleware/forum_mode.py b/askbot/middleware/forum_mode.py
index 7b5b6b7d5e..bb93d1ee7f 100644
--- a/askbot/middleware/forum_mode.py
+++ b/askbot/middleware/forum_mode.py
@@ -30,7 +30,7 @@ def is_view_allowed(func):
return view_path in ALLOWED_VIEWS
-class ForumModeMiddleware(object):
+class ForumModeMiddleware:
"""protects forum views is the closed forum mode"""
def __init__(self, get_response=None): # i think get_reponse is never None. If it's not another middleware it's the view, I think
@@ -67,7 +67,7 @@ def process_request(self, request):
_('Please log in to use %s') % \
askbot_settings.APP_SHORT_NAME
)
- redirect_url = '%s?next=%s' % (
+ redirect_url = '{}?next={}'.format(
url_utils.get_login_url(),
encode_jwt({'next_url': request.get_full_path()})
)
diff --git a/askbot/middleware/locale.py b/askbot/middleware/locale.py
index fa17fc6033..3e7c202b62 100644
--- a/askbot/middleware/locale.py
+++ b/askbot/middleware/locale.py
@@ -4,7 +4,7 @@
from django.utils import translation
from askbot.conf import settings
-class LocaleMiddleware(object):
+class LocaleMiddleware:
"""
This is a very simple middleware that parses a request
and decides what translation object to install in the current
diff --git a/askbot/middleware/remote_ip.py b/askbot/middleware/remote_ip.py
index e30ffdd30e..c12e62b5a4 100644
--- a/askbot/middleware/remote_ip.py
+++ b/askbot/middleware/remote_ip.py
@@ -8,7 +8,7 @@
'askbot.middleware.remote_ip.SetRemoteIPFromXForwardedFor',
"""
-class SetRemoteIPFromXForwardedFor(object):
+class SetRemoteIPFromXForwardedFor:
def __init__(self, get_response=None): # i think get_reponse is never None. If it's not another middleware it's the view, I think
if get_response is None:
get_response = lambda x:x
diff --git a/askbot/middleware/view_log.py b/askbot/middleware/view_log.py
index 15d3e529fe..a8249d2494 100644
--- a/askbot/middleware/view_log.py
+++ b/askbot/middleware/view_log.py
@@ -7,7 +7,7 @@
from django.utils import timezone
-class ViewLogMiddleware(object):
+class ViewLogMiddleware:
"""
ViewLogMiddleware sends the site_visited signal
diff --git a/askbot/models/__init__.py b/askbot/models/__init__.py
index ce52c4e1f5..ccf6a69381 100644
--- a/askbot/models/__init__.py
+++ b/askbot/models/__init__.py
@@ -146,7 +146,7 @@ def get_users_by_text_query(search_query, users_query_set = None):
# models.Q(localized_user_profiles__about__search = search_query)
# )
-class RelatedObjectSimulator(object):
+class RelatedObjectSimulator:
'''Objects that simulates the "messages_set" related field
somehow django does not creates it automatically in django1.4.1'''
@@ -272,7 +272,7 @@ def user_get_absolute_url(self, language_code=None):
def user_get_unsubscribe_url(self):
url = reverse('user_unsubscribe')
email_key = self.get_or_create_email_key()
- return '{0}?key={1}&email={2}'.format(url, email_key, self.email)
+ return f'{url}?key={email_key}&email={self.email}'
def user_get_subscriptions_url(self):
@@ -2640,14 +2640,14 @@ def user_get_anonymous_name(self):
def user_get_anonymized_name(self):
"""Returns name that can be used for anonymized
account"""
- anonymized_name = 'anonymous{}'.format(self.pk)
+ anonymized_name = f'anonymous{self.pk}'
attempt = 0
if self.username == anonymized_name:
return anonymized_name
while User.objects.filter(username=anonymized_name).exists():
- seed_name = 'anonymous{}{}'.format(self.pk, attempt)
+ seed_name = f'anonymous{self.pk}{attempt}'
attempt += 1
return anonymized_name
@@ -2918,8 +2918,7 @@ def user_get_languages(self):
def get_profile_link(self, text=None):
- profile_link = '%s' \
- % (self.get_profile_url(), escape(text or self.username))
+ profile_link = f'{escape(text or self.username)}'
return mark_safe(profile_link)
diff --git a/askbot/models/badges.py b/askbot/models/badges.py
index 7a000f3cc6..2b0f34b90d 100644
--- a/askbot/models/badges.py
+++ b/askbot/models/badges.py
@@ -34,7 +34,7 @@
from askbot.utils.loading import load_module
-class Badge(object):
+class Badge:
"""base class for the badges
badges must implement method consider_award
@@ -133,7 +133,7 @@ def __init__(self):
description = _(
'Deleted own post with %(votes)s or more upvotes'
) % {'votes': askbot_settings.DISCIPLINED_BADGE_MIN_UPVOTES}
- super(Disciplined, self).__init__(
+ super().__init__(
name=_('Disciplined'), description=description,
level=const.BRONZE_BADGE, multiple=True)
@@ -152,7 +152,7 @@ def __init__(self):
description = _(
'Deleted own post with %(votes)s or more downvotes'
) % {'votes': askbot_settings.PEER_PRESSURE_BADGE_MIN_DOWNVOTES}
- super(PeerPressure, self).__init__(
+ super().__init__(
name=_('Peer Pressure'), description=description,
level=const.BRONZE_BADGE, multiple=True)
@@ -175,7 +175,7 @@ def __init__(self):
'votes': askbot_settings.TEACHER_BADGE_MIN_UPVOTES,
'answer_voted_up': askbot_settings.WORDS_ANSWER_VOTED_UP
}
- super(Teacher, self).__init__(
+ super().__init__(
name=_('Teacher'), description=description,
level=const.BRONZE_BADGE, multiple=False)
@@ -196,7 +196,7 @@ class FirstVote(Badge):
key = 'first-vote'
def __init__(self):
- super(FirstVote, self).__init__(
+ super().__init__(
name=self.name, description=self.description,
level=const.BRONZE_BADGE, multiple=False)
@@ -211,7 +211,7 @@ class Supporter(FirstVote):
key = 'supporter'
def __new__(cls):
- self = super(Supporter, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = _('Supporter')
self.description = _('First upvote')
return self
@@ -222,7 +222,7 @@ class Critic(FirstVote):
key = 'critic'
def __new__(cls):
- self = super(Critic, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = _('Critic')
self.description = _('First downvote')
return self
@@ -234,7 +234,7 @@ class CivicDuty(Badge):
def __init__(self):
min_votes = askbot_settings.CIVIC_DUTY_BADGE_MIN_VOTES
- super(CivicDuty, self).__init__(
+ super().__init__(
name=_('Civic Duty'),
description=_('Voted %(num)s times') % {'num': min_votes},
level=const.SILVER_BADGE, multiple=False)
@@ -256,7 +256,7 @@ def __init__(self):
'num': askbot_settings.SELF_LEARNER_BADGE_MIN_UPVOTES,
'answered_own_question': askbot_settings.WORDS_ANSWERED_OWN_QUESTION
}
- super(SelfLearner, self).__init__(
+ super().__init__(
name=_('Self-Learner'), description=description,
level=const.BRONZE_BADGE, multiple=True)
@@ -285,7 +285,7 @@ class QualityPost(Badge):
key = 'quality-post'
def __init__(self):
- super(QualityPost, self).__init__(
+ super().__init__(
name=self.name, description=self.description,
level=self.level, multiple=self.multiple)
@@ -301,7 +301,7 @@ class NiceAnswer(QualityPost):
key = 'nice-answer'
def __new__(cls):
- self = super(NiceAnswer, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_NICE_ANSWER
self.level = const.BRONZE_BADGE
self.multiple = True
@@ -318,7 +318,7 @@ class GoodAnswer(QualityPost):
key = 'good-answer'
def __new__(cls):
- self = super(GoodAnswer, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_GOOD_ANSWER
self.level = const.SILVER_BADGE
self.multiple = True
@@ -335,7 +335,7 @@ class GreatAnswer(QualityPost):
key = 'great-answer'
def __new__(cls):
- self = super(GreatAnswer, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_GREAT_ANSWER
self.level = const.GOLD_BADGE
self.multiple = True
@@ -352,7 +352,7 @@ class NiceQuestion(QualityPost):
key = 'nice-question'
def __new__(cls):
- self = super(NiceQuestion, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_NICE_QUESTION
self.level = const.BRONZE_BADGE
self.multiple = True
@@ -369,7 +369,7 @@ class GoodQuestion(QualityPost):
key = 'good-question'
def __new__(cls):
- self = super(GoodQuestion, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_GOOD_QUESTION
self.level = const.SILVER_BADGE
self.multiple = True
@@ -386,7 +386,7 @@ class GreatQuestion(QualityPost):
key = 'great-question'
def __new__(cls):
- self = super(GreatQuestion, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_GREAT_QUESTION
self.level = const.GOLD_BADGE
self.multiple = True
@@ -403,7 +403,7 @@ class Student(QualityPost):
key = 'student'
def __new__(cls):
- self = super(Student, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = _('Student')
self.level = const.BRONZE_BADGE
self.multiple = False
@@ -427,7 +427,7 @@ class FrequentedQuestion(Badge):
key = 'frequented-question'
def __init__(self):
- super(FrequentedQuestion, self).__init__(
+ super().__init__(
name=self.name, description=self.description,
level=self.level, multiple=True)
@@ -443,7 +443,7 @@ class PopularQuestion(FrequentedQuestion):
key = 'popular-question'
def __new__(cls):
- self = super(PopularQuestion, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_POPULAR_QUESTION
self.level = const.BRONZE_BADGE
self.min_views = askbot_settings.POPULAR_QUESTION_BADGE_MIN_VIEWS
@@ -458,7 +458,7 @@ class NotableQuestion(FrequentedQuestion):
key = 'notable-question'
def __new__(cls):
- self = super(NotableQuestion, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_NOTABLE_QUESTION
self.level = const.SILVER_BADGE
self.min_views = askbot_settings.NOTABLE_QUESTION_BADGE_MIN_VIEWS
@@ -473,7 +473,7 @@ class FamousQuestion(FrequentedQuestion):
key = 'famous-question'
def __new__(cls):
- self = super(FamousQuestion, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_FAMOUS_QUESTION
self.level = const.GOLD_BADGE
self.multiple = True
@@ -496,7 +496,7 @@ def __init__(self):
'asked_a_question': askbot_settings.WORDS_ASKED_A_QUESTION,
'accepted_an_answer': askbot_settings.WORDS_ACCEPTED_AN_ANSWER
}
- super(Scholar, self).__init__(
+ super().__init__(
name=_('Scholar'), level=const.BRONZE_BADGE,
multiple=False, description=description)
@@ -518,7 +518,7 @@ class VotedAcceptedAnswer(Badge):
key = 'voted-accepted-answer'
def __init__(self):
- super(VotedAcceptedAnswer, self).__init__(
+ super().__init__(
name=self.name, level=self.level,
multiple=self.multiple, description=self.description)
@@ -534,7 +534,7 @@ class Enlightened(VotedAcceptedAnswer):
key = 'enlightened'
def __new__(cls):
- self = super(Enlightened, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = _('Enlightened')
self.level = const.SILVER_BADGE
self.multiple = False
@@ -551,7 +551,7 @@ class Guru(VotedAcceptedAnswer):
key = 'guru'
def __new__(cls):
- self = super(Guru, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = _('Guru')
self.level = const.GOLD_BADGE
self.multiple = True
@@ -578,7 +578,7 @@ def __init__(self):
'votes': votes,
'answered_a_question': askbot_settings.WORDS_ANSWERED_A_QUESTION
}
- super(Necromancer, self).__init__(
+ super().__init__(
name=_('Necromancer'), level=const.SILVER_BADGE,
description=description, multiple=True)
@@ -599,7 +599,7 @@ class CitizenPatrol(Badge):
key = 'citizen-patrol'
def __init__(self):
- super(CitizenPatrol, self).__init__(
+ super().__init__(
name=_('Citizen Patrol'), level=const.BRONZE_BADGE,
multiple=False, description=_('First flagged post'))
@@ -613,7 +613,7 @@ class Cleanup(Badge):
key = 'cleanup'
def __init__(self):
- super(Cleanup, self).__init__(
+ super().__init__(
name=_('Cleanup'), level=const.BRONZE_BADGE,
multiple=False, description=_('First rollback'))
@@ -626,7 +626,7 @@ class Pundit(Badge):
key = 'pundit'
def __init__(self):
- super(Pundit, self).__init__(
+ super().__init__(
name=_('Pundit'), level=const.SILVER_BADGE, multiple=False,
description=_('Left 10 comments with score of 10 or more'))
@@ -639,7 +639,7 @@ class EditorTypeBadge(Badge):
key = 'editor-type-badge'
def __init__(self):
- super(EditorTypeBadge, self).__init__(
+ super().__init__(
name=self.name, level=self.level,
multiple=False, description=self.description
)
@@ -659,7 +659,7 @@ class Editor(EditorTypeBadge):
key = 'editor'
def __new__(cls):
- self = super(Editor, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = _('Editor')
self.level = const.BRONZE_BADGE
self.multiple = False
@@ -672,7 +672,7 @@ class AssociateEditor(EditorTypeBadge):
key = 'associate-editor' # legacy copycat name from stackoverflow
def __new__(cls):
- self = super(AssociateEditor, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = _('Associate Editor')
self.level = const.SILVER_BADGE
self.multiple = False
@@ -685,7 +685,7 @@ class Organizer(Badge):
key = 'organizer'
def __init__(self):
- super(Organizer, self).__init__(
+ super().__init__(
name=_('Organizer'), level=const.BRONZE_BADGE,
multiple=False, description=_('First retag'))
@@ -694,7 +694,7 @@ class Autobiographer(Badge):
key = 'autobiographer'
def __init__(self):
- super(Autobiographer, self).__init__(
+ super().__init__(
name=_('Autobiographer'), level=const.BRONZE_BADGE,
multiple=False, description=_('Completed all user profile fields'))
@@ -719,7 +719,7 @@ def __init__(self):
'num': self.min_stars,
'asked_a_question': askbot_settings.WORDS_ASKED_A_QUESTION
}
- super(FavoriteTypeBadge, self).__init__(
+ super().__init__(
name=self.name, level=self.level, multiple=True,
description=description)
@@ -739,7 +739,7 @@ class StellarQuestion(FavoriteTypeBadge):
key = 'stellar-question'
def __new__(cls):
- self = super(StellarQuestion, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_STELLAR_QUESTION
self.level = const.GOLD_BADGE
self.min_stars = askbot_settings.STELLAR_QUESTION_BADGE_MIN_STARS
@@ -750,7 +750,7 @@ class FavoriteQuestion(FavoriteTypeBadge):
key = 'favorite-question'
def __new__(cls):
- self = super(FavoriteQuestion, cls).__new__(cls)
+ self = super().__new__(cls)
self.name = askbot_settings.WORDS_FAVORITE_QUESTION
self.level = const.SILVER_BADGE
self.min_stars = askbot_settings.FAVORITE_QUESTION_BADGE_MIN_STARS
@@ -764,7 +764,7 @@ class Enthusiast(Badge):
key = 'enthusiast'
def __init__(self):
- super(Enthusiast, self).__init__(
+ super().__init__(
name = _('Enthusiast'),
level = const.SILVER_BADGE,
multiple = False,
@@ -787,7 +787,7 @@ class Commentator(Badge):
key = 'commentator'
def __init__(self):
- super(Commentator, self).__init__(
+ super().__init__(
name=_('Commentator'), level=const.BRONZE_BADGE,
multiple=False, description=_(
'Posted %(num_comments)s comments'
@@ -806,7 +806,7 @@ class Taxonomist(Badge):
key = 'taxonomist'
def __init__(self):
- super(Taxonomist, self).__init__(
+ super().__init__(
name=_('Taxonomist'), level=const.SILVER_BADGE,
multiple=False, description=ngettext(
'Created a tag used %(num)s time',
@@ -829,7 +829,7 @@ def __init__(self):
description = _('Responded to question within %(max_delay)s hours') % {
'max_delay': askbot_settings.RAPID_RESPONDER_BADGE_MAX_DELAY,
}
- super(RapidResponder, self).__init__(
+ super().__init__(
name=_('Rapid Responder'), level=const.SILVER_BADGE,
description=description, multiple=True)
@@ -859,7 +859,7 @@ class Expert(Badge):
key = 'expert'
def __init__(self):
- super(Expert, self).__init__(
+ super().__init__(
name=_('Expert'), level=const.SILVER_BADGE,
multiple=False, description=_('Very active in one tag'))
diff --git a/askbot/models/fields.py b/askbot/models/fields.py
index 0ea1908a84..46dbc0ea28 100644
--- a/askbot/models/fields.py
+++ b/askbot/models/fields.py
@@ -6,4 +6,4 @@ def __init__(self, *args, **kwargs):
kwargs['choices'] = django_settings.LANGUAGES
kwargs['default'] = django_settings.LANGUAGE_CODE
kwargs['max_length'] = 16
- super(LanguageCodeField, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
diff --git a/askbot/models/post.py b/askbot/models/post.py
index 2b36bf6c83..396d8d6f8f 100644
--- a/askbot/models/post.py
+++ b/askbot/models/post.py
@@ -336,7 +336,7 @@ def precache_comments(self, for_posts, visitor):
# return comments
-class MockPost(object):
+class MockPost:
"""Used for special purposes, e.g. to fill
out the js templates for the posts made via ajax
"""
@@ -598,7 +598,7 @@ def parse_and_save(self, author=None, **kwargs):
#this save must precede saving the mention activity
#as well as assigning groups to the post
#because generic relation needs primary key of the related object
- super(Post, self).save(**kwargs)
+ super().save(**kwargs)
# TODO: move this group stuff out of this function
if self.is_comment():
@@ -1108,7 +1108,7 @@ def delete(self, **kwargs):
for user in recipients:
user.update_response_counts()
- super(Post, self).delete(**kwargs)
+ super().delete(**kwargs)
def __str__(self):
if self.is_question():
@@ -1117,7 +1117,7 @@ def __str__(self):
return self.html
def save(self, *args, **kwargs):
- super(Post, self).save(*args, **kwargs)
+ super().save(*args, **kwargs)
if self.is_answer() and 'postgres' in askbot.get_database_engine_name():
# hit the database to trigger update of full text search vector
self.thread._question_post().save()
@@ -1136,7 +1136,7 @@ def get_text_content(self, title=None, body_text=None, tags=None):
title = title or self.thread.title
tags = tags or self.thread.tagnames
body_text = body_text or self.text
- return '{}\n\n{}\n\n{}'.format(title, tags, body_text)
+ return f'{title}\n\n{tags}\n\n{body_text}'
return body_text or self.text
def get_snippet(self, max_length=None):
@@ -2085,7 +2085,7 @@ def get_question_title(self):
else:
attr = None
if attr is not None:
- return '%s %s' % (self.thread.title, str(attr))
+ return f'{self.thread.title} {str(attr)}'
else:
return self.thread.title
raise NotImplementedError
@@ -2175,10 +2175,10 @@ def create(self, *args, **kwargs):
pending_revs.update(**kwargs)
revision = pending_revs[0]
except AssertionError:
- revision = super(PostRevisionManager, self).create(*args, **kwargs)
+ revision = super().create(*args, **kwargs)
else:
kwargs['revision'] = post.get_latest_revision_number() + 1
- revision = super(PostRevisionManager, self).create(*args, **kwargs)
+ revision = super().create(*args, **kwargs)
# set default summary
if revision.summary == '':
@@ -2355,8 +2355,7 @@ def should_notify_author_about_publishing(self, was_approved=False):
raise ValueError()
def __str__(self):
- return '%s - revision %s of %s' % (self.post.post_type, self.revision,
- self.title)
+ return f'{self.post.post_type} - revision {self.revision} of {self.title}'
def parent(self):
return self.post
@@ -2370,7 +2369,7 @@ def save(self, **kwargs):
if not self.ip_addr:
self.ip_addr = '0.0.0.0'
self.full_clean()
- super(PostRevision, self).save(**kwargs)
+ super().save(**kwargs)
def get_absolute_url(self):
diff --git a/askbot/models/question.py b/askbot/models/question.py
index 084e223911..f20129a29d 100644
--- a/askbot/models/question.py
+++ b/askbot/models/question.py
@@ -75,7 +75,7 @@ def default_title_renderer(thread):
else:
attr = None
if attr is not None:
- return '%s %s' % (thread.title, str(attr))
+ return f'{thread.title} {str(attr)}'
else:
return thread.title
@@ -174,7 +174,7 @@ def create_new(self, title, author, added_at, wiki, text, tagnames=None,
language = language or get_language()
tagnames = clean_tagnames(tagnames)
- thread = super(ThreadManager, self).create(
+ thread = super().create(
title=title, tagnames=tagnames, last_activity_at=added_at,
last_activity_by=author, language_code=language)
@@ -1784,7 +1784,7 @@ class Meta:
verbose_name_plural = _("favorite questions")
def __str__(self):
- return '[%s] favorited at %s' % (self.user, self.added_at)
+ return f'[{self.user}] favorited at {self.added_at}'
class DraftQuestion(DraftContent):
diff --git a/askbot/models/recent_contributors.py b/askbot/models/recent_contributors.py
index 36ab31555f..61ec46b375 100644
--- a/askbot/models/recent_contributors.py
+++ b/askbot/models/recent_contributors.py
@@ -8,7 +8,7 @@
from askbot.utils.translation import get_language
-class AvatarsBlockData(object):
+class AvatarsBlockData:
"""Class managing data for the avatars
block, displayed on the main page"""
CACHE_KEY = 'askbot-avatar-block-data'
diff --git a/askbot/models/reply_by_email.py b/askbot/models/reply_by_email.py
index faa2c2e872..7eb7f6d928 100644
--- a/askbot/models/reply_by_email.py
+++ b/askbot/models/reply_by_email.py
@@ -87,11 +87,7 @@ def was_used(self):
def as_email_address(self, prefix='reply-'):
"""returns email address, prefix is added
in front of the code"""
- return '%s%s@%s' % (
- prefix,
- self.address,
- askbot_settings.REPLY_BY_EMAIL_HOSTNAME
- )
+ return f'{prefix}{self.address}@{askbot_settings.REPLY_BY_EMAIL_HOSTNAME}'
def edit_post(self, body_text, title=None, edit_response=False):
"""edits the created post upon repeated response
diff --git a/askbot/models/repute.py b/askbot/models/repute.py
index adef027400..16e51c1fe6 100644
--- a/askbot/models/repute.py
+++ b/askbot/models/repute.py
@@ -59,7 +59,7 @@ class Meta:
verbose_name_plural = _("votes")
def __str__(self):
- return '[%s] voted at %s: %s' % (self.user, self.voted_at, self.vote)
+ return f'[{self.user}] voted at {self.voted_at}: {self.vote}'
def __int__(self):
"""1 if upvote -1 if downvote"""
@@ -142,10 +142,10 @@ class Meta:
verbose_name_plural = _("badge data")
def __str__(self):
- return '%s: %s' % (self.get_type_display(), self.slug)
+ return f'{self.get_type_display()}: {self.slug}'
def get_absolute_url(self):
- return '%s%s/' % (reverse('badge', args=[self.id]), self.slug)
+ return '{}{}/'.format(reverse('badge', args=[self.id]), self.slug)
class Award(models.Model):
@@ -159,7 +159,7 @@ class Award(models.Model):
notified = models.BooleanField(default=False)
def __str__(self):
- return '[%s] is awarded a badge [%s] at %s' % (self.user.username,
+ return '[{}] is awarded a badge [{}] at {}'.format(self.user.username,
self.badge.get_name(),
self.awarded_at)
def __lt__(self, other):
@@ -222,8 +222,7 @@ class Repute(models.Model):
objects = ReputeManager()
def __str__(self):
- return '[%s]\' reputation changed at %s' % (self.user.username,
- self.reputed_at)
+ return f'[{self.user.username}]\' reputation changed at {self.reputed_at}'
class Meta:
app_label = 'askbot'
@@ -236,7 +235,7 @@ def save(self, *args, **kwargs):
self.language_code = self.question.language_code
else:
self.language_code = get_language()
- super(Repute, self).save(*args, **kwargs)
+ super().save(*args, **kwargs)
def get_explanation_snippet(self):
"""returns HTML snippet with a link to related question
@@ -258,7 +257,7 @@ def get_explanation_snippet(self):
'question_title': self.question.thread.title
}
- return '%(question_title)s' % {
- 'url': self.question.get_absolute_url(),
- 'question_title': escape(self.question.thread.title),
- }
+ return '{question_title}'.format(
+ url=self.question.get_absolute_url(),
+ question_title=escape(self.question.thread.title),
+ )
diff --git a/askbot/models/tag.py b/askbot/models/tag.py
index 62814e6763..86b0b933c8 100644
--- a/askbot/models/tag.py
+++ b/askbot/models/tag.py
@@ -193,7 +193,7 @@ def create(self, name=None, created_by=None, auto_approve=False, **kwargs):
kwargs['name'] = name
kwargs['status'] = status
- return super(TagManager, self).create(**kwargs)
+ return super().create(**kwargs)
def create_in_bulk(self, tag_names=None, user=None, language_code=None, auto_approve=False):
"""creates tags by names. If user can create tags,
@@ -324,4 +324,4 @@ class Meta:
app_label = 'askbot'
def __str__(self):
- return '%s -> %s' % (self.source_tag_name, self.target_tag_name)
+ return f'{self.source_tag_name} -> {self.target_tag_name}'
diff --git a/askbot/models/user.py b/askbot/models/user.py
index 2ca057c6ae..10bd2b2593 100644
--- a/askbot/models/user.py
+++ b/askbot/models/user.py
@@ -22,7 +22,7 @@
PERSONAL_GROUP_NAME_PREFIX = '_personal_'
-class InvitedModerator(object):
+class InvitedModerator:
"""Mock user class to represent invited moderators"""
def __init__(self, username, email):
self.username = username
@@ -93,7 +93,7 @@ def remove_email_from_invited_moderators(email):
askbot_settings.update('INVITED_MODERATORS', value)
-class MockUser(object):
+class MockUser:
def __init__(self):
self.username = ''
@@ -314,7 +314,7 @@ class Activity(models.Model):
objects = ActivityManager()
def __str__(self):
- return '[%s] was active at %s' % (self.user.username, self.active_at)
+ return f'[{self.user.username}] was active at {self.active_at}'
class Meta:
app_label = 'askbot'
@@ -447,7 +447,7 @@ def __str__(self):
reported_at = "'not yet'"
else:
reported_at = '%s' % self.reported_at.strftime('%d/%m/%y %H:%M')
- return 'Email feed for %s type=%s, frequency=%s, reported_at=%s' % (
+ return 'Email feed for {} type={}, frequency={}, reported_at={}'.format(
self.subscriber,
self.feed_type,
self.frequency,
@@ -462,7 +462,7 @@ def save(self, *args, **kwargs):
.exclude(pk=self.id)
if similar.exists():
raise IntegrityError('email feed setting already exists')
- super(EmailFeedSetting, self).save(*args, **kwargs)
+ super().save(*args, **kwargs)
def get_previous_report_cutoff_time(self):
now = timezone.now()
@@ -564,7 +564,7 @@ def create(self, **kwargs):
kwargs['group_ptr'] = group_ptr
except AuthGroup.DoesNotExist:
pass
- return super(GroupManager, self).create(**kwargs)
+ return super().create(**kwargs)
def get_or_create(self, name=None, user=None, openness=None):
"""creates a group tag or finds one, if exists"""
@@ -705,7 +705,7 @@ def clean(self):
def save(self, *args, **kwargs):
self.clean()
- super(Group, self).save(*args, **kwargs)
+ super().save(*args, **kwargs)
class BulkTagSubscriptionManager(BaseQuerySetManager):
@@ -724,7 +724,7 @@ def create(
user_list = user_list or []
group_list = group_list or []
- new_object = super(BulkTagSubscriptionManager, self).create(**kwargs)
+ new_object = super().create(**kwargs)
tag_name_list = []
if tag_names:
diff --git a/askbot/models/user_profile.py b/askbot/models/user_profile.py
index 9dd2be85c3..be0e907130 100644
--- a/askbot/models/user_profile.py
+++ b/askbot/models/user_profile.py
@@ -13,7 +13,7 @@
# that the parameter is called "user" ...
def get_profile_cache_key(user):
if user.pk:
- return 'askbot-profile-{}'.format(user.pk)
+ return f'askbot-profile-{user.pk}'
raise ValueError('auth.models.User is not saved, cant make cache key')
@@ -230,7 +230,7 @@ def update_cache(self):
def save(self, *args, **kwargs):
self.update_cache()
- super(UserProfile, self).save(*args, **kwargs)
+ super().save(*args, **kwargs)
class LocalizedUserProfile(models.Model):
@@ -265,7 +265,7 @@ def update_cache(self):
def save(self, *args, **kwargs):
self.update_cache()
- super(LocalizedUserProfile, self).save(*args, **kwargs)
+ super().save(*args, **kwargs)
def update_user_profile(instance, **kwargs):
diff --git a/askbot/search/haystack/base.py b/askbot/search/haystack/base.py
index 49c49182f8..a564e1cb6c 100644
--- a/askbot/search/haystack/base.py
+++ b/askbot/search/haystack/base.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
import askbot
from django.conf import settings
from django.utils.translation import override
@@ -19,7 +18,7 @@ def _get_backend(self, using):
We set the backend alias to be able to determine language in multilanguage setup.
"""
self._backend_alias = using
- return super(BaseIndex, self)._get_backend(using)
+ return super()._get_backend(using)
def get_language(self, obj):
return None
@@ -57,6 +56,6 @@ def prepare(self, obj):
current_language = self.get_current_language(using=self._backend_alias, obj=obj)
with override(current_language):
- self.prepared_data = super(BaseIndex, self).prepare(obj)
+ self.prepared_data = super().prepare(obj)
self.prepared_data['text'] = ' '.join(self.prepared_data['text'].split())
return self.prepared_data
diff --git a/askbot/search/haystack/helpers.py b/askbot/search/haystack/helpers.py
index 4f4d4141a1..3ca8fad3a7 100644
--- a/askbot/search/haystack/helpers.py
+++ b/askbot/search/haystack/helpers.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
from haystack import connections
from haystack.exceptions import NotHandled
from haystack.query import SearchQuerySet
diff --git a/askbot/search/haystack/indexes.py b/askbot/search/haystack/indexes.py
index f4d2571756..c9ad704fa9 100644
--- a/askbot/search/haystack/indexes.py
+++ b/askbot/search/haystack/indexes.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
from django.conf import settings
from django.apps import apps
diff --git a/askbot/search/haystack/signals.py b/askbot/search/haystack/signals.py
index e96d6e5f06..86426f3087 100644
--- a/askbot/search/haystack/signals.py
+++ b/askbot/search/haystack/signals.py
@@ -22,10 +22,10 @@ def handle_delete(self, sender, instance, **kwargs):
# but still need to update/remove thread when post is removed.
instance, sender = (instance.thread, Thread)
- super(AskbotRealtimeSignalProcessor, self).handle_delete(sender, instance, **kwargs)
+ super().handle_delete(sender, instance, **kwargs)
def setup(self):
- super(AskbotRealtimeSignalProcessor, self).setup()
+ super().setup()
try:
askbot_signals.after_post_removed.connect(self.handle_delete)
@@ -33,7 +33,7 @@ def setup(self):
pass
def teardown(self):
- super(AskbotRealtimeSignalProcessor, self).setup()
+ super().setup()
#askbot signals
try:
askbot_signals.after_post_removed.disconnect(self.handle_delete)
diff --git a/askbot/search/haystack/utils.py b/askbot/search/haystack/utils.py
index 3223042dad..0b3091ecab 100644
--- a/askbot/search/haystack/utils.py
+++ b/askbot/search/haystack/utils.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
from django.core.exceptions import ImproperlyConfigured
from django.conf import settings
try:
@@ -24,7 +23,7 @@ def get_base_index():
required_fields = ['text']
if not all(field in BaseClass.fields for field in required_fields):
- raise ImproperlyConfigured('ASKBOT_HAYSTACK_INDEX_BASE_CLASS: %s must contain at least these fields: %s' % (index_string, required_fields))
+ raise ImproperlyConfigured(f'ASKBOT_HAYSTACK_INDEX_BASE_CLASS: {index_string} must contain at least these fields: {required_fields}')
return BaseClass
@@ -57,7 +56,7 @@ def alias_from_language(language):
connection_prefix = get_connection_prefix()
if connection_prefix:
- connection = '{0}_{1}'.format(connection_prefix, language)
+ connection = f'{connection_prefix}_{language}'
else:
connection = language
return connection
diff --git a/askbot/search/state_manager.py b/askbot/search/state_manager.py
index 1c0f37bab5..53f618a0d7 100644
--- a/askbot/search/state_manager.py
+++ b/askbot/search/state_manager.py
@@ -82,7 +82,7 @@ def parse_query(query):
'query_users': query_users
}
-class SearchState(object):
+class SearchState:
@classmethod
def get_empty(cls):
@@ -275,7 +275,7 @@ def change_page(self, new_page):
return ss
-class DummySearchState(object): # Used for caching question/thread summaries
+class DummySearchState: # Used for caching question/thread summaries
def add_tag(self, tag):
self.tag = tag
diff --git a/askbot/setup_templates/celery_app.py b/askbot/setup_templates/celery_app.py
index 87645a0720..9003a158d2 100644
--- a/askbot/setup_templates/celery_app.py
+++ b/askbot/setup_templates/celery_app.py
@@ -18,4 +18,4 @@
@app.task(bind=True)
def debug_task(self):
- print('Request: {0!r}'.format(self.request))
+ print(f'Request: {self.request!r}')
diff --git a/askbot/skins/askbot_environments.py b/askbot/skins/askbot_environments.py
index 7b2c96dfa9..b54a7c5c79 100644
--- a/askbot/skins/askbot_environments.py
+++ b/askbot/skins/askbot_environments.py
@@ -21,7 +21,7 @@
class MultilingualEnvironment(Environment):
def __init__(self, *args, **kwargs):
lang_code = kwargs.pop('language_code', None) # atm I don't see this ever becoming None
- super(MultilingualEnvironment, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
# The following caused problems before. Reverting to call set_language() explicitly
# if lang_code is not None:
# self.set_language(lang_code)
@@ -57,7 +57,7 @@ def __init__(self, *args, **kwargs):
key = self.build_sibling_key(this_sibling_key)
self.__class__.siblings[key] = self
- super(SkinEnvironment, self).__init__(*args, **kwargs)
+ super().__init__(*args, **kwargs)
@classmethod
def build_sibling_key(cls, parts):
diff --git a/askbot/skins/template_backends.py b/askbot/skins/template_backends.py
index 0172685ed6..6f602bb45a 100644
--- a/askbot/skins/template_backends.py
+++ b/askbot/skins/template_backends.py
@@ -6,7 +6,7 @@
class Template(OriginalJinja2Template):
# backend parameter was added with Django 1.11
def __init__(self, template, backend=None):
- super(Template,self).__init__(template, backend)
+ super().__init__(template, backend)
def render(self, context=None, request=None):
# dict from_context is from django_jinja and I am not sure if we still
@@ -14,6 +14,6 @@ def render(self, context=None, request=None):
if isinstance(context,BaseContext):
context = dict_from_context(context)
- return super(Template, self).render(context, request)
+ return super().render(context, request)
django.template.backends.jinja2.Template = Template
diff --git a/askbot/skins/utils.py b/askbot/skins/utils.py
index dee934cab8..4bb3c1d7aa 100644
--- a/askbot/skins/utils.py
+++ b/askbot/skins/utils.py
@@ -156,8 +156,7 @@ def get_media_url(url, ignore_missing = False):
use_skin = resolve_skin_for_media(media=url, preferred_skin = use_skin)
except MediaNotFound:
if ignore_missing == False:
- log_message = 'missing media resource %s in skin %s' \
- % (url, use_skin)
+ log_message = f'missing media resource {url} in skin {use_skin}'
logging.critical(log_message)
return None
diff --git a/askbot/spam_checker/akismet_spam_checker.py b/askbot/spam_checker/akismet_spam_checker.py
index 3963353c9d..5812ed97df 100644
--- a/askbot/spam_checker/akismet_spam_checker.py
+++ b/askbot/spam_checker/akismet_spam_checker.py
@@ -68,7 +68,7 @@ def call_akismet(text,
elif command == 'submit_ham':
return api.submit_ham(ip_addr, user_agent, **data)
else:
- raise RuntimeError('unknown akismet method: "{}"'.format(command))
+ raise RuntimeError(f'unknown akismet method: "{command}"')
except APIKeyError:
logging.critical('Akismet Key is missing')
except AkismetError:
diff --git a/askbot/startup_procedures.py b/askbot/startup_procedures.py
index 17900ed459..da6a511ffa 100644
--- a/askbot/startup_procedures.py
+++ b/askbot/startup_procedures.py
@@ -46,7 +46,7 @@ def __init__(self, error_message):
if sys.__stdin__.isatty():
#print footer only when askbot is run from the shell
msg += FOOTER
- super(AskbotConfigError, self).__init__(msg)
+ super().__init__(msg)
def domain_is_bad():
@@ -222,7 +222,7 @@ def try_import(module_name, pypi_package_name, show_requirements_message=True,
def unparse_requirement(req):
line = req.name
if req.specs:
- specs = ['%s%s' % spec for spec in req.specs]
+ specs = ['{}{}'.format(*spec) for spec in req.specs]
line += ','.join(specs)
if req.extras:
line += ' [%s]' % ','.join(req.extras)
@@ -402,7 +402,7 @@ def test_media_url():
)
-class SettingsTester(object):
+class SettingsTester:
"""class to test contents of the settings.py file"""
def __init__(self, requirements=None):
diff --git a/askbot/templatetags/extra_filters_jinja.py b/askbot/templatetags/extra_filters_jinja.py
index 56121f0e25..638c069c17 100644
--- a/askbot/templatetags/extra_filters_jinja.py
+++ b/askbot/templatetags/extra_filters_jinja.py
@@ -435,8 +435,8 @@ def convert_text(text):
'=': '\\u003D',
'-': '\\u002D',
';': '\\u003B',
- u'\u2028': '\\u2028',
- u'\u2029': '\\u2029'
+ '\u2028': '\\u2028',
+ '\u2029': '\\u2029'
}
# Escape every ASCII character with a value less than 32.
_js_escapes.update(('%c' % z, '\\u%04X' % z) for z in range(32))
diff --git a/askbot/tests/skip_test_reply_by_email.py b/askbot/tests/skip_test_reply_by_email.py
index 2bc6288bd5..0fc0cb8964 100644
--- a/askbot/tests/skip_test_reply_by_email.py
+++ b/askbot/tests/skip_test_reply_by_email.py
@@ -17,7 +17,7 @@
TEST_CONTENT = 'Test content'
TEST_LONG_CONTENT = 'Test content' * 10
-class MockPart(object):
+class MockPart:
def __init__(self, body, content_type='text/plain'):
self.body = body
self.content_encoding = {'Content-Type':(content_type,)}
diff --git a/askbot/tests/test_akismet.py b/askbot/tests/test_akismet.py
index d9ef220928..de2ea53101 100644
--- a/askbot/tests/test_akismet.py
+++ b/askbot/tests/test_akismet.py
@@ -7,8 +7,8 @@
AKISMET_CLASSIFIER = 'askbot.spam_checker.akismet_spam_checker.is_spam'
TEXT = 'hello foobar'
API_KEY = 'foobar'
-CHECK_SPAM_URL = 'https://{}.rest.akismet.com/1.1/comment-check'.format(API_KEY)
-SUBMIT_SPAM_URL = 'https://{}.rest.akismet.com/1.1/submit-spam'.format(API_KEY)
+CHECK_SPAM_URL = f'https://{API_KEY}.rest.akismet.com/1.1/comment-check'
+SUBMIT_SPAM_URL = f'https://{API_KEY}.rest.akismet.com/1.1/submit-spam'
VERIFY_KEY_URL = 'https://rest.akismet.com/1.1/verify-key'
USER_AGENT = 'user_agent_string'
USER_IP = '0.0.0.0'
@@ -16,7 +16,7 @@
COMMENT_AUTHOR_EMAIL = 'bob@example.com'
-class User(object):
+class User:
def __init__(self, anon=False, username=COMMENT_AUTHOR, email=COMMENT_AUTHOR_EMAIL):
self.anon = anon
if anon:
@@ -34,7 +34,7 @@ def is_anonymous(self):
return self.anon
-class AuthRequest(object):
+class AuthRequest:
environ = {'HTTP_USER_AGENT': USER_AGENT}
META = {'REMOTE_ADDR': USER_IP}
def __init__(self, anon=False, username=COMMENT_AUTHOR, email=COMMENT_AUTHOR_EMAIL):
diff --git a/askbot/tests/test_email_alerts.py b/askbot/tests/test_email_alerts.py
index 8effc0839e..5d98e76ff8 100644
--- a/askbot/tests/test_email_alerts.py
+++ b/askbot/tests/test_email_alerts.py
@@ -299,8 +299,7 @@ def check_results(self, test_key = None):
self.assertEqual(len(outbox), expected['message_count'], error_message)
if expected['message_count'] > 0:
if len(outbox) > 0:
- error_message = 'expected recipient %s found %s' % \
- (self.target_user.email, outbox[0].recipients()[0])
+ error_message = f'expected recipient {self.target_user.email} found {outbox[0].recipients()[0]}'
#verify that target user receives the email
self.assertEqual(
outbox[0].recipients()[0],
@@ -901,7 +900,7 @@ class AcceptAnswerReminderTests(EmailReminderTestCase):
command_name = 'send_accept_answer_reminders'
def do_post(self, timestamp):
- super(AcceptAnswerReminderTests, self).do_post(timestamp)
+ super().do_post(timestamp)
self.answer = self.post_answer(
question = self.question,
user = self.u2,
diff --git a/askbot/tests/test_email_parsing.py b/askbot/tests/test_email_parsing.py
index 56340e67c7..5a7724c6ef 100644
--- a/askbot/tests/test_email_parsing.py
+++ b/askbot/tests/test_email_parsing.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
from django.conf import settings as django_settings
from django.template import Context
from django.template.loader import get_template
diff --git a/askbot/tests/test_management_commands.py b/askbot/tests/test_management_commands.py
index 855c3ba32c..b05e8b641a 100644
--- a/askbot/tests/test_management_commands.py
+++ b/askbot/tests/test_management_commands.py
@@ -119,7 +119,7 @@ def test_command(self):
# put three upfiles in place
paths = list()
for idx in range(1, 4):
- path = self.put_upfile('file{}.txt'.format(idx))
+ path = self.put_upfile(f'file{idx}.txt')
paths.append(path)
# post question with an image
@@ -223,7 +223,7 @@ def test_askbot_add_user(self):
subs = models.EmailFeedSetting.objects.filter(
subscriber = user,
)
- self.assertEquals(subs.count(), 6)
+ self.assertEqual(subs.count(), 6)
#try to log in
user = auth.authenticate(username=username, password=password)
self.assertTrue(user is not None)
diff --git a/askbot/tests/test_markup.py b/askbot/tests/test_markup.py
index 6d38549727..1ef523a3a0 100644
--- a/askbot/tests/test_markup.py
+++ b/askbot/tests/test_markup.py
@@ -1,4 +1,3 @@
-# -*- coding: utf-8 -*-
from django.conf import settings as django_settings
from django.test import TestCase
from askbot.utils.markup import markdown_input_converter
diff --git a/askbot/tests/test_page_load.py b/askbot/tests/test_page_load.py
index 2f51ac29ec..b0ae433fd3 100644
--- a/askbot/tests/test_page_load.py
+++ b/askbot/tests/test_page_load.py
@@ -47,11 +47,11 @@ def setUpClass(cls):
everyone.save()
activate_language(settings.LANGUAGE_CODE)
management.call_command('askbot_add_test_content', verbosity=0, interactive=False)
- super(PageLoadTestCase, cls).setUpClass()
+ super().setUpClass()
@classmethod
def tearDownClass(cls):
- super(PageLoadTestCase, cls).tearDownClass()
+ super().tearDownClass()
management.call_command('flush', verbosity=0, interactive=False)
def _fixture_setup(self):
@@ -91,7 +91,7 @@ def try_url(
else:
url_info = 'getting url %s' % url
if data:
- url_info += '?' + '&'.join(['%s=%s' % (k, v) for k, v in data.items()])
+ url_info += '?' + '&'.join([f'{k}={v}' for k, v in data.items()])
# print(url_info)
# if redirect expected, but we wont' follow
diff --git a/askbot/tests/test_permission_assertions.py b/askbot/tests/test_permission_assertions.py
index cbb6fc9834..494612d351 100644
--- a/askbot/tests/test_permission_assertions.py
+++ b/askbot/tests/test_permission_assertions.py
@@ -56,7 +56,7 @@ def post_answer(self, question = None, author = None):
class SeeOffensiveFlagsPermissionAssertionTests(utils.AskbotTestCase):
def setUp(self):
- super(SeeOffensiveFlagsPermissionAssertionTests, self).setUp()
+ super().setUp()
self.create_user()
self.create_user(username = 'other_user')
self.min_rep = askbot_settings.MIN_REP_TO_VIEW_OFFENSIVE_FLAGS
@@ -173,10 +173,7 @@ def setUp(self):
def post_answer(self, user = None):
if user is None:
user = self.user
- self.answer = super(
- DeleteAnswerPermissionAssertionTests,
- self
- ).post_answer(
+ self.answer = super().post_answer(
question = self.question,
user = user
)
@@ -313,7 +310,7 @@ def test_moderator_can_delete_question_with_upvoted_answer_by_other(self):
class CloseQuestionPermissionAssertionTests(utils.AskbotTestCase):
def setUp(self):
- super(CloseQuestionPermissionAssertionTests, self).setUp()
+ super().setUp()
self.create_user()
self.create_user(username = 'other_user')
self.question = self.post_question()
@@ -609,10 +606,7 @@ class EditAnswerPermissionAssertionTests(
EditQuestionPermissionAssertionTests
):
def setUp(self):
- super(
- EditAnswerPermissionAssertionTests,
- self,
- ).setUp()
+ super().setUp()
self.post = self.post_answer(question = self.post)
def assert_user_can(
@@ -649,10 +643,7 @@ class RetagQuestionPermissionAssertionTests(
):
def setUp(self):
- super(
- RetagQuestionPermissionAssertionTests,
- self,
- ).setUp()
+ super().setUp()
self.min_rep = askbot_settings.MIN_REP_TO_RETAG_OTHERS_QUESTIONS
def assert_user_can(
diff --git a/askbot/tests/test_user_views.py b/askbot/tests/test_user_views.py
index c5eacea041..51ed29da21 100644
--- a/askbot/tests/test_user_views.py
+++ b/askbot/tests/test_user_views.py
@@ -4,7 +4,7 @@
from django.contrib.auth.models import AnonymousUser
from django.urls import reverse
from django.http import HttpResponseRedirect
-from mock import Mock
+from unittest.mock import Mock
import urllib.request, urllib.parse, urllib.error
import urllib.parse
diff --git a/askbot/tests/utils.py b/askbot/tests/utils.py
index a2b8945ed3..1572e070a0 100644
--- a/askbot/tests/utils.py
+++ b/askbot/tests/utils.py
@@ -109,7 +109,7 @@ class AskbotTestCase(TestCase):
"""
def _fixture_setup(self):
- super(AskbotTestCase, self)._fixture_setup()
+ super()._fixture_setup()
for app_config in apps.get_app_configs():
create_contenttypes(app_config)
create_permissions(app_config)
@@ -120,7 +120,7 @@ def _fixture_teardown(self):
post_migrate.disconnect(create_contenttypes)
post_migrate.disconnect(create_permissions, dispatch_uid="django.contrib.auth.management.create_permissions")
- super(AskbotTestCase, self)._fixture_teardown()
+ super()._fixture_teardown()
post_migrate.connect(create_contenttypes)
post_migrate.connect(create_permissions, dispatch_uid="django.contrib.auth.management.create_permissions")
@@ -130,7 +130,7 @@ def _fixture_teardown(self):
@classmethod
def setUpClass(cls):
cache.clear()
- super(AskbotTestCase, cls).setUpClass()
+ super().setUpClass()
def create_user(
self,
@@ -170,7 +170,7 @@ def assertRaisesRegexp(self, *args, **kwargs):
"""a shim for python < 2.7"""
try:
#run assertRaisesRegex, if available
- super(AskbotTestCase, self).assertRaisesRegex(*args, **kwargs)
+ super().assertRaisesRegex(*args, **kwargs)
except AttributeError:
#in this case lose testing for the error text
#second argument is the regex that is supposed
diff --git a/askbot/urls.py b/askbot/urls.py
index de33b2fb70..cb9d48bd3c 100644
--- a/askbot/urls.py
+++ b/askbot/urls.py
@@ -40,13 +40,13 @@
re_path(
# Note that all parameters, even if optional, are provided to the view. Non-present ones have None value.
(r'^%s' % MAIN_PAGE_BASE_URL.strip('/') +
- r'(%s)?' % r'/scope:(?P\w+)' +
- r'(%s)?' % r'/sort:(?P[\w\-]+)' +
- r'(%s)?' % r'/tags:(?P[\w+.#,-]+)' + # Should match: const.TAG_CHARS + ','; TODO: Is `#` char decoded by the time URLs are processed ??
- r'(%s)?' % r'/author:(?P\d+)' +
- r'(%s)?' % r'/page:(?P\d+)' +
- r'(%s)?' % r'/page-size:(?P\d+)' +
- r'(%s)?' % r'/query:(?P.+)' + # INFO: query is last, b/c it can contain slash!!!
+ r'({})?'.format(r'/scope:(?P\w+)') +
+ r'({})?'.format(r'/sort:(?P[\w\-]+)') +
+ r'({})?'.format(r'/tags:(?P[\w+.#,-]+)') + # Should match: const.TAG_CHARS + ','; TODO: Is `#` char decoded by the time URLs are processed ??
+ r'({})?'.format(r'/author:(?P\d+)') +
+ r'({})?'.format(r'/page:(?P\d+)') +
+ r'({})?'.format(r'/page-size:(?P\d+)') +
+ r'({})?'.format(r'/query:(?P.+)') + # INFO: query is last, b/c it can contain slash!!!
r'/$'),
views.readers.questions,
name='questions'
@@ -72,7 +72,7 @@
name='users'
),
re_path(
- r'^%s%s(?P\d+)/(?P.*)/$' % (
+ r'^{}{}(?P\d+)/(?P.*)/$'.format(
pgettext('urls', 'users/'),
pgettext('urls', 'by-group/')
),
@@ -82,17 +82,17 @@
),
# TODO: rename as user_edit, b/c that's how template is named
re_path(
- r'^%s(?P\d+)/%s$' % (pgettext('urls', 'users/'), pgettext('urls', 'edit/')),
+ r'^{}(?P\d+)/{}$'.format(pgettext('urls', 'users/'), pgettext('urls', 'edit/')),
views.users.edit_user,
name='edit_user'
),
service_url(
- r'^%s(?P\d+)/%s(?P.+)/$' % (pgettext('urls', 'users/'), pgettext('urls', 'download-data/')),
+ r'^{}(?P\d+)/{}(?P.+)/$'.format(pgettext('urls', 'users/'), pgettext('urls', 'download-data/')),
views.users.download_user_data,
name='download_user_data'
),
service_url(#ajax get only
- r'^%s(?P\d+)/%s$' % (pgettext('urls', 'users/'), pgettext('urls', 'get-todays-backup-file-name/')),
+ r'^{}(?P\d+)/{}$'.format(pgettext('urls', 'users/'), pgettext('urls', 'get-todays-backup-file-name/')),
views.users.get_todays_backup_file_name,
name='get_todays_backup_file_name'
),
@@ -112,7 +112,7 @@
name='set_user_description',
),
re_path(
- r'^%s(?P\d+)/(?P.+)/%s$' % (
+ r'^{}(?P\d+)/(?P.+)/{}$'.format(
pgettext('urls', 'users/'),
pgettext('urls', 'subscriptions/'),
),
@@ -121,7 +121,7 @@
name='user_subscriptions'
),
re_path(
- r'^%s%s$' % (
+ r'^{}{}$'.format(
pgettext('urls', 'users/'),
pgettext('urls', 'unsubscribe/'),
),
@@ -129,7 +129,7 @@
name='user_unsubscribe'
),
re_path(
- r'^%s(?P\d+)/(?P.+)/%s$' % (
+ r'^{}(?P\d+)/(?P.+)/{}$'.format(
pgettext('urls', 'users/'),
pgettext('urls', 'select_languages/'),
),
@@ -198,12 +198,12 @@
),
re_path(r'^%s$' % pgettext('urls', 'help/'), views.meta.help_page, name='help'),
service_url(
- r'^%s(?P\d+)/%s$' % (pgettext('urls', 'answers/'), pgettext('urls', 'edit/')),
+ r'^{}(?P\d+)/{}$'.format(pgettext('urls', 'answers/'), pgettext('urls', 'edit/')),
views.writers.edit_answer,
name='edit_answer'
),
re_path(
- r'^%s(?P\d+)/%s$' % (pgettext('urls', 'answers/'), pgettext('urls', 'revisions/')),
+ r'^{}(?P\d+)/{}$'.format(pgettext('urls', 'answers/'), pgettext('urls', 'revisions/')),
views.readers.revisions,
kwargs={'post_type': 'answer'},
name='answer_revisions'
@@ -300,27 +300,27 @@
name='get_post_html'
),
re_path(
- r'^%s%s$' % (MAIN_PAGE_BASE_URL, pgettext('urls', 'ask/')),
+ r'^{}{}$'.format(MAIN_PAGE_BASE_URL, pgettext('urls', 'ask/')),
views.writers.ask,
name='ask'
),
service_url( # this url is both regular and ajax
- r'^%s(?P\d+)/%s$' % (MAIN_PAGE_BASE_URL, pgettext('urls', 'retag/')),
+ r'^{}(?P\d+)/{}$'.format(MAIN_PAGE_BASE_URL, pgettext('urls', 'retag/')),
views.writers.retag_question,
name='retag_question'
),
re_path(
- r'^%s%s(?P\d+)$' % (MAIN_PAGE_BASE_URL, pgettext('urls', 'close/')),
+ r'^{}{}(?P\d+)$'.format(MAIN_PAGE_BASE_URL, pgettext('urls', 'close/')),
views.commands.close,
name='close'
),
re_path(
- r'^%s%s(?P\d+)$' % (MAIN_PAGE_BASE_URL, pgettext('urls', 'reopen/')),
+ r'^{}{}(?P\d+)$'.format(MAIN_PAGE_BASE_URL, pgettext('urls', 'reopen/')),
views.commands.reopen,
name='reopen'
),
service_url(
- r'^%s(?P\d+)/%s$' % (MAIN_PAGE_BASE_URL, pgettext('urls', 'answer/')),
+ r'^{}(?P\d+)/{}$'.format(MAIN_PAGE_BASE_URL, pgettext('urls', 'answer/')),
views.writers.answer,
name='answer'
),
@@ -335,7 +335,7 @@
name='vote'
),
re_path(
- r'^%s(?P\d+)/%s$' % (MAIN_PAGE_BASE_URL, pgettext('urls', 'revisions/')),
+ r'^{}(?P\d+)/{}$'.format(MAIN_PAGE_BASE_URL, pgettext('urls', 'revisions/')),
views.readers.revisions,
kwargs={'post_type': 'question'},
name='question_revisions'
@@ -393,12 +393,12 @@
name='publish_post'
),
service_url(
- r'^%s%s$' % (pgettext('urls', 'tags/'), pgettext('urls', 'subscriptions/')),
+ r'^{}{}$'.format(pgettext('urls', 'tags/'), pgettext('urls', 'subscriptions/')),
views.commands.list_bulk_tag_subscription,
name='list_bulk_tag_subscription'
),
service_url( # post only
- r'^%s%s%s$' % (
+ r'^{}{}{}$'.format(
pgettext('urls', 'tags/'),
pgettext('urls', 'subscriptions/'),
pgettext('urls', 'delete/')
@@ -407,7 +407,7 @@
name='delete_bulk_tag_subscription'
),
service_url(
- r'^%s%s%s$' % (
+ r'^{}{}{}$'.format(
pgettext('urls', 'tags/'),
pgettext('urls', 'subscriptions/'),
pgettext('urls', 'create/')
@@ -416,7 +416,7 @@
name='create_bulk_tag_subscription'
),
service_url(
- r'^%s%s%s(?P\d+)/$' % (
+ r'^{}{}{}(?P\d+)/$'.format(
pgettext('urls', 'tags/'),
pgettext('urls', 'subscriptions/'),
pgettext('urls', 'edit/')
@@ -430,25 +430,25 @@
name='list_suggested_tags'
),
service_url( # ajax only
- r'^%s$' % 'moderate-suggested-tag',
+ r'^{}$'.format('moderate-suggested-tag'),
views.commands.moderate_suggested_tag,
name='moderate_suggested_tag'
),
# TODO: collapse these three urls and use an extra json data var
service_url( # ajax only
- r'^%s%s$' % ('mark-tag/', 'interesting/'),
+ r'^{}{}$'.format('mark-tag/', 'interesting/'),
views.commands.mark_tag,
kwargs={'reason': 'good', 'action': 'add'},
name='mark_interesting_tag'
),
service_url( # ajax only
- r'^%s%s$' % ('mark-tag/', 'ignored/'),
+ r'^{}{}$'.format('mark-tag/', 'ignored/'),
views.commands.mark_tag,
kwargs={'reason': 'bad', 'action': 'add'},
name='mark_ignored_tag'
),
service_url( # ajax only
- r'^%s%s$' % ('mark-tag/', 'subscribed/'),
+ r'^{}{}$'.format('mark-tag/', 'subscribed/'),
views.commands.mark_tag,
kwargs={'reason': 'subscribed', 'action': 'add'},
name='mark_subscribed_tag'
diff --git a/askbot/user_messages/context_processors.py b/askbot/user_messages/context_processors.py
index 38e3880816..410a35c002 100644
--- a/askbot/user_messages/context_processors.py
+++ b/askbot/user_messages/context_processors.py
@@ -28,7 +28,7 @@ def user_messages(request):
return { 'user_messages': messages }
return {}
-class LazyMessages(object):
+class LazyMessages:
"""
Lazy message container, so messages aren't actually retrieved from
session and deleted until the template asks for them.
diff --git a/askbot/utils/classes.py b/askbot/utils/classes.py
index d3585cb6a7..0173145625 100644
--- a/askbot/utils/classes.py
+++ b/askbot/utils/classes.py
@@ -3,7 +3,7 @@
from django.utils import timezone
from django.conf import settings as django_settings
-class ReminderSchedule(object): #pylint: disable=too-few-public-methods
+class ReminderSchedule: #pylint: disable=too-few-public-methods
"""class that given the three settings:
* days to wait before sending the reminders
* frequency of reminders
diff --git a/askbot/utils/console.py b/askbot/utils/console.py
index 562e09cce1..fdc920fe89 100644
--- a/askbot/utils/console.py
+++ b/askbot/utils/console.py
@@ -42,10 +42,10 @@ def choice_dialog(prompt_phrase, choices=None, invalid_phrase=None, default=None
choices = [str(ch) for ch in choices]
if default is None:
- prompt = '%s\ntype %s\n> ' % (prompt_phrase, '/'.join(choices))
+ prompt = '{}\ntype {}\n> '.format(prompt_phrase, '/'.join(choices))
else:
default = str(default)
- prompt = '%s\nType %s, press ENTER to select %s\n> ' % (prompt_phrase, '/'.join(choices), default)
+ prompt = '{}\nType {}, press ENTER to select {}\n> '.format(prompt_phrase, '/'.join(choices), default)
while 1:
response = input(prompt).strip()
@@ -77,9 +77,9 @@ def numeric_choice_dialog(prompt_phrase, choices, default=None):
assert(not isinstance(choices, str))
choice_menu = "\n".join(["%d - %s" % (i,x) for i, x in enumerate(choices)])
if default:
- prompt_phrase = '%s\n%s\nPress ENTER to select %s> ' % (choice_menu, prompt_phrase, default)
+ prompt_phrase = f'{choice_menu}\n{prompt_phrase}\nPress ENTER to select {default}> '
else:
- prompt_phrase = '%s\n%s> ' % (choice_menu, prompt_phrase)
+ prompt_phrase = f'{choice_menu}\n{prompt_phrase}> '
while True:
response = input(prompt_phrase).strip()
@@ -122,7 +122,7 @@ def numeric_multiple_choice_dialog(prompt_phrase, choices, all_option=False):
choice_indexes = []
index = False
while True:
- response = input('\n%s\n%s> ' % (choice_menu, prompt_phrase))
+ response = input(f'\n{choice_menu}\n{prompt_phrase}> ')
selections = response.split()
print("selections: %s" % selections)
for c in selections:
@@ -246,7 +246,7 @@ def print_progress(elapsed, total, nowipe = False):
output = '%6.2f%%' % (100 * float(elapsed)/float(total))
print_action(output, nowipe)
-class ProgressBar(object):
+class ProgressBar:
"""A wrapper for an iterator, that prints
a progress bar along the way of iteration
"""
@@ -293,7 +293,7 @@ def print_progress_percent(self):
def finish_progress_bar(self):
"""brint the last bars, to make all bars equal length"""
self.backspace_progress_percent()
- sys.stdout.write('-' * int(math.floor((self.max_barlen - self.curr_barlen))))
+ sys.stdout.write('-' * int(math.floor(self.max_barlen - self.curr_barlen)))
def __next__(self):
diff --git a/askbot/utils/forms.py b/askbot/utils/forms.py
index 3054cd3248..351359b952 100644
--- a/askbot/utils/forms.py
+++ b/askbot/utils/forms.py
@@ -94,10 +94,7 @@ def clean(self, value):
class NextUrlField(forms.CharField):
def __init__(self):
- super(
- NextUrlField,
- self
- ).__init__(
+ super().__init__(
max_length = 255,
widget = forms.HiddenInput(),
required = False
@@ -145,7 +142,7 @@ def __init__(
widget_attrs = login_form_widget_attrs
max_length = 30#todo: support custom length of user name MAX_USERNAME_LENGTH()
- super(UserNameField,self).__init__(
+ super().__init__(
max_length=max_length,
widget=forms.TextInput(attrs=widget_attrs),
label=label,
@@ -168,7 +165,7 @@ def clean(self, username):
raise TypeError('user instance must be of type User')
try:
- username = super(UserNameField, self).clean(username)
+ username = super().clean(username)
except forms.ValidationError:
raise forms.ValidationError(self.error_messages['required'])
@@ -262,7 +259,7 @@ def __init__(self, skip_clean=False, **kw):
else:
widget_class = forms.TextInput
- super(UserEmailField,self).__init__(
+ super().__init__(
widget=widget_class(
attrs=dict(login_form_widget_attrs, maxlength=200)
),
@@ -285,7 +282,7 @@ def clean(self, email):
moderated_email_validator(email)
- email = super(UserEmailField,self).clean(email)
+ email = super().clean(email)
if self.skip_clean:
return email
@@ -320,7 +317,7 @@ class SetPasswordForm(forms.Form):
)
def __init__(self, data=None, user=None, *args, **kwargs):
- super(SetPasswordForm, self).__init__(data, *args, **kwargs)
+ super().__init__(data, *args, **kwargs)
def clean_password2(self):
"""
diff --git a/askbot/utils/jive.py b/askbot/utils/jive.py
index ae03ee0851..e8e2ed975e 100755
--- a/askbot/utils/jive.py
+++ b/askbot/utils/jive.py
@@ -1,5 +1,4 @@
#!/usr/bin/env python
-# -*- coding: utf-8 -*-
# Copyright (c) Askbot S.p.A. 2013
# License: MIT (http://www.opensource.org/licenses/mit-license.php)
r"""Converter of Jive markup to markdown,
@@ -23,16 +22,8 @@
import codecs
#---- Python version compat
-if sys.version_info[:2] < (2,4):
- from sets import Set as set
- def reversed(sequence):
- for i in sequence[::-1]:
- yield i
- def _unicode_decode(s, encoding, errors='xmlcharrefreplace'):
- return str(s, encoding, errors)
-else:
- def _unicode_decode(s, encoding, errors='strict'):
- return s.decode(encoding, errors)
+def _unicode_decode(s, encoding, errors='strict'):
+ return s.decode(encoding, errors)
#---- globals
@@ -78,7 +69,7 @@ def _regularize_eols(text):
text = re.sub(r'\n{2,}', '\n', text)
return text.strip('\n')
-class JiveConverter(object):
+class JiveConverter:
"""converts Jive Markup into HTML"""
def __init__(self):
@@ -206,14 +197,14 @@ def _hypertext_link_sub1(self, match):
elif num_bits == 1:
link = link_bits[0]
if self._url_re.match(link) or not self._email_re.match(link):
- return '%s' % (link, link)
+ return f'{link}'
elif num_bits in (2, 3):
#if self._url_re.match(link_bits[1]):
if num_bits == 2:
- return '%s' % (link_bits[1], link_bits[0])
+ return f'{link_bits[0]}'
else:
bits = link_bits
- return '%s' % (bits[1], bits[2], bits[0])
+ return f'{bits[0]}'
return '[' + '|'.join(link_bits) + ']'
_hypertext_link_re2 = re.compile(r'\[url\]%s\[/url\]' % _url_pattern)
@@ -264,7 +255,7 @@ def _do_links(self, text):
def _h_sub(self, match):
n = match.group(1)
text = self._run_span_gamut(match.group(2))
- html = '%s' % (n, text, n)
+ html = f'{text}'
return self._hashed(html)
def _do_headers(self, text):
@@ -392,7 +383,7 @@ def _list_sub(self, match):
text = self._list_item_re.sub(self._list_item_sub, text)
text = self._nested_list_re.sub(self._nested_list_sub, text)
tag = (match.group(2) == '*' and 'ul' or 'ol')
- html = '<%s>\n%s%s>' % (tag, text, tag)
+ html = f'<{tag}>\n{text}{tag}>'
return self._hashed(html)
_list_re = re.compile(
@@ -408,7 +399,7 @@ def _do_lists(self, text):
def _leading_blanks_sub(self, match):
spaces = match.group(1)
text = match.group(2)
- return '%s%s\n' % (' '*len(spaces), text)
+ return '{}{}\n'.format(' '*len(spaces), text)
def _preserve_leading_blanks(self, text):
"""replace leading blanks with """
@@ -437,7 +428,7 @@ def _form_paragraphs(self, text):
def _auto_link_sub(self, match):
"""auto-links are just passed through"""
link = match.group(1)
- return '%s' % (link, link)
+ return f'{link}'
_auto_email_link_re = re.compile(r"""
\[
@@ -448,7 +439,7 @@ def _auto_link_sub(self, match):
""" % _email_pattern, re.I | re.X | re.U)
def _auto_email_link_sub(self, match):
email = match.group(1)
- return '%s' % (email, email)
+ return f'{email}'
def _do_auto_links(self, text):
text = self._auto_link_re.sub(self._auto_link_sub, text)
diff --git a/askbot/utils/markup.py b/askbot/utils/markup.py
index 70d704af69..3a379a3684 100644
--- a/askbot/utils/markup.py
+++ b/askbot/utils/markup.py
@@ -82,7 +82,7 @@ def format_mention_in_html(mentioned_user):
try:
url = mentioned_user.get_profile_url()
username = mentioned_user.username
- return '@%s' % (url, username)
+ return f'@{username}'
except NoReverseMatch:
return ""
diff --git a/askbot/utils/mysql.py b/askbot/utils/mysql.py
index 08e41b4428..161786b9af 100644
--- a/askbot/utils/mysql.py
+++ b/askbot/utils/mysql.py
@@ -16,7 +16,7 @@ def mysql_table_supports_full_text_search(table_name):
def get_drop_index_sql(index_name, table_name):
"""returns sql for dropping index by name on table"""
- return 'ALTER TABLE %s DROP INDEX %s' % (table_name, index_name)
+ return f'ALTER TABLE {table_name} DROP INDEX {index_name}'
def get_create_full_text_index_sql(index_name, table_name, column_list):
diff --git a/askbot/utils/transaction.py b/askbot/utils/transaction.py
index 2921fc504b..0d62a2bfe9 100644
--- a/askbot/utils/transaction.py
+++ b/askbot/utils/transaction.py
@@ -2,7 +2,7 @@
from django.conf import settings as django_settings
#from django.core.signals import request_finished
-class DummyTransaction(object):
+class DummyTransaction:
"""Dummy transaction class
that can be imported instead of the django
transaction management and debug issues
diff --git a/askbot/utils/twitter.py b/askbot/utils/twitter.py
index 2e7f701eeb..4431d464ec 100644
--- a/askbot/utils/twitter.py
+++ b/askbot/utils/twitter.py
@@ -4,10 +4,10 @@
class Twitter(OAuthConnection):
def __new__(cls):
- return super(Twitter, cls).__new__(cls, 'twitter')
+ return super().__new__(cls, 'twitter')
def __init__(self):
- super(Twitter, self).__init__('twitter')
+ super().__init__('twitter')
self.tweet_url = 'https://api.twitter.com/1.1/statuses/update.json'
def tweet(self, text, access_token=None):
diff --git a/askbot/utils/unicode_detect.py b/askbot/utils/unicode_detect.py
index b6004a12d7..12e6a15bb8 100644
--- a/askbot/utils/unicode_detect.py
+++ b/askbot/utils/unicode_detect.py
@@ -604,7 +604,7 @@ def _compile_scripts_txt():
idx.append((int(a, 16), int(b or a, 16), names.index(name), cats.index(cat)))
idx.sort()
- print('script_data = {\n"names":%s,\n"cats":%s,\n"idx":[\n%s\n]}' % (
+ print('script_data = {{\n"names":{},\n"cats":{},\n"idx":[\n{}\n]}}'.format(
'\n'.join(textwrap.wrap(repr(names), 80)),
'\n'.join(textwrap.wrap(repr(cats), 80)),
'\n'.join(textwrap.wrap(', '.join('(0x%x,0x%x,%d,%d)' % c for c in idx), 80))))
diff --git a/askbot/utils/views.py b/askbot/utils/views.py
index de3c3f0f77..dc09796927 100644
--- a/askbot/utils/views.py
+++ b/askbot/utils/views.py
@@ -19,7 +19,7 @@ def is_askbot_view(view_func):
return True
return False
-class PjaxView(object):
+class PjaxView:
"""custom class-based view
to be used for pjax use and for generation
of content in the traditional way, where
diff --git a/askbot/views/readers.py b/askbot/views/readers.py
index d919109219..4e389d9b6e 100644
--- a/askbot/views/readers.py
+++ b/askbot/views/readers.py
@@ -1,4 +1,3 @@
-# encoding:utf-8
"""
:synopsis: views "read-only" for main textual content
diff --git a/askbot/views/users.py b/askbot/views/users.py
index 832e37efd3..6f84e7e3ad 100644
--- a/askbot/views/users.py
+++ b/askbot/views/users.py
@@ -239,13 +239,13 @@ def users_list(request, by_group=False, group_id=None, group_slug=None):
matching_users.order_by('-askbot_profile__reputation'),
askbot_settings.USERS_PAGE_SIZE
)
- base_url = request.path + '?query=%s&sort=%s&' % (search_query, sort_method)
+ base_url = request.path + f'?query={search_query}&sort={sort_method}&'
elif search_query and not cleaned_search_query:
objects_list = Paginator(
models.User.objects.none(),
askbot_settings.USERS_PAGE_SIZE
)
- base_url = request.path + '?query=%s&sort=%s&' % (search_query, sort_method)
+ base_url = request.path + f'?query={search_query}&sort={sort_method}&'
else:
if sort_method == 'newest':
order_by_parameter = '-date_joined'
@@ -855,7 +855,7 @@ def get_type_name(type_id):
if type_id in item:
return item[1]
- class Event(object):
+ class Event:
is_badge = False
def __init__(self, time, type, title, summary, url):
self.time = time
@@ -866,7 +866,7 @@ def __init__(self, time, type, title, summary, url):
slug_title = slugify(title)
self.title_link = url
- class AwardEvent(object):
+ class AwardEvent:
is_badge = True
def __init__(self, time, type, content_object, badge):
self.time = time
@@ -1157,12 +1157,12 @@ def user_reputation(request, user, context):
def format_graph_data(raw_data, user):
# prepare data for the graph - last values go in first
final_rep = user.get_localized_profile().reputation + const.MIN_REPUTATION
- rep_list = ['[%s,%s]' % (calendar.timegm(datetime.datetime.now().timetuple()) * 1000, final_rep)]
+ rep_list = [f'[{calendar.timegm(datetime.datetime.now().timetuple()) * 1000},{final_rep}]']
for rep in raw_data:
- rep_list.append('[%s,%s]' % (calendar.timegm(rep.reputed_at.timetuple()) * 1000, rep.reputation))
+ rep_list.append(f'[{calendar.timegm(rep.reputed_at.timetuple()) * 1000},{rep.reputation}]')
#add initial rep point
- rep_list.append('[%s,%s]' % (calendar.timegm(user.date_joined.timetuple()) * 1000, const.MIN_REPUTATION))
+ rep_list.append(f'[{calendar.timegm(user.date_joined.timetuple()) * 1000},{const.MIN_REPUTATION}]')
reps = ','.join(rep_list)
return '[%s]' % reps
diff --git a/askbot/views/writers.py b/askbot/views/writers.py
index 15cc820f16..ae1718ec60 100644
--- a/askbot/views/writers.py
+++ b/askbot/views/writers.py
@@ -1,4 +1,3 @@
-# encoding:utf-8
"""
:synopsis: views diplaying and processing main content post forms
@@ -144,7 +143,7 @@ def __import_se_data(dump_file):
#run a loop where we'll be reading output of the
#importer tread and yielding it to the caller
- read_stdout = open(fake_stdout.name, 'r')
+ read_stdout = open(fake_stdout.name)
file_pos = 0
fd = read_stdout.fileno()
yield 'Importing your data. This may take a few minutes...
'
@@ -228,7 +227,7 @@ def ask(request):#view used to ask a new question
#group_id = form.cleaned_data.get('group_id', None)
language = form.cleaned_data.get('language', None)
- content = '{}\n\n{}\n\n{}'.format(title, tagnames, text)
+ content = f'{title}\n\n{tagnames}\n\n{text}'
spam_checker_params = spam_checker.get_params_from_request(request)
enabled = askbot_settings.SPAM_FILTER_ENABLED
if enabled and spam_checker.is_spam(content, **spam_checker_params):
diff --git a/ez_setup.py b/ez_setup.py
index f46e986bc6..2313fe8543 100644
--- a/ez_setup.py
+++ b/ez_setup.py
@@ -66,7 +66,7 @@ def _build_egg(egg, archive_filename, to_dir):
# returning the result
log.warn(egg)
if not os.path.exists(egg):
- raise IOError('Could not build the egg.')
+ raise OSError('Could not build the egg.')
class ContextualZipFile(zipfile.ZipFile):
@@ -83,7 +83,7 @@ def __new__(cls, *args, **kwargs):
"""Construct a ZipFile or ContextualZipFile as appropriate."""
if hasattr(zipfile.ZipFile, '__exit__'):
return zipfile.ZipFile(*args, **kwargs)
- return super(ContextualZipFile, cls).__new__(cls)
+ return super().__new__(cls)
@contextlib.contextmanager
@@ -222,8 +222,7 @@ def download_file_powershell(url, target):
ps_cmd = (
"[System.Net.WebRequest]::DefaultWebProxy.Credentials = "
"[System.Net.CredentialCache]::DefaultCredentials; "
- "(new-object System.Net.WebClient).DownloadFile(%(url)r, %(target)r)"
- % vars()
+ "(new-object System.Net.WebClient).DownloadFile({url!r}, {target!r})".format(**vars())
)
cmd = [
'powershell',
diff --git a/pyproject.toml b/pyproject.toml
index 8e2eb05307..a2a43e27b0 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -59,7 +59,7 @@ select = [
# TODO: "SLF", # flake8-self
# TODO: "SLOT", # flake8-slots
# TODO: "TID", # flake8-tidy-imports
- # ** TODO: "UP", # pyupgrade
+ "UP", # pyupgrade
# ** TODO: "Q", # flake8-quotes
# TODO: "TCH", # flake8-type-checking
# TODO: "T10", # flake8-debugger
diff --git a/setup.py b/setup.py
index a829289311..a43957e6b2 100644
--- a/setup.py
+++ b/setup.py
@@ -1,4 +1,3 @@
-from __future__ import print_function
from setuptools import setup, find_packages
import sys
import askbot
diff --git a/testproject/testproject/celery.py b/testproject/testproject/celery.py
index db2a1233fd..a25dcbf051 100644
--- a/testproject/testproject/celery.py
+++ b/testproject/testproject/celery.py
@@ -18,4 +18,4 @@
@app.task(bind=True)
def debug_task(self):
- print('Request: {0!r}'.format(self.request))
+ print(f'Request: {self.request!r}')
diff --git a/testproject/testproject/settings.py b/testproject/testproject/settings.py
index 1d1af72cd6..27eedbeab5 100644
--- a/testproject/testproject/settings.py
+++ b/testproject/testproject/settings.py
@@ -240,7 +240,7 @@
ASKBOT_URL = '' #no leading slash, default = '' empty string
ASKBOT_TRANSLATE_URL = True #translate specific URLs
_ = lambda v:v #fake translation function for the login url
-LOGIN_URL = '/%s%s%s' % (ASKBOT_URL, _('account/'), _('signin/'))
+LOGIN_URL = '/{}{}{}'.format(ASKBOT_URL, _('account/'), _('signin/'))
LOGIN_REDIRECT_URL = ASKBOT_URL #adjust, if needed
#note - it is important that upload dir url is NOT translated!!!
#also, this url must not have the leading slash
@@ -343,7 +343,7 @@
message_level.ERROR: 'notification_error',
}
-class DisableMigrations(object):
+class DisableMigrations:
def __contains__(self, item):
return True