Import large package lazily to speed up startup (#5636)

* Import large package lazily to speed up startup

* Make all jsonschema imports lazy
This commit is contained in:
Raphael Michel
2025-12-09 09:52:53 +01:00
committed by GitHub
parent f214edaf34
commit b895d9bbca
10 changed files with 41 additions and 11 deletions

View File

@@ -53,7 +53,6 @@ from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _ from django.utils.translation import gettext_lazy as _
from django_otp.models import Device from django_otp.models import Device
from django_scopes import scopes_disabled from django_scopes import scopes_disabled
from webauthn.helpers.structs import PublicKeyCredentialDescriptor
from pretix.base.i18n import language from pretix.base.i18n import language
from pretix.helpers.urls import build_absolute_uri from pretix.helpers.urls import build_absolute_uri
@@ -708,6 +707,8 @@ class U2FDevice(Device):
@property @property
def webauthndevice(self): def webauthndevice(self):
from webauthn.helpers.structs import PublicKeyCredentialDescriptor
d = json.loads(self.json_data) d = json.loads(self.json_data)
return PublicKeyCredentialDescriptor(websafe_decode(d['keyHandle'])) return PublicKeyCredentialDescriptor(websafe_decode(d['keyHandle']))
@@ -737,6 +738,8 @@ class WebAuthnDevice(Device):
@property @property
def webauthndevice(self): def webauthndevice(self):
from webauthn.helpers.structs import PublicKeyCredentialDescriptor
return PublicKeyCredentialDescriptor(websafe_decode(self.credential_id)) return PublicKeyCredentialDescriptor(websafe_decode(self.credential_id))
@property @property

View File

@@ -22,7 +22,6 @@
import json import json
from collections import namedtuple from collections import namedtuple
import jsonschema
from django.contrib.staticfiles import finders from django.contrib.staticfiles import finders
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.db import models from django.db import models
@@ -38,6 +37,8 @@ from pretix.base.models import Event, Item, LoggedModel, Organizer, SubEvent
@deconstructible @deconstructible
class SeatingPlanLayoutValidator: class SeatingPlanLayoutValidator:
def __call__(self, value): def __call__(self, value):
import jsonschema
if not isinstance(value, dict): if not isinstance(value, dict):
try: try:
val = json.loads(value) val = json.loads(value)

View File

@@ -23,7 +23,6 @@ import json
from decimal import Decimal from decimal import Decimal
from typing import Optional from typing import Optional
import jsonschema
from django.contrib.staticfiles import finders from django.contrib.staticfiles import finders
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.core.validators import MaxValueValidator, MinValueValidator from django.core.validators import MaxValueValidator, MinValueValidator
@@ -298,6 +297,8 @@ def cc_to_vat_prefix(country_code):
@deconstructible @deconstructible
class CustomRulesValidator: class CustomRulesValidator:
def __call__(self, value): def __call__(self, value):
import jsonschema
if not isinstance(value, dict): if not isinstance(value, dict):
try: try:
val = json.loads(value) val = json.loads(value)

View File

@@ -47,7 +47,6 @@ from collections import OrderedDict, defaultdict
from functools import partial from functools import partial
from io import BytesIO from io import BytesIO
import jsonschema
import pypdf import pypdf
import pypdf.generic import pypdf.generic
import reportlab.rl_config import reportlab.rl_config
@@ -1311,6 +1310,8 @@ def _correct_page_media_box(page: pypdf.PageObject):
@deconstructible @deconstructible
class PdfLayoutValidator: class PdfLayoutValidator:
def __call__(self, value): def __call__(self, value):
import jsonschema
if not isinstance(value, dict): if not isinstance(value, dict):
try: try:
val = json.loads(value) val = json.loads(value)

View File

@@ -47,7 +47,6 @@ from urllib.parse import urljoin, urlparse
from zoneinfo import ZoneInfo from zoneinfo import ZoneInfo
import requests import requests
from bs4 import BeautifulSoup
from celery import chain from celery import chain
from celery.exceptions import MaxRetriesExceededError from celery.exceptions import MaxRetriesExceededError
from django.conf import settings from django.conf import settings
@@ -764,6 +763,8 @@ def render_mail(template, context, placeholder_mode=SafeFormatter.MODE_RICH_TO_P
def replace_images_with_cid_paths(body_html): def replace_images_with_cid_paths(body_html):
from bs4 import BeautifulSoup
if body_html: if body_html:
email = BeautifulSoup(body_html, "lxml") email = BeautifulSoup(body_html, "lxml")
cid_images = [] cid_images = []

View File

@@ -60,7 +60,6 @@ from pretix.base.models import (
) )
from pretix.base.services.quotas import QuotaAvailability from pretix.base.services.quotas import QuotaAvailability
from pretix.base.timeline import timeline_for_event from pretix.base.timeline import timeline_for_event
from pretix.control.forms.event import CommentForm
from pretix.control.signals import ( from pretix.control.signals import (
event_dashboard_widgets, user_dashboard_widgets, event_dashboard_widgets, user_dashboard_widgets,
) )
@@ -341,6 +340,8 @@ def welcome_wizard_widget(sender, **kwargs):
def event_index(request, organizer, event): def event_index(request, organizer, event):
from pretix.control.forms.event import CommentForm
subevent = None subevent = None
if request.GET.get("subevent", "") != "" and request.event.has_subevents: if request.GET.get("subevent", "") != "" and request.event.has_subevents:
i = request.GET.get("subevent", "") i = request.GET.get("subevent", "")

View File

@@ -98,7 +98,6 @@ from pretix.control.views.mailsetup import MailSettingsSetupView
from pretix.control.views.user import RecentAuthenticationRequiredMixin from pretix.control.views.user import RecentAuthenticationRequiredMixin
from pretix.helpers.database import rolledback_transaction from pretix.helpers.database import rolledback_transaction
from pretix.multidomain.urlreverse import build_absolute_uri, get_event_domain from pretix.multidomain.urlreverse import build_absolute_uri, get_event_domain
from pretix.plugins.stripe.payment import StripeSettingsHolder
from pretix.presale.views.widget import ( from pretix.presale.views.widget import (
version_default as widget_version_default, version_default as widget_version_default,
) )
@@ -1666,6 +1665,8 @@ class QuickSetupView(FormView):
'or take your event live to start selling!')) 'or take your event live to start selling!'))
if form.cleaned_data.get('payment_stripe__enabled', False): if form.cleaned_data.get('payment_stripe__enabled', False):
from pretix.plugins.stripe.payment import StripeSettingsHolder
self.request.session['payment_stripe_oauth_enable'] = True self.request.session['payment_stripe_oauth_enable'] = True
return redirect(StripeSettingsHolder(self.request.event).get_connect_url(self.request)) return redirect(StripeSettingsHolder(self.request.event).get_connect_url(self.request))

