We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Display remaining quota of add-on products
Currently if you enable "Show number of tickets left" on an event that only applies to products, not add-on products. In my opinion if there is an quota presend for add-on products it should also be displayed (if the quota is exceeded that is already displayed).
Display remaining quota of add-on products
Currently if you enable "Show number of tickets left" on an event that only applies to products, not add-on products. In my opinion if there is an quota presend for add-on products it should also be displayed (if the quota is exceeded that is already displayed).

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `src/pretix/presale/forms/checkout.py`
Content:
```
1 from itertools import chain
2 
3 from django import forms
4 from django.core.exceptions import ValidationError
5 from django.db.models import Count, Prefetch, Q
6 from django.utils.encoding import force_text
7 from django.utils.formats import number_format
8 from django.utils.timezone import now
9 from django.utils.translation import ugettext_lazy as _
10 
11 from pretix.base.forms.questions import (
12     BaseInvoiceAddressForm, BaseQuestionsForm,
13 )
14 from pretix.base.models import ItemVariation
15 from pretix.base.models.tax import TAXED_ZERO
16 from pretix.base.templatetags.money import money_filter
17 from pretix.base.templatetags.rich_text import rich_text
18 from pretix.base.validators import EmailBlacklistValidator
19 from pretix.presale.signals import contact_form_fields
20 
21 
22 class ContactForm(forms.Form):
23     required_css_class = 'required'
24     email = forms.EmailField(label=_('E-mail'),
25                              help_text=_('Make sure to enter a valid email address. We will send you an order '
26                                          'confirmation including a link that you need in case you want to make '
27                                          'modifications to your order or download your ticket later.'),
28                              validators=[EmailBlacklistValidator()],
29                              widget=forms.EmailInput(attrs={'autofocus': 'autofocus'}))
30 
31     def __init__(self, *args, **kwargs):
32         self.event = kwargs.pop('event')
33         self.request = kwargs.pop('request')
34         super().__init__(*args, **kwargs)
35 
36         if self.event.settings.order_email_asked_twice:
37             self.fields['email_repeat'] = forms.EmailField(
38                 label=_('E-mail address (repeated)'),
39                 help_text=_('Please enter the same email address again to make sure you typed it correctly.')
40             )
41 
42         responses = contact_form_fields.send(self.event, request=self.request)
43         for r, response in sorted(responses, key=lambda r: str(r[0])):
44             for key, value in response.items():
45                 # We need to be this explicit, since OrderedDict.update does not retain ordering
46                 self.fields[key] = value
47 
48     def clean(self):
49         if self.event.settings.order_email_asked_twice and self.cleaned_data.get('email') and self.cleaned_data.get('email_repeat'):
50             if self.cleaned_data.get('email').lower() != self.cleaned_data.get('email_repeat').lower():
51                 raise ValidationError(_('Please enter the same email address twice.'))
52 
53 
54 class InvoiceAddressForm(BaseInvoiceAddressForm):
55     required_css_class = 'required'
56     vat_warning = True
57 
58 
59 class QuestionsForm(BaseQuestionsForm):
60     """
61     This form class is responsible for asking order-related questions. This includes
62     the attendee name for admission tickets, if the corresponding setting is enabled,
63     as well as additional questions defined by the organizer.
64     """
65     required_css_class = 'required'
66 
67 
68 class AddOnRadioSelect(forms.RadioSelect):
69     option_template_name = 'pretixpresale/forms/addon_choice_option.html'
70 
71     def optgroups(self, name, value, attrs=None):
72         attrs = attrs or {}
73         groups = []
74         has_selected = False
75         for index, (option_value, option_label, option_desc) in enumerate(chain(self.choices)):
76             if option_value is None:
77                 option_value = ''
78             if isinstance(option_label, (list, tuple)):
79                 raise TypeError('Choice groups are not supported here')
80             group_name = None
81             subgroup = []
82             groups.append((group_name, subgroup, index))
83 
84             selected = (
85                 force_text(option_value) in value and
86                 (has_selected is False or self.allow_multiple_selected)
87             )
88             if selected is True and has_selected is False:
89                 has_selected = True
90             attrs['description'] = option_desc
91             subgroup.append(self.create_option(
92                 name, option_value, option_label, selected, index,
93                 subindex=None, attrs=attrs,
94             ))
95 
96         return groups
97 
98 
99 class AddOnVariationField(forms.ChoiceField):
100     def valid_value(self, value):
101         text_value = force_text(value)
102         for k, v, d in self.choices:
103             if value == k or text_value == force_text(k):
104                 return True
105         return False
106 
107 
108 class AddOnsForm(forms.Form):
109     """
110     This form class is responsible for selecting add-ons to a product in the cart.
111     """
112 
113     def _label(self, event, item_or_variation, avail, override_price=None):
114         if isinstance(item_or_variation, ItemVariation):
115             variation = item_or_variation
116             item = item_or_variation.item
117             price = variation.price
118             label = variation.value
119         else:
120             item = item_or_variation
121             price = item.default_price
122             label = item.name
123 
124         if override_price:
125             price = override_price
126 
127         if self.price_included:
128             price = TAXED_ZERO
129         else:
130             price = item.tax(price)
131 
132         if not price.gross:
133             n = '{name}'.format(
134                 name=label
135             )
136         elif not price.rate:
137             n = _('{name} (+ {price})').format(
138                 name=label, price=money_filter(price.gross, event.currency)
139             )
140         elif event.settings.display_net_prices:
141             n = _('{name} (+ {price} plus {taxes}% {taxname})').format(
142                 name=label, price=money_filter(price.net, event.currency),
143                 taxes=number_format(price.rate), taxname=price.name
144             )
145         else:
146             n = _('{name} (+ {price} incl. {taxes}% {taxname})').format(
147                 name=label, price=money_filter(price.gross, event.currency),
148                 taxes=number_format(price.rate), taxname=price.name
149             )
150 
151         if avail[0] < 20:
152             n += ' – {}'.format(_('SOLD OUT'))
153         elif avail[0] < 100:
154             n += ' – {}'.format(_('Currently unavailable'))
155 
156         return n
157 
158     def __init__(self, *args, **kwargs):
159         """
160         Takes additional keyword arguments:
161 
162         :param category: The category to choose from
163         :param event: The event this belongs to
164         :param subevent: The event the parent cart position belongs to
165         :param initial: The current set of add-ons
166         :param quota_cache: A shared dictionary for quota caching
167         :param item_cache: A shared dictionary for item/category caching
168         """
169         category = kwargs.pop('category')
170         event = kwargs.pop('event')
171         subevent = kwargs.pop('subevent')
172         current_addons = kwargs.pop('initial')
173         quota_cache = kwargs.pop('quota_cache')
174         item_cache = kwargs.pop('item_cache')
175         self.price_included = kwargs.pop('price_included')
176 
177         super().__init__(*args, **kwargs)
178 
179         if subevent:
180             item_price_override = subevent.item_price_overrides
181             var_price_override = subevent.var_price_overrides
182         else:
183             item_price_override = {}
184             var_price_override = {}
185 
186         ckey = '{}-{}'.format(subevent.pk if subevent else 0, category.pk)
187         if ckey not in item_cache:
188             # Get all items to possibly show
189             items = category.items.filter(
190                 Q(active=True)
191                 & Q(Q(available_from__isnull=True) | Q(available_from__lte=now()))
192                 & Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))
193                 & Q(hide_without_voucher=False)
194             ).select_related('tax_rule').prefetch_related(
195                 Prefetch('quotas',
196                          to_attr='_subevent_quotas',
197                          queryset=event.quotas.filter(subevent=subevent)),
198                 Prefetch('variations', to_attr='available_variations',
199                          queryset=ItemVariation.objects.filter(active=True, quotas__isnull=False).prefetch_related(
200                              Prefetch('quotas',
201                                       to_attr='_subevent_quotas',
202                                       queryset=event.quotas.filter(subevent=subevent))
203                          ).distinct()),
204             ).annotate(
205                 quotac=Count('quotas'),
206                 has_variations=Count('variations')
207             ).filter(
208                 quotac__gt=0
209             ).order_by('category__position', 'category_id', 'position', 'name')
210             item_cache[ckey] = items
211         else:
212             items = item_cache[ckey]
213 
214         for i in items:
215             if i.has_variations:
216                 choices = [('', _('no selection'), '')]
217                 for v in i.available_variations:
218                     cached_availability = v.check_quotas(subevent=subevent, _cache=quota_cache)
219                     if v._subevent_quotas:
220                         choices.append(
221                             (v.pk,
222                              self._label(event, v, cached_availability,
223                                          override_price=var_price_override.get(v.pk)),
224                              v.description)
225                         )
226 
227                 field = AddOnVariationField(
228                     choices=choices,
229                     label=i.name,
230                     required=False,
231                     widget=AddOnRadioSelect,
232                     help_text=rich_text(str(i.description)),
233                     initial=current_addons.get(i.pk),
234                 )
235                 if len(choices) > 1:
236                     self.fields['item_%s' % i.pk] = field
237             else:
238                 if not i._subevent_quotas:
239                     continue
240                 cached_availability = i.check_quotas(subevent=subevent, _cache=quota_cache)
241                 field = forms.BooleanField(
242                     label=self._label(event, i, cached_availability,
243                                       override_price=item_price_override.get(i.pk)),
244                     required=False,
245                     initial=i.pk in current_addons,
246                     help_text=rich_text(str(i.description)),
247                 )
248                 self.fields['item_%s' % i.pk] = field
249
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/src/pretix/presale/forms/checkout.py b/src/pretix/presale/forms/checkout.py
--- a/src/pretix/presale/forms/checkout.py
+++ b/src/pretix/presale/forms/checkout.py
@@ -152,6 +152,9 @@
             n += ' – {}'.format(_('SOLD OUT'))
         elif avail[0] < 100:
             n += ' – {}'.format(_('Currently unavailable'))
+        else:
+            if avail[1] is not None and event.settings.show_quota_left:
+                n += ' – {}'.format(_('%(num)s currently available') % {'num': avail[1]})
 
         return n

{"golden_diff": "diff --git a/src/pretix/presale/forms/checkout.py b/src/pretix/presale/forms/checkout.py\n--- a/src/pretix/presale/forms/checkout.py\n+++ b/src/pretix/presale/forms/checkout.py\n@@ -152,6 +152,9 @@\n             n += ' \u2013 {}'.format(_('SOLD OUT'))\n         elif avail[0] < 100:\n             n += ' \u2013 {}'.format(_('Currently unavailable'))\n+        else:\n+            if avail[1] is not None and event.settings.show_quota_left:\n+                n += ' \u2013 {}'.format(_('%(num)s currently available') % {'num': avail[1]})\n \n         return n\n", "issue": "Display remaining quota of add-on products\nCurrently if you enable \"Show number of tickets left\" on an event that only applies to products, not add-on products. In my opinion if there is an quota presend for add-on products it should also be displayed (if the quota is exceeded that is already displayed).\nDisplay remaining quota of add-on products\nCurrently if you enable \"Show number of tickets left\" on an event that only applies to products, not add-on products. In my opinion if there is an quota presend for add-on products it should also be displayed (if the quota is exceeded that is already displayed).\n", "before_files": [{"content": "from itertools import chain\n\nfrom django import forms\nfrom django.core.exceptions import ValidationError\nfrom django.db.models import Count, Prefetch, Q\nfrom django.utils.encoding import force_text\nfrom django.utils.formats import number_format\nfrom django.utils.timezone import now\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom pretix.base.forms.questions import (\n    BaseInvoiceAddressForm, BaseQuestionsForm,\n)\nfrom pretix.base.models import ItemVariation\nfrom pretix.base.models.tax import TAXED_ZERO\nfrom pretix.base.templatetags.money import money_filter\nfrom pretix.base.templatetags.rich_text import rich_text\nfrom pretix.base.validators import EmailBlacklistValidator\nfrom pretix.presale.signals import contact_form_fields\n\n\nclass ContactForm(forms.Form):\n    required_css_class = 'required'\n    email = forms.EmailField(label=_('E-mail'),\n                             help_text=_('Make sure to enter a valid email address. We will send you an order '\n                                         'confirmation including a link that you need in case you want to make '\n                                         'modifications to your order or download your ticket later.'),\n                             validators=[EmailBlacklistValidator()],\n                             widget=forms.EmailInput(attrs={'autofocus': 'autofocus'}))\n\n    def __init__(self, *args, **kwargs):\n        self.event = kwargs.pop('event')\n        self.request = kwargs.pop('request')\n        super().__init__(*args, **kwargs)\n\n        if self.event.settings.order_email_asked_twice:\n            self.fields['email_repeat'] = forms.EmailField(\n                label=_('E-mail address (repeated)'),\n                help_text=_('Please enter the same email address again to make sure you typed it correctly.')\n            )\n\n        responses = contact_form_fields.send(self.event, request=self.request)\n        for r, response in sorted(responses, key=lambda r: str(r[0])):\n            for key, value in response.items():\n                # We need to be this explicit, since OrderedDict.update does not retain ordering\n                self.fields[key] = value\n\n    def clean(self):\n        if self.event.settings.order_email_asked_twice and self.cleaned_data.get('email') and self.cleaned_data.get('email_repeat'):\n            if self.cleaned_data.get('email').lower() != self.cleaned_data.get('email_repeat').lower():\n                raise ValidationError(_('Please enter the same email address twice.'))\n\n\nclass InvoiceAddressForm(BaseInvoiceAddressForm):\n    required_css_class = 'required'\n    vat_warning = True\n\n\nclass QuestionsForm(BaseQuestionsForm):\n    \"\"\"\n    This form class is responsible for asking order-related questions. This includes\n    the attendee name for admission tickets, if the corresponding setting is enabled,\n    as well as additional questions defined by the organizer.\n    \"\"\"\n    required_css_class = 'required'\n\n\nclass AddOnRadioSelect(forms.RadioSelect):\n    option_template_name = 'pretixpresale/forms/addon_choice_option.html'\n\n    def optgroups(self, name, value, attrs=None):\n        attrs = attrs or {}\n        groups = []\n        has_selected = False\n        for index, (option_value, option_label, option_desc) in enumerate(chain(self.choices)):\n            if option_value is None:\n                option_value = ''\n            if isinstance(option_label, (list, tuple)):\n                raise TypeError('Choice groups are not supported here')\n            group_name = None\n            subgroup = []\n            groups.append((group_name, subgroup, index))\n\n            selected = (\n                force_text(option_value) in value and\n                (has_selected is False or self.allow_multiple_selected)\n            )\n            if selected is True and has_selected is False:\n                has_selected = True\n            attrs['description'] = option_desc\n            subgroup.append(self.create_option(\n                name, option_value, option_label, selected, index,\n                subindex=None, attrs=attrs,\n            ))\n\n        return groups\n\n\nclass AddOnVariationField(forms.ChoiceField):\n    def valid_value(self, value):\n        text_value = force_text(value)\n        for k, v, d in self.choices:\n            if value == k or text_value == force_text(k):\n                return True\n        return False\n\n\nclass AddOnsForm(forms.Form):\n    \"\"\"\n    This form class is responsible for selecting add-ons to a product in the cart.\n    \"\"\"\n\n    def _label(self, event, item_or_variation, avail, override_price=None):\n        if isinstance(item_or_variation, ItemVariation):\n            variation = item_or_variation\n            item = item_or_variation.item\n            price = variation.price\n            label = variation.value\n        else:\n            item = item_or_variation\n            price = item.default_price\n            label = item.name\n\n        if override_price:\n            price = override_price\n\n        if self.price_included:\n            price = TAXED_ZERO\n        else:\n            price = item.tax(price)\n\n        if not price.gross:\n            n = '{name}'.format(\n                name=label\n            )\n        elif not price.rate:\n            n = _('{name} (+ {price})').format(\n                name=label, price=money_filter(price.gross, event.currency)\n            )\n        elif event.settings.display_net_prices:\n            n = _('{name} (+ {price} plus {taxes}% {taxname})').format(\n                name=label, price=money_filter(price.net, event.currency),\n                taxes=number_format(price.rate), taxname=price.name\n            )\n        else:\n            n = _('{name} (+ {price} incl. {taxes}% {taxname})').format(\n                name=label, price=money_filter(price.gross, event.currency),\n                taxes=number_format(price.rate), taxname=price.name\n            )\n\n        if avail[0] < 20:\n            n += ' \u2013 {}'.format(_('SOLD OUT'))\n        elif avail[0] < 100:\n            n += ' \u2013 {}'.format(_('Currently unavailable'))\n\n        return n\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"\n        Takes additional keyword arguments:\n\n        :param category: The category to choose from\n        :param event: The event this belongs to\n        :param subevent: The event the parent cart position belongs to\n        :param initial: The current set of add-ons\n        :param quota_cache: A shared dictionary for quota caching\n        :param item_cache: A shared dictionary for item/category caching\n        \"\"\"\n        category = kwargs.pop('category')\n        event = kwargs.pop('event')\n        subevent = kwargs.pop('subevent')\n        current_addons = kwargs.pop('initial')\n        quota_cache = kwargs.pop('quota_cache')\n        item_cache = kwargs.pop('item_cache')\n        self.price_included = kwargs.pop('price_included')\n\n        super().__init__(*args, **kwargs)\n\n        if subevent:\n            item_price_override = subevent.item_price_overrides\n            var_price_override = subevent.var_price_overrides\n        else:\n            item_price_override = {}\n            var_price_override = {}\n\n        ckey = '{}-{}'.format(subevent.pk if subevent else 0, category.pk)\n        if ckey not in item_cache:\n            # Get all items to possibly show\n            items = category.items.filter(\n                Q(active=True)\n                & Q(Q(available_from__isnull=True) | Q(available_from__lte=now()))\n                & Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))\n                & Q(hide_without_voucher=False)\n            ).select_related('tax_rule').prefetch_related(\n                Prefetch('quotas',\n                         to_attr='_subevent_quotas',\n                         queryset=event.quotas.filter(subevent=subevent)),\n                Prefetch('variations', to_attr='available_variations',\n                         queryset=ItemVariation.objects.filter(active=True, quotas__isnull=False).prefetch_related(\n                             Prefetch('quotas',\n                                      to_attr='_subevent_quotas',\n                                      queryset=event.quotas.filter(subevent=subevent))\n                         ).distinct()),\n            ).annotate(\n                quotac=Count('quotas'),\n                has_variations=Count('variations')\n            ).filter(\n                quotac__gt=0\n            ).order_by('category__position', 'category_id', 'position', 'name')\n            item_cache[ckey] = items\n        else:\n            items = item_cache[ckey]\n\n        for i in items:\n            if i.has_variations:\n                choices = [('', _('no selection'), '')]\n                for v in i.available_variations:\n                    cached_availability = v.check_quotas(subevent=subevent, _cache=quota_cache)\n                    if v._subevent_quotas:\n                        choices.append(\n                            (v.pk,\n                             self._label(event, v, cached_availability,\n                                         override_price=var_price_override.get(v.pk)),\n                             v.description)\n                        )\n\n                field = AddOnVariationField(\n                    choices=choices,\n                    label=i.name,\n                    required=False,\n                    widget=AddOnRadioSelect,\n                    help_text=rich_text(str(i.description)),\n                    initial=current_addons.get(i.pk),\n                )\n                if len(choices) > 1:\n                    self.fields['item_%s' % i.pk] = field\n            else:\n                if not i._subevent_quotas:\n                    continue\n                cached_availability = i.check_quotas(subevent=subevent, _cache=quota_cache)\n                field = forms.BooleanField(\n                    label=self._label(event, i, cached_availability,\n                                      override_price=item_price_override.get(i.pk)),\n                    required=False,\n                    initial=i.pk in current_addons,\n                    help_text=rich_text(str(i.description)),\n                )\n                self.fields['item_%s' % i.pk] = field\n", "path": "src/pretix/presale/forms/checkout.py"}], "after_files": [{"content": "from itertools import chain\n\nfrom django import forms\nfrom django.core.exceptions import ValidationError\nfrom django.db.models import Count, Prefetch, Q\nfrom django.utils.encoding import force_text\nfrom django.utils.formats import number_format\nfrom django.utils.timezone import now\nfrom django.utils.translation import ugettext_lazy as _\n\nfrom pretix.base.forms.questions import (\n    BaseInvoiceAddressForm, BaseQuestionsForm,\n)\nfrom pretix.base.models import ItemVariation\nfrom pretix.base.models.tax import TAXED_ZERO\nfrom pretix.base.templatetags.money import money_filter\nfrom pretix.base.templatetags.rich_text import rich_text\nfrom pretix.base.validators import EmailBlacklistValidator\nfrom pretix.presale.signals import contact_form_fields\n\n\nclass ContactForm(forms.Form):\n    required_css_class = 'required'\n    email = forms.EmailField(label=_('E-mail'),\n                             help_text=_('Make sure to enter a valid email address. We will send you an order '\n                                         'confirmation including a link that you need in case you want to make '\n                                         'modifications to your order or download your ticket later.'),\n                             validators=[EmailBlacklistValidator()],\n                             widget=forms.EmailInput(attrs={'autofocus': 'autofocus'}))\n\n    def __init__(self, *args, **kwargs):\n        self.event = kwargs.pop('event')\n        self.request = kwargs.pop('request')\n        super().__init__(*args, **kwargs)\n\n        if self.event.settings.order_email_asked_twice:\n            self.fields['email_repeat'] = forms.EmailField(\n                label=_('E-mail address (repeated)'),\n                help_text=_('Please enter the same email address again to make sure you typed it correctly.')\n            )\n\n        responses = contact_form_fields.send(self.event, request=self.request)\n        for r, response in sorted(responses, key=lambda r: str(r[0])):\n            for key, value in response.items():\n                # We need to be this explicit, since OrderedDict.update does not retain ordering\n                self.fields[key] = value\n\n    def clean(self):\n        if self.event.settings.order_email_asked_twice and self.cleaned_data.get('email') and self.cleaned_data.get('email_repeat'):\n            if self.cleaned_data.get('email').lower() != self.cleaned_data.get('email_repeat').lower():\n                raise ValidationError(_('Please enter the same email address twice.'))\n\n\nclass InvoiceAddressForm(BaseInvoiceAddressForm):\n    required_css_class = 'required'\n    vat_warning = True\n\n\nclass QuestionsForm(BaseQuestionsForm):\n    \"\"\"\n    This form class is responsible for asking order-related questions. This includes\n    the attendee name for admission tickets, if the corresponding setting is enabled,\n    as well as additional questions defined by the organizer.\n    \"\"\"\n    required_css_class = 'required'\n\n\nclass AddOnRadioSelect(forms.RadioSelect):\n    option_template_name = 'pretixpresale/forms/addon_choice_option.html'\n\n    def optgroups(self, name, value, attrs=None):\n        attrs = attrs or {}\n        groups = []\n        has_selected = False\n        for index, (option_value, option_label, option_desc) in enumerate(chain(self.choices)):\n            if option_value is None:\n                option_value = ''\n            if isinstance(option_label, (list, tuple)):\n                raise TypeError('Choice groups are not supported here')\n            group_name = None\n            subgroup = []\n            groups.append((group_name, subgroup, index))\n\n            selected = (\n                force_text(option_value) in value and\n                (has_selected is False or self.allow_multiple_selected)\n            )\n            if selected is True and has_selected is False:\n                has_selected = True\n            attrs['description'] = option_desc\n            subgroup.append(self.create_option(\n                name, option_value, option_label, selected, index,\n                subindex=None, attrs=attrs,\n            ))\n\n        return groups\n\n\nclass AddOnVariationField(forms.ChoiceField):\n    def valid_value(self, value):\n        text_value = force_text(value)\n        for k, v, d in self.choices:\n            if value == k or text_value == force_text(k):\n                return True\n        return False\n\n\nclass AddOnsForm(forms.Form):\n    \"\"\"\n    This form class is responsible for selecting add-ons to a product in the cart.\n    \"\"\"\n\n    def _label(self, event, item_or_variation, avail, override_price=None):\n        if isinstance(item_or_variation, ItemVariation):\n            variation = item_or_variation\n            item = item_or_variation.item\n            price = variation.price\n            label = variation.value\n        else:\n            item = item_or_variation\n            price = item.default_price\n            label = item.name\n\n        if override_price:\n            price = override_price\n\n        if self.price_included:\n            price = TAXED_ZERO\n        else:\n            price = item.tax(price)\n\n        if not price.gross:\n            n = '{name}'.format(\n                name=label\n            )\n        elif not price.rate:\n            n = _('{name} (+ {price})').format(\n                name=label, price=money_filter(price.gross, event.currency)\n            )\n        elif event.settings.display_net_prices:\n            n = _('{name} (+ {price} plus {taxes}% {taxname})').format(\n                name=label, price=money_filter(price.net, event.currency),\n                taxes=number_format(price.rate), taxname=price.name\n            )\n        else:\n            n = _('{name} (+ {price} incl. {taxes}% {taxname})').format(\n                name=label, price=money_filter(price.gross, event.currency),\n                taxes=number_format(price.rate), taxname=price.name\n            )\n\n        if avail[0] < 20:\n            n += ' \u2013 {}'.format(_('SOLD OUT'))\n        elif avail[0] < 100:\n            n += ' \u2013 {}'.format(_('Currently unavailable'))\n        else:\n            if avail[1] is not None and event.settings.show_quota_left:\n                n += ' \u2013 {}'.format(_('%(num)s currently available') % {'num': avail[1]})\n\n        return n\n\n    def __init__(self, *args, **kwargs):\n        \"\"\"\n        Takes additional keyword arguments:\n\n        :param category: The category to choose from\n        :param event: The event this belongs to\n        :param subevent: The event the parent cart position belongs to\n        :param initial: The current set of add-ons\n        :param quota_cache: A shared dictionary for quota caching\n        :param item_cache: A shared dictionary for item/category caching\n        \"\"\"\n        category = kwargs.pop('category')\n        event = kwargs.pop('event')\n        subevent = kwargs.pop('subevent')\n        current_addons = kwargs.pop('initial')\n        quota_cache = kwargs.pop('quota_cache')\n        item_cache = kwargs.pop('item_cache')\n        self.price_included = kwargs.pop('price_included')\n\n        super().__init__(*args, **kwargs)\n\n        if subevent:\n            item_price_override = subevent.item_price_overrides\n            var_price_override = subevent.var_price_overrides\n        else:\n            item_price_override = {}\n            var_price_override = {}\n\n        ckey = '{}-{}'.format(subevent.pk if subevent else 0, category.pk)\n        if ckey not in item_cache:\n            # Get all items to possibly show\n            items = category.items.filter(\n                Q(active=True)\n                & Q(Q(available_from__isnull=True) | Q(available_from__lte=now()))\n                & Q(Q(available_until__isnull=True) | Q(available_until__gte=now()))\n                & Q(hide_without_voucher=False)\n            ).select_related('tax_rule').prefetch_related(\n                Prefetch('quotas',\n                         to_attr='_subevent_quotas',\n                         queryset=event.quotas.filter(subevent=subevent)),\n                Prefetch('variations', to_attr='available_variations',\n                         queryset=ItemVariation.objects.filter(active=True, quotas__isnull=False).prefetch_related(\n                             Prefetch('quotas',\n                                      to_attr='_subevent_quotas',\n                                      queryset=event.quotas.filter(subevent=subevent))\n                         ).distinct()),\n            ).annotate(\n                quotac=Count('quotas'),\n                has_variations=Count('variations')\n            ).filter(\n                quotac__gt=0\n            ).order_by('category__position', 'category_id', 'position', 'name')\n            item_cache[ckey] = items\n        else:\n            items = item_cache[ckey]\n\n        for i in items:\n            if i.has_variations:\n                choices = [('', _('no selection'), '')]\n                for v in i.available_variations:\n                    cached_availability = v.check_quotas(subevent=subevent, _cache=quota_cache)\n                    if v._subevent_quotas:\n                        choices.append(\n                            (v.pk,\n                             self._label(event, v, cached_availability,\n                                         override_price=var_price_override.get(v.pk)),\n                             v.description)\n                        )\n\n                field = AddOnVariationField(\n                    choices=choices,\n                    label=i.name,\n                    required=False,\n                    widget=AddOnRadioSelect,\n                    help_text=rich_text(str(i.description)),\n                    initial=current_addons.get(i.pk),\n                )\n                if len(choices) > 1:\n                    self.fields['item_%s' % i.pk] = field\n            else:\n                if not i._subevent_quotas:\n                    continue\n                cached_availability = i.check_quotas(subevent=subevent, _cache=quota_cache)\n                field = forms.BooleanField(\n                    label=self._label(event, i, cached_availability,\n                                      override_price=item_price_override.get(i.pk)),\n                    required=False,\n                    initial=i.pk in current_addons,\n                    help_text=rich_text(str(i.description)),\n                )\n                self.fields['item_%s' % i.pk] = field\n", "path": "src/pretix/presale/forms/checkout.py"}]}