diff --git a/devel/fields.py b/devel/fields.py index 289862fc..9bd64879 100644 --- a/devel/fields.py +++ b/devel/fields.py @@ -4,14 +4,14 @@ class PGPKeyField(models.CharField): def __init__(self, *args, **kwargs): - super(PGPKeyField, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.validators.append( RegexValidator(r'^[0-9A-F]{40}$', "Ensure this value consists of 40 hex characters.", 'hex_char')) def to_python(self, value): if value == '' or value is None: return None - value = super(PGPKeyField, self).to_python(value) + value = super().to_python(value) # remove all spaces value = value.replace(' ', '') # prune prefixes, either 0x or 2048R/ type diff --git a/devel/forms.py b/devel/forms.py index 060b2f2c..99e2fbc3 100644 --- a/devel/forms.py +++ b/devel/forms.py @@ -60,7 +60,7 @@ class Meta: exclude = ('picture', 'user') def __init__(self, *args, **kwargs): - super(NewUserForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) # Hack ourself so certain fields appear first old = self.fields self.fields = OrderedDict() @@ -79,7 +79,7 @@ def clean_username(self): return username def save(self, commit=True): - profile = super(NewUserForm, self).save(commit=False) + profile = super().save(commit=False) pwletters = ascii_letters + digits password = ''.join([random.choice(pwletters) for _ in range(8)]) user = User.objects.create_user( diff --git a/feeds.py b/feeds.py index d6fe1f7a..dff07836 100644 --- a/feeds.py +++ b/feeds.py @@ -43,7 +43,7 @@ def write(self, outfile, encoding): '>' closing tags and over 1600 write calls in our package feed. ''' wrapper = BatchWritesWrapper(outfile) - super(FasterRssFeed, self).write(wrapper, encoding) + super().write(wrapper, encoding) wrapper.flush() @@ -61,7 +61,7 @@ class PackageFeed(Feed): def __call__(self, request, *args, **kwargs): wrapper = condition(last_modified_func=package_last_modified) - return wrapper(super(PackageFeed, self).__call__)(request, *args, **kwargs) + return wrapper(super().__call__)(request, *args, **kwargs) __name__ = 'package_feed' @@ -183,7 +183,7 @@ class PackageUpdatesFeed(Feed): def __call__(self, request, *args, **kwargs): wrapper = condition(last_modified_func=removal_last_modified) - return wrapper(super(PackageUpdatesFeed, self).__call__)(request, *args, **kwargs) + return wrapper(super().__call__)(request, *args, **kwargs) __name__ = 'packages_updates_feed' @@ -318,7 +318,7 @@ class NewsFeed(Feed): def __call__(self, request, *args, **kwargs): wrapper = condition(last_modified_func=news_last_modified) - return wrapper(super(NewsFeed, self).__call__)(request, *args, **kwargs) + return wrapper(super().__call__)(request, *args, **kwargs) __name__ = 'news_feed' @@ -405,7 +405,7 @@ class PlanetFeed(Feed): def __call__(self, request, *args, **kwargs): wrapper = condition(last_modified_func=planet_last_modified) - return wrapper(super(PlanetFeed, self).__call__)(request, *args, **kwargs) + return wrapper(super().__call__)(request, *args, **kwargs) __name__ = 'planet_feed' diff --git a/main/log.py b/main/log.py index bb756b67..de6b0037 100644 --- a/main/log.py +++ b/main/log.py @@ -12,14 +12,14 @@ def __init__(self, *args, **kwargs): self.size_limit = None if self.size_limit and self.size_limit < 0: raise Exception('Invalid size specified') - super(LimitedSizeDict, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) self.check_item_limits() def __setitem__(self, key, value): # delete and add to ensure it ends up at the end of the linked list if key in self: - super(LimitedSizeDict, self).__delitem__(key) - super(LimitedSizeDict, self).__setitem__(key, value) + super().__delitem__(key) + super().__setitem__(key, value) self.check_item_limits() def check_item_limits(self): diff --git a/main/management/commands/donor_import.py b/main/management/commands/donor_import.py index 18a9c059..a48725a1 100644 --- a/main/management/commands/donor_import.py +++ b/main/management/commands/donor_import.py @@ -18,7 +18,6 @@ import email import logging import sys -from argparse import FileType from email.header import decode_header from django.core.management.base import BaseCommand, CommandError @@ -33,7 +32,7 @@ class Command(BaseCommand): def add_arguments(self, parser): - parser.add_argument('input', nargs='?', type=FileType('r'), default=sys.stdin) + parser.add_argument('input', nargs='?', default=None, help='Input file (default: stdin)') def decode_subject(self, subject): subject = decode_header(subject) @@ -78,7 +77,12 @@ def handle(self, *args, **options): elif v >= 2: logger.level = logging.DEBUG - msg = email.message_from_file(options['input']) + input_path = options['input'] + if input_path is not None: + with open(input_path, 'r') as f: + msg = email.message_from_file(f) + else: + msg = email.message_from_file(sys.stdin) if not msg['subject']: raise CommandError("Failed to read from STDIN") subject = msg.get('subject', '') diff --git a/main/models.py b/main/models.py index 86801e0e..eb4c59a1 100644 --- a/main/models.py +++ b/main/models.py @@ -122,7 +122,7 @@ def __str__(self): @property def full_version(self): if self.epoch > 0: - return '%d:%s-%s' % (self.epoch, self.pkgver, self.pkgrel) + return f'{self.epoch}:{self.pkgver}-{self.pkgrel}' return f'{self.pkgver}-{self.pkgrel}' def get_absolute_url(self): diff --git a/main/storage.py b/main/storage.py index a1f92cb5..d4abae75 100644 --- a/main/storage.py +++ b/main/storage.py @@ -16,8 +16,7 @@ class MinifiedStaticFilesStorage(ManifestStaticFilesStorage): ) def post_process(self, paths, dry_run=False, **options): - for original_path, processed_path, processed in super( - MinifiedStaticFilesStorage, self).post_process( + for original_path, processed_path, processed in super().post_process( paths, dry_run, **options): for ext, func in self.minifiers: if '.min' in original_path: diff --git a/main/tests/test_donor_import.py b/main/tests/test_donor_import.py index 17e52f64..151a972a 100644 --- a/main/tests/test_donor_import.py +++ b/main/tests/test_donor_import.py @@ -42,9 +42,9 @@ def test_invalid_args(monkeypatch): def test_invalid_path(): - with pytest.raises(CommandError) as e: + with pytest.raises(FileNotFoundError) as e: call_command('donor_import', '/tmp/non-existant') - assert 'argument input: can\'t open' in str(e.value) + assert 'No such file or directory' in str(e.value) def test_maildir(db, monkeypatch): diff --git a/mirrors/fields.py b/mirrors/fields.py index cb1c3893..118b7686 100644 --- a/mirrors/fields.py +++ b/mirrors/fields.py @@ -21,7 +21,7 @@ class IPNetworkField(models.Field): def __init__(self, *args, **kwargs): kwargs['max_length'] = 44 - super(IPNetworkField, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) def get_internal_type(self): return "IPAddressField" @@ -40,7 +40,7 @@ def get_prep_value(self, value): def formfield(self, **kwargs): defaults = {'form_class': IPNetworkFormField} defaults.update(kwargs) - return super(IPNetworkField, self).formfield(**defaults) + return super().formfield(**defaults) def from_db_value(self, value, expression, connection): return self.to_python(value) diff --git a/mirrors/views/api.py b/mirrors/views/api.py index 900c72b4..b0a81b71 100644 --- a/mirrors/views/api.py +++ b/mirrors/views/api.py @@ -33,7 +33,7 @@ def default(self, obj): return data if isinstance(obj, MirrorProtocol): return str(obj) - return super(MirrorStatusJSONEncoder, self).default(obj) + return super().default(obj) class ExtendedMirrorStatusJSONEncoder(MirrorStatusJSONEncoder): @@ -43,7 +43,7 @@ class ExtendedMirrorStatusJSONEncoder(MirrorStatusJSONEncoder): def default(self, obj): if isinstance(obj, MirrorUrl): - data = super(ExtendedMirrorStatusJSONEncoder, self).default(obj) + data = super().default(obj) cutoff = now() - DEFAULT_CUTOFF data['logs'] = list(obj.logs.filter( check_time__gte=cutoff).order_by('check_time')) @@ -52,7 +52,7 @@ def default(self, obj): data = {attr: getattr(obj, attr) for attr in self.log_attributes} data['error'] = obj.error or None return data - return super(ExtendedMirrorStatusJSONEncoder, self).default(obj) + return super().default(obj) class LocationJSONEncoder(DjangoJSONEncoder): @@ -68,7 +68,7 @@ def default(self, obj): 'country_code': obj.country.code, 'ip_version': obj.ip_version, } - return super(LocationJSONEncoder, self).default(obj) + return super().default(obj) @cache_control(max_age=311) diff --git a/mirrors/views/mirrorlist.py b/mirrors/views/mirrorlist.py index 92b4241a..1fb4e48b 100644 --- a/mirrors/views/mirrorlist.py +++ b/mirrors/views/mirrorlist.py @@ -21,7 +21,7 @@ class MirrorlistForm(forms.Form): use_mirror_status = forms.BooleanField(required=False) def __init__(self, *args, **kwargs): - super(MirrorlistForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) fields = self.fields fields['country'].choices = [('all', 'All'), *self.get_countries()] fields['country'].initial = ['all'] diff --git a/news/views.py b/news/views.py index 33ad1aa5..a8009427 100644 --- a/news/views.py +++ b/news/views.py @@ -62,7 +62,7 @@ def form_valid(self, form): from_email=from_, to=[settings.ANNOUNCE_EMAIL], headers=headers).send() - return super(NewsCreateView, self).form_valid(form) + return super().form_valid(form) class NewsEditView(UpdateView): diff --git a/packages/admin.py b/packages/admin.py index dee0140f..8a4ad6b7 100644 --- a/packages/admin.py +++ b/packages/admin.py @@ -33,7 +33,7 @@ class FlagRequestAdmin(admin.ModelAdmin): ordering = ('-created',) def get_queryset(self, request): - qs = super(FlagRequestAdmin, self).get_queryset(request) + qs = super().get_queryset(request) return qs.select_related('repo', 'user') @@ -53,7 +53,7 @@ class SignoffSpecificationAdmin(admin.ModelAdmin): ordering = ('-created',) def get_queryset(self, request): - qs = super(SignoffSpecificationAdmin, self).get_queryset(request) + qs = super().get_queryset(request) return qs.select_related('arch', 'repo', 'user') diff --git a/packages/models.py b/packages/models.py index cd3c0801..61d70b3d 100644 --- a/packages/models.py +++ b/packages/models.py @@ -227,8 +227,8 @@ def __str__(self): class FlagDenylist(models.Model): keyword = models.CharField(max_length=255) - def __str__(self): - return f"{self.keyword}" + def __str__(self) -> str: + return str(self.keyword) class UpdateManager(models.Manager): @@ -477,7 +477,7 @@ class Depend(RelatedToBase): def __str__(self): '''For depends, we may also have a description and a modifier.''' - to_str = super(Depend, self).__str__() + to_str = super().__str__() if self.description: return f'{to_str}: {self.description}' return to_str diff --git a/packages/templatetags/package_extras.py b/packages/templatetags/package_extras.py index be8f3bf6..15481125 100644 --- a/packages/templatetags/package_extras.py +++ b/packages/templatetags/package_extras.py @@ -9,7 +9,7 @@ class BuildQueryStringNode(template.Node): def __init__(self, sortfield): self.sortfield = sortfield - super(BuildQueryStringNode, self).__init__() + super().__init__() def render(self, context): qs = parse_qs(context['current_query']) diff --git a/packages/utils.py b/packages/utils.py index e56deb9d..43a96cfb 100644 --- a/packages/utils.py +++ b/packages/utils.py @@ -466,6 +466,6 @@ def default(self, obj): for attr in self.todolistpackage_attributes: data[attr] = getattr(obj, attr) return data - return super(PackageJSONEncoder, self).default(obj) + return super().default(obj) # vim: set ts=4 sw=4 et: diff --git a/packages/views/flag.py b/packages/views/flag.py index 67b2c27d..a5cdf67e 100644 --- a/packages/views/flag.py +++ b/packages/views/flag.py @@ -29,7 +29,7 @@ def __init__(self, *args, **kwargs): # we remove the 'email' field if this form is being shown to a # logged-in user, e.g., a developer. auth = kwargs.pop('authenticated', False) - super(FlagForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) if auth: del self.fields['email'] diff --git a/packages/views/search.py b/packages/views/search.py index a795ecc0..b9d383d2 100644 --- a/packages/views/search.py +++ b/packages/views/search.py @@ -28,7 +28,7 @@ class GroupSearchForm(forms.Form): def __init__(self, *args, **kwargs): show_staging = kwargs.pop('show_staging', False) - super(GroupSearchForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) repos = Repo.objects.all() @@ -59,7 +59,7 @@ class PackageSearchForm(forms.Form): def __init__(self, *args, **kwargs): show_staging = kwargs.pop('show_staging', False) - super(PackageSearchForm, self).__init__(*args, **kwargs) + super().__init__(*args, **kwargs) repos = Repo.objects.all() if not show_staging: repos = repos.filter(staging=False) @@ -153,7 +153,7 @@ def get(self, request, *args, **kwargs): return empty_response() self.form = PackageSearchForm(data=request.GET, show_staging=self.request.user.is_authenticated) - return super(SearchListView, self).get(request, *args, **kwargs) + return super().get(request, *args, **kwargs) def get_queryset(self): packages = Package.objects.normal() @@ -170,7 +170,7 @@ def get_queryset(self): return Package.objects.none() def get_context_data(self, **kwargs): - context = super(SearchListView, self).get_context_data(**kwargs) + context = super().get_context_data(**kwargs) query_params = self.request.GET.copy() query_params.pop('page', None) context['current_query'] = query_params.urlencode() diff --git a/packages/views/signoff.py b/packages/views/signoff.py index 3634a71d..7a05e699 100644 --- a/packages/views/signoff.py +++ b/packages/views/signoff.py @@ -198,7 +198,7 @@ def default(self, obj): return obj.username elif isinstance(obj, set): return list(obj) - return super(SignoffJSONEncoder, self).default(obj) + return super().default(obj) @permission_required('packages.change_signoff') diff --git a/pyproject.toml b/pyproject.toml index 8430515c..ef628ddb 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -69,6 +69,7 @@ select = [ "T10", # flake8-debugger "TCH", # flake8-type-checking "UP032", # f-string + "UP008", # super-call-with-parameters "W", # warnings (mostly whitespace) "YTT", # flake8-2020 ] diff --git a/releng/views.py b/releng/views.py index 2f7b933f..04849246 100644 --- a/releng/views.py +++ b/releng/views.py @@ -56,7 +56,7 @@ def default(self, obj): torrent_data.pop('url_list', None) data['torrent'] = torrent_data return data - return super(ReleaseJSONEncoder, self).default(obj) + return super().default(obj) def releases_json(request): diff --git a/sitemaps.py b/sitemaps.py index 9546a9e1..7039d807 100644 --- a/sitemaps.py +++ b/sitemaps.py @@ -81,7 +81,7 @@ def get_latest_lastmod(self): return None def location(self, obj): - return f"/packages/{obj['repo'].name.lower()}/{obj['arch']}/obj['pkgbase']/" + return f"/packages/{obj['repo'].name.lower()}/{obj['arch']}/{obj['pkgbase']}/" class NewsSitemap(Sitemap): @@ -116,7 +116,7 @@ class RecentNewsSitemap(NewsSitemap): def items(self): now = datetime.now(timezone.utc) cutoff = now - timedelta(days=30) - return super(RecentNewsSitemap, self).items().filter(postdate__gte=cutoff) + return super().items().filter(postdate__gte=cutoff) class ReleasesSitemap(Sitemap): diff --git a/todolists/views.py b/todolists/views.py index 84f4785b..f0401354 100644 --- a/todolists/views.py +++ b/todolists/views.py @@ -241,7 +241,7 @@ def default(self, obj): 'kind': obj.kind_str } - return super(TodoListJSONEncoder, self).default(obj) + return super().default(obj) def view_json(request, slug): diff --git a/urls.py b/urls.py index 7b36b0ca..58d7dc3b 100644 --- a/urls.py +++ b/urls.py @@ -115,7 +115,7 @@ ]) # prometheus metrics -if settings.PROMETHEUS_METRICS: # pragma :no cover +if settings.PROMETHEUS_METRICS: # pragma: no cover urlpatterns.extend([ path('', include('django_prometheus.urls')), ])