View File

@@ -38,7 +38,6 @@ from pretix.base.signals import (
) )
from pretix.control.signals import nav_organizer from pretix.control.signals import nav_organizer
from pretix.plugins.stripe.forms import StripeKeyValidator from pretix.plugins.stripe.forms import StripeKeyValidator
from pretix.plugins.stripe.payment import StripeMethod
from pretix.presale.signals import html_head, process_response from pretix.presale.signals import html_head, process_response
@@ -189,6 +188,8 @@ def nav_o(sender, request, organizer, **kwargs):
@receiver(signal=process_response, dispatch_uid="stripe_middleware_resp") @receiver(signal=process_response, dispatch_uid="stripe_middleware_resp")
def signal_process_response(sender, request: HttpRequest, response: HttpResponse, **kwargs): def signal_process_response(sender, request: HttpRequest, response: HttpResponse, **kwargs):
from pretix.plugins.stripe.payment import StripeMethod
provider = StripeMethod(sender) provider = StripeMethod(sender)
url = resolve(request.path_info) url = resolve(request.path_info)

View File

@@ -22,7 +22,6 @@
import logging import logging
from urllib.parse import urlsplit from urllib.parse import urlsplit
import stripe
from django.conf import settings from django.conf import settings
from pretix.base.services.tasks import EventTask from pretix.base.services.tasks import EventTask
@@ -50,7 +49,10 @@ def get_stripe_account_key(prov):
@app.task(base=EventTask, max_retries=5, default_retry_delay=1) @app.task(base=EventTask, max_retries=5, default_retry_delay=1)
def stripe_verify_domain(event, domain): def stripe_verify_domain(event, domain):
import stripe
from pretix.plugins.stripe.payment import StripeCC from pretix.plugins.stripe.payment import StripeCC
prov = StripeCC(event) prov = StripeCC(event)
account = get_stripe_account_key(prov) account = get_stripe_account_key(prov)

