diff --git a/.github/workflows/style.yml b/.github/workflows/style.yml index 9282bb59a..f2261aebd 100644 --- a/.github/workflows/style.yml +++ b/.github/workflows/style.yml @@ -31,7 +31,7 @@ jobs: - name: Install Dependencies run: pip3 install --no-use-pep517 -Ur src/requirements/dev.txt - name: Run isort - run: isort -c -rc -df . + run: isort -c . working-directory: ./src flake: name: flake8 diff --git a/doc/development/contribution/style.rst b/doc/development/contribution/style.rst index cfdf33436..995bff770 100644 --- a/doc/development/contribution/style.rst +++ b/doc/development/contribution/style.rst @@ -7,7 +7,7 @@ Coding style and quality for more information. Use four spaces for indentation. * We sort our imports by a certain schema, but you don't have to do this by hand. Again, ``setup.cfg`` contains - some definitions that allow the command ``isort -rc `` to automatically sort the imports in your source + some definitions that allow the command ``isort `` to automatically sort the imports in your source files. * For templates and models, please take a look at the `Django Coding Style`_. We like Django's `class-based views`_ and diff --git a/doc/development/setup.rst b/doc/development/setup.rst index 4a1a0715e..d00d97f8d 100644 --- a/doc/development/setup.rst +++ b/doc/development/setup.rst @@ -98,7 +98,7 @@ pull request nevertheless and ask us for help, we are happy to assist you. Execute the following commands to check for code style errors:: flake8 . - isort -c -rc . + isort -c . python manage.py check Execute the following command to run pretix' test suite (might take a couple of minutes):: @@ -121,7 +121,7 @@ for example, to check for any errors in any staged files when committing:: do echo $file git show ":$file" | flake8 - --stdin-display-name="$file" || exit 1 # we only want to lint the staged changes, not any un-staged changes - git show ":$file" | isort -df --check-only - | grep ERROR && exit 1 || true + git show ":$file" | isort -c - | grep ERROR && exit 1 || true done diff --git a/src/pretix/base/i18n.py b/src/pretix/base/i18n.py index 366abd0b5..bd737e34d 100644 --- a/src/pretix/base/i18n.py +++ b/src/pretix/base/i18n.py @@ -4,6 +4,9 @@ from django.conf import settings from django.utils import translation from django.utils.formats import date_format, number_format from django.utils.translation import gettext + +from pretix.base.templatetags.money import money_filter + from i18nfield.fields import ( # noqa I18nCharField, I18nTextarea, I18nTextField, I18nTextInput, ) @@ -12,8 +15,6 @@ from i18nfield.forms import I18nFormField # noqa from i18nfield.strings import LazyI18nString # noqa from i18nfield.utils import I18nJSONEncoder # noqa -from pretix.base.templatetags.money import money_filter - class LazyDate: def __init__(self, value): diff --git a/src/pretix/base/migrations/0159_mails_by_sales_channel.py b/src/pretix/base/migrations/0159_mails_by_sales_channel.py index efab29c1b..2c18e7c1b 100644 --- a/src/pretix/base/migrations/0159_mails_by_sales_channel.py +++ b/src/pretix/base/migrations/0159_mails_by_sales_channel.py @@ -4,6 +4,7 @@ from django.db import migrations from pretix.base.channels import get_all_sales_channels + def set_sales_channels(apps, schema_editor): # We now allow restricting some mails to certain sales channels # The default is changing from all channels to "web" only diff --git a/src/pretix/base/models/auth.py b/src/pretix/base/models/auth.py index e4d754cc9..f18cc651e 100644 --- a/src/pretix/base/models/auth.py +++ b/src/pretix/base/models/auth.py @@ -173,7 +173,7 @@ class User(AbstractBaseUser, PermissionsMixin, LoggingMixin): return self.email def send_security_notice(self, messages, email=None): - from pretix.base.services.mail import mail, SendMailException + from pretix.base.services.mail import SendMailException, mail try: with language(self.locale): diff --git a/src/pretix/base/models/base.py b/src/pretix/base/models/base.py index d679ac063..f7205e273 100644 --- a/src/pretix/base/models/base.py +++ b/src/pretix/base/models/base.py @@ -48,14 +48,15 @@ class LoggingMixin: :param data: Any JSON-serializable object :param user: The user performing the action (optional) """ - from .log import LogEntry - from .event import Event - from .devices import Device from pretix.api.models import OAuthAccessToken, OAuthApplication - from .organizer import TeamAPIToken + from pretix.api.webhooks import get_all_webhook_events, notify_webhooks + from ..notifications import get_all_notification_types from ..services.notifications import notify - from pretix.api.webhooks import get_all_webhook_events, notify_webhooks + from .devices import Device + from .event import Event + from .log import LogEntry + from .organizer import TeamAPIToken event = None if isinstance(self, Event): diff --git a/src/pretix/base/models/checkin.py b/src/pretix/base/models/checkin.py index 18fed1c62..1ef71be92 100644 --- a/src/pretix/base/models/checkin.py +++ b/src/pretix/base/models/checkin.py @@ -48,7 +48,7 @@ class CheckinList(LoggedModel): @property def positions(self): - from . import OrderPosition, Order + from . import Order, OrderPosition qs = OrderPosition.objects.filter( order__event=self.event, diff --git a/src/pretix/base/models/event.py b/src/pretix/base/models/event.py index 52453652b..f76adbcd7 100644 --- a/src/pretix/base/models/event.py +++ b/src/pretix/base/models/event.py @@ -415,7 +415,7 @@ class Event(EventMixin, LoggedModel): return super().presale_has_ended def delete_all_orders(self, really=False): - from .orders import OrderRefund, OrderPayment, OrderPosition, OrderFee + from .orders import OrderFee, OrderPayment, OrderPosition, OrderRefund if not really: raise TypeError("Pass really=True as a parameter.") @@ -502,8 +502,10 @@ class Event(EventMixin, LoggedModel): ), tz) def copy_data_from(self, other): - from . import ItemAddOn, ItemCategory, Item, Question, Quota, ItemMetaValue from ..signals import event_copy_data + from . import ( + Item, ItemAddOn, ItemCategory, ItemMetaValue, Question, Quota, + ) self.plugins = other.plugins self.is_public = other.is_public @@ -1183,8 +1185,8 @@ class RequiredAction(models.Model): created = not self.pk super().save(*args, **kwargs) if created: - from .log import LogEntry from ..services.notifications import notify + from .log import LogEntry logentry = LogEntry.objects.create( content_object=self, diff --git a/src/pretix/base/models/log.py b/src/pretix/base/models/log.py index bba31273f..b37c6fa95 100644 --- a/src/pretix/base/models/log.py +++ b/src/pretix/base/models/log.py @@ -75,7 +75,10 @@ class LogEntry(models.Model): @cached_property def display_object(self): - from . import Order, Voucher, Quota, Item, ItemCategory, Question, Event, TaxRule, SubEvent + from . import ( + Event, Item, ItemCategory, Order, Question, Quota, SubEvent, + TaxRule, Voucher, + ) try: if self.content_type.model_class() is Event: diff --git a/src/pretix/base/models/orders.py b/src/pretix/base/models/orders.py index 8d64eac1d..44f044e39 100644 --- a/src/pretix/base/models/orders.py +++ b/src/pretix/base/models/orders.py @@ -209,7 +209,7 @@ class Order(LockModel, LoggedModel): return self.full_code def gracefully_delete(self, user=None, auth=None): - from . import Voucher, GiftCard, GiftCardTransaction + from . import GiftCard, GiftCardTransaction, Voucher if not self.testmode: raise TypeError("Only test mode orders can be deleted.") @@ -838,7 +838,9 @@ class Order(LockModel, LoggedModel): only be attached for this position and child positions, the link will only point to the position and the attendee email will be used if available. """ - from pretix.base.services.mail import SendMailException, mail, render_mail, TolerantDict + from pretix.base.services.mail import ( + SendMailException, TolerantDict, mail, render_mail, + ) if not self.email: return @@ -1421,7 +1423,9 @@ class OrderPayment(models.Model): :type mail_text: str :raises Quota.QuotaExceededException: if the quota is exceeded and ``force`` is ``False`` """ - from pretix.base.services.invoices import generate_invoice, invoice_qualified + from pretix.base.services.invoices import ( + generate_invoice, invoice_qualified, + ) with transaction.atomic(): locked_instance = OrderPayment.objects.select_for_update().get(pk=self.pk) @@ -2066,7 +2070,9 @@ class OrderPosition(AbstractPosition): :param sender: Custom email sender. :param attach_tickets: Attach tickets of this order, if they are existing and ready to download """ - from pretix.base.services.mail import SendMailException, mail, render_mail + from pretix.base.services.mail import ( + SendMailException, mail, render_mail, + ) if not self.attendee_email: return diff --git a/src/pretix/base/models/organizer.py b/src/pretix/base/models/organizer.py index beb12e7a2..58631fa7b 100644 --- a/src/pretix/base/models/organizer.py +++ b/src/pretix/base/models/organizer.py @@ -113,7 +113,7 @@ class Organizer(LoggedModel): ), tz) def allow_delete(self): - from . import Order, Invoice + from . import Invoice, Order return ( not Order.objects.filter(event__organizer=self).exists() and not Invoice.objects.filter(event__organizer=self).exists() and diff --git a/src/pretix/base/models/seating.py b/src/pretix/base/models/seating.py index 351d67fdf..a494796e3 100644 --- a/src/pretix/base/models/seating.py +++ b/src/pretix/base/models/seating.py @@ -163,7 +163,7 @@ class Seat(models.Model): @classmethod def annotated(cls, qs, event_id, subevent, ignore_voucher_id=None, minimal_distance=0, ignore_order_id=None, ignore_cart_id=None, distance_only_within_row=False): - from . import Order, OrderPosition, Voucher, CartPosition + from . import CartPosition, Order, OrderPosition, Voucher vqs = Voucher.objects.filter( event_id=event_id, diff --git a/src/pretix/base/pdf.py b/src/pretix/base/pdf.py index 177701dca..d4813fee1 100644 --- a/src/pretix/base/pdf.py +++ b/src/pretix/base/pdf.py @@ -544,7 +544,7 @@ class Renderer: with open(os.path.join(d, 'out.pdf'), 'rb') as f: return BytesIO(f.read()) else: - from PyPDF2 import PdfFileWriter, PdfFileReader + from PyPDF2 import PdfFileReader, PdfFileWriter buffer.seek(0) new_pdf = PdfFileReader(buffer) output = PdfFileWriter() diff --git a/src/pretix/control/forms/__init__.py b/src/pretix/control/forms/__init__.py index 396944fb1..6bfef9e8b 100644 --- a/src/pretix/control/forms/__init__.py +++ b/src/pretix/control/forms/__init__.py @@ -10,6 +10,7 @@ from django.forms.utils import from_current_timezone from django.utils.translation import gettext_lazy as _ from ...base.forms import I18nModelForm + # Import for backwards compatibility with okd import paths from ...base.forms.widgets import ( # noqa DatePickerWidget, SplitDateTimePickerWidget, TimePickerWidget, diff --git a/src/pretix/control/forms/event.py b/src/pretix/control/forms/event.py index 1861ef1c0..e60aa51ba 100644 --- a/src/pretix/control/forms/event.py +++ b/src/pretix/control/forms/event.py @@ -1,3 +1,5 @@ +from urllib.parse import urlencode, urlparse + from django import forms from django.conf import settings from django.core.exceptions import ValidationError @@ -15,7 +17,6 @@ from i18nfield.forms import ( I18nForm, I18nFormField, I18nFormSetMixin, I18nTextarea, I18nTextInput, ) from pytz import common_timezones, timezone -from urllib.parse import urlencode, urlparse from pretix.base.channels import get_all_sales_channels from pretix.base.email import get_available_placeholders diff --git a/src/pretix/multidomain/urlreverse.py b/src/pretix/multidomain/urlreverse.py index 707cfdaed..43ae4548d 100644 --- a/src/pretix/multidomain/urlreverse.py +++ b/src/pretix/multidomain/urlreverse.py @@ -91,7 +91,9 @@ def eventreverse(obj, name, kwargs=None): needed. :returns: An absolute URL (including scheme and host) as a string """ - from pretix.multidomain import event_domain_urlconf, organizer_domain_urlconf, maindomain_urlconf + from pretix.multidomain import ( + event_domain_urlconf, maindomain_urlconf, organizer_domain_urlconf, + ) c = None if not kwargs: diff --git a/src/pretix/plugins/badges/exporters.py b/src/pretix/plugins/badges/exporters.py index eda15a118..1c5f4e4bf 100644 --- a/src/pretix/plugins/badges/exporters.py +++ b/src/pretix/plugins/badges/exporters.py @@ -121,7 +121,7 @@ OPTIONS = OrderedDict([ def render_pdf(event, positions, opt): - from PyPDF2 import PdfFileWriter, PdfFileReader + from PyPDF2 import PdfFileReader, PdfFileWriter Renderer._register_fonts() renderermap = { diff --git a/src/pretix/plugins/banktransfer/mt940import.py b/src/pretix/plugins/banktransfer/mt940import.py index 56b04130a..a60440e9b 100644 --- a/src/pretix/plugins/banktransfer/mt940import.py +++ b/src/pretix/plugins/banktransfer/mt940import.py @@ -5,7 +5,6 @@ import mt940 from pretix.base.decimal import round_decimal - """ The parse_transaction_details and join_reference functions are Copyright (c) 2017 Nicole Klünder diff --git a/src/pretix/plugins/reports/exporters.py b/src/pretix/plugins/reports/exporters.py index 388a01f67..9a051677b 100644 --- a/src/pretix/plugins/reports/exporters.py +++ b/src/pretix/plugins/reports/exporters.py @@ -43,8 +43,8 @@ class ReportlabExportMixin: @staticmethod def register_fonts(): - from reportlab.pdfbase.ttfonts import TTFont from reportlab.pdfbase import pdfmetrics + from reportlab.pdfbase.ttfonts import TTFont pdfmetrics.registerFont(TTFont('OpenSans', finders.find('fonts/OpenSans-Regular.ttf'))) pdfmetrics.registerFont(TTFont('OpenSansIt', finders.find('fonts/OpenSans-Italic.ttf'))) @@ -56,8 +56,8 @@ class ReportlabExportMixin: return BaseDocTemplate def create(self, form_data): - from reportlab.platypus import PageTemplate from reportlab.lib.units import mm + from reportlab.platypus import PageTemplate with tempfile.NamedTemporaryFile(suffix=".pdf") as f: Report.register_fonts() @@ -162,8 +162,8 @@ class OverviewReport(Report): return pagesizes.landscape(pagesizes.A4) def get_story(self, doc, form_data): - from reportlab.platypus import Paragraph, Spacer, TableStyle, Table from reportlab.lib.units import mm + from reportlab.platypus import Paragraph, Spacer, Table, TableStyle if form_data.get('date_from'): form_data['date_from'] = parse(form_data['date_from']) @@ -334,8 +334,8 @@ class OrderTaxListReportPDF(Report): return pagesizes.landscape(pagesizes.A4) def get_story(self, doc, form_data): - from reportlab.platypus import Paragraph, Spacer, TableStyle, Table from reportlab.lib.units import mm + from reportlab.platypus import Paragraph, Spacer, Table, TableStyle headlinestyle = self.get_style() headlinestyle.fontSize = 15 diff --git a/src/pretix/plugins/stripe/signals.py b/src/pretix/plugins/stripe/signals.py index b4a94b98f..ddccc9205 100644 --- a/src/pretix/plugins/stripe/signals.py +++ b/src/pretix/plugins/stripe/signals.py @@ -21,8 +21,9 @@ from pretix.presale.signals import html_head @receiver(register_payment_providers, dispatch_uid="payment_stripe") def register_payment_provider(sender, **kwargs): from .payment import ( - StripeSettingsHolder, StripeCC, StripeGiropay, StripeIdeal, StripeAlipay, StripeBancontact, - StripeSofort, StripeEPS, StripeMultibanco, StripePrzelewy24, StripeWeChatPay + StripeAlipay, StripeBancontact, StripeCC, StripeEPS, StripeGiropay, + StripeIdeal, StripeMultibanco, StripePrzelewy24, StripeSettingsHolder, + StripeSofort, StripeWeChatPay, ) return [ diff --git a/src/pretix/plugins/ticketoutputpdf/ticketoutput.py b/src/pretix/plugins/ticketoutputpdf/ticketoutput.py index 91f1d3c43..7a243e510 100644 --- a/src/pretix/plugins/ticketoutputpdf/ticketoutput.py +++ b/src/pretix/plugins/ticketoutputpdf/ticketoutput.py @@ -116,8 +116,8 @@ class PdfTicketOutput(BaseTicketOutput): return 'order%s%s.pdf' % (self.event.slug, order.code), 'application/pdf', outbuffer.read() def _create_canvas(self, buffer): - from reportlab.pdfgen import canvas from reportlab.lib import pagesizes + from reportlab.pdfgen import canvas # Doesn't matter as we'll overpaint it over a background later pagesize = pagesizes.A4 diff --git a/src/setup.cfg b/src/setup.cfg index a112b0408..00dc9a4f1 100644 --- a/src/setup.cfg +++ b/src/setup.cfg @@ -8,9 +8,11 @@ max-complexity = 11 combine_as_imports = true include_trailing_comma = true known_first_party = pretix -known_third_party = versions +known_third_party = versions,tests extra_standard_library = typing,enum,mimetypes multi_line_output = 5 +line_length = 79 +honor_noqa = true skip = make_testdata.py,wsgi.py,bootstrap,celery_app.py,pretix/settings.py,tests/settings.py,pretix/testutils/settings.py [tool:pytest] diff --git a/src/tests/testdummy/signals.py b/src/tests/testdummy/signals.py index 838818e96..559998d20 100644 --- a/src/tests/testdummy/signals.py +++ b/src/tests/testdummy/signals.py @@ -15,7 +15,10 @@ def register_ticket_outputs(sender, **kwargs): @receiver(register_payment_providers, dispatch_uid="payment_dummy") def register_payment_provider(sender, **kwargs): - from .payment import DummyPaymentProvider, DummyFullRefundablePaymentProvider, DummyPartialRefundablePaymentProvider + from .payment import ( + DummyFullRefundablePaymentProvider, + DummyPartialRefundablePaymentProvider, DummyPaymentProvider, + ) return [DummyPaymentProvider, DummyFullRefundablePaymentProvider, DummyPartialRefundablePaymentProvider]