View File

@@ -37,7 +37,6 @@ import logging
import urllib.parse import urllib.parse
import requests import requests
import stripe
from django.contrib import messages from django.contrib import messages
from django.core import signing from django.core import signing
from django.db import transaction from django.db import transaction
@@ -68,7 +67,6 @@ from pretix.helpers.http import redirect_to_url
from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse from pretix.multidomain.urlreverse import build_absolute_uri, eventreverse
from pretix.plugins.stripe.forms import OrganizerStripeSettingsForm from pretix.plugins.stripe.forms import OrganizerStripeSettingsForm
from pretix.plugins.stripe.models import ReferencedStripeObject from pretix.plugins.stripe.models import ReferencedStripeObject
from pretix.plugins.stripe.payment import StripeCC, StripeSettingsHolder
from pretix.plugins.stripe.tasks import ( from pretix.plugins.stripe.tasks import (
get_domain_for_event, stripe_verify_domain, get_domain_for_event, stripe_verify_domain,
) )
@@ -100,6 +98,8 @@ def redirect_view(request, *args, **kwargs):
@scopes_disabled() @scopes_disabled()
def oauth_return(request, *args, **kwargs): def oauth_return(request, *args, **kwargs):
import stripe
if 'payment_stripe_oauth_event' not in request.session: if 'payment_stripe_oauth_event' not in request.session:
messages.error(request, _('An error occurred during connecting with Stripe, please try again.')) messages.error(request, _('An error occurred during connecting with Stripe, please try again.'))
return redirect('control:index') return redirect('control:index')
@@ -268,6 +268,10 @@ SOURCE_TYPES = {
def charge_webhook(event, event_json, charge_id, rso): def charge_webhook(event, event_json, charge_id, rso):
import stripe
from pretix.plugins.stripe.payment import StripeCC
prov = StripeCC(event) prov = StripeCC(event)
prov._init_api() prov._init_api()
@@ -371,6 +375,10 @@ def charge_webhook(event, event_json, charge_id, rso):
def source_webhook(event, event_json, source_id, rso): def source_webhook(event, event_json, source_id, rso):
import stripe
from pretix.plugins.stripe.payment import StripeCC
prov = StripeCC(event) prov = StripeCC(event)
prov._init_api() prov._init_api()
try: try:
@@ -440,6 +448,10 @@ def source_webhook(event, event_json, source_id, rso):
def paymentintent_webhook(event, event_json, paymentintent_id, rso): def paymentintent_webhook(event, event_json, paymentintent_id, rso):
import stripe
from pretix.plugins.stripe.payment import StripeCC
prov = StripeCC(event) prov = StripeCC(event)
prov._init_api() prov._init_api()
@@ -516,6 +528,8 @@ class StripeOrderView:
@method_decorator(xframe_options_exempt, 'dispatch') @method_decorator(xframe_options_exempt, 'dispatch')
class ReturnView(StripeOrderView, View): class ReturnView(StripeOrderView, View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
import stripe
prov = self.pprov prov = self.pprov
prov._init_api() prov._init_api()
try: try:
@@ -568,6 +582,10 @@ class ReturnView(StripeOrderView, View):
class ScaView(StripeOrderView, View): class ScaView(StripeOrderView, View):
def get(self, request, *args, **kwargs): def get(self, request, *args, **kwargs):
import stripe
from pretix.plugins.stripe.payment import StripeSettingsHolder
prov = self.pprov prov = self.pprov
prov._init_api() prov._init_api()