prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Attribute filters are not available in subcategories
  ### What I'm trying to achieve
  
  I'm trying to filter products in subcategories by attributes of this products
  
  ### Steps to reproduce the problem
  1.  Create category and then create 2 or more subcategory
  2.  Add product to last subcategory
  3. Select category, than subcategory and try to filter products by attributes
  
  ### What I expected to happen
  
  Attribute filters are not available in subcategories! Filters by attributes available only in last subcategory. For example, i have category "Phones" with subcategories by companies names -> phone model. If i select last subcategory "Iphone 8", i got all filters, but if i select subcategory "Apple", i got filter only by price range.
  
  So, how to enable these filters? Can i modify some template or python code by myself, or you guys will do it some later?
  
  ### Screenshots
  ![nofitlers](https://user-images.githubusercontent.com/16798475/44631772-945c1600-a979-11e8-992b-7726533c37b3.png)
  ![filters](https://user-images.githubusercontent.com/16798475/44632055-33364180-a97d-11e8-97a0-289e9e960a1b.png)
  
  
  
  </issue>
  <code>
  [start of saleor/product/filters.py]
  1 from collections import OrderedDict
  2 
  3 from django.db.models import Q
  4 from django.forms import CheckboxSelectMultiple
  5 from django.utils.translation import pgettext_lazy
  6 from django_filters import MultipleChoiceFilter, OrderingFilter, RangeFilter
  7 
  8 from ..core.filters import SortedFilterSet
  9 from .models import Attribute, Product
  10 
  11 SORT_BY_FIELDS = OrderedDict([
  12     ('name', pgettext_lazy('Product list sorting option', 'name')),
  13     ('price', pgettext_lazy('Product list sorting option', 'price')),
  14     ('updated_at', pgettext_lazy(
  15         'Product list sorting option', 'last updated'))])
  16 
  17 
  18 class ProductFilter(SortedFilterSet):
  19     sort_by = OrderingFilter(
  20         label=pgettext_lazy('Product list sorting form', 'Sort by'),
  21         fields=SORT_BY_FIELDS.keys(),
  22         field_labels=SORT_BY_FIELDS)
  23     price = RangeFilter(
  24         label=pgettext_lazy('Currency amount', 'Price'))
  25 
  26     class Meta:
  27         model = Product
  28         fields = []
  29 
  30     def __init__(self, *args, **kwargs):
  31         super().__init__(*args, **kwargs)
  32         self.product_attributes, self.variant_attributes = (
  33             self._get_attributes())
  34         self.filters.update(self._get_product_attributes_filters())
  35         self.filters.update(self._get_product_variants_attributes_filters())
  36         self.filters = OrderedDict(sorted(self.filters.items()))
  37 
  38     def _get_attributes(self):
  39         q_product_attributes = self._get_product_attributes_lookup()
  40         q_variant_attributes = self._get_variant_attributes_lookup()
  41         product_attributes = (
  42             Attribute.objects.all()
  43             .prefetch_related('translations', 'values__translations')
  44             .filter(q_product_attributes)
  45             .distinct())
  46         variant_attributes = (
  47             Attribute.objects.all()
  48             .prefetch_related('translations', 'values__translations')
  49             .filter(q_variant_attributes)
  50             .distinct())
  51         return product_attributes, variant_attributes
  52 
  53     def _get_product_attributes_lookup(self):
  54         raise NotImplementedError()
  55 
  56     def _get_variant_attributes_lookup(self):
  57         raise NotImplementedError()
  58 
  59     def _get_product_attributes_filters(self):
  60         filters = {}
  61         for attribute in self.product_attributes:
  62             filters[attribute.slug] = MultipleChoiceFilter(
  63                 field_name='attributes__%s' % attribute.pk,
  64                 label=attribute.translated.name,
  65                 widget=CheckboxSelectMultiple,
  66                 choices=self._get_attribute_choices(attribute))
  67         return filters
  68 
  69     def _get_product_variants_attributes_filters(self):
  70         filters = {}
  71         for attribute in self.variant_attributes:
  72             filters[attribute.slug] = MultipleChoiceFilter(
  73                 field_name='variants__attributes__%s' % attribute.pk,
  74                 label=attribute.translated.name,
  75                 widget=CheckboxSelectMultiple,
  76                 choices=self._get_attribute_choices(attribute))
  77         return filters
  78 
  79     def _get_attribute_choices(self, attribute):
  80         return [
  81             (choice.pk, choice.translated.name)
  82             for choice in attribute.values.all()]
  83 
  84 
  85 class ProductCategoryFilter(ProductFilter):
  86     def __init__(self, *args, **kwargs):
  87         self.category = kwargs.pop('category')
  88         super().__init__(*args, **kwargs)
  89 
  90     def _get_product_attributes_lookup(self):
  91         return Q(product_type__products__category=self.category)
  92 
  93     def _get_variant_attributes_lookup(self):
  94         return Q(product_variant_type__products__category=self.category)
  95 
  96 
  97 class ProductCollectionFilter(ProductFilter):
  98     def __init__(self, *args, **kwargs):
  99         self.collection = kwargs.pop('collection')
  100         super().__init__(*args, **kwargs)
  101 
  102     def _get_product_attributes_lookup(self):
  103         return Q(product_type__products__collections=self.collection)
  104 
  105     def _get_variant_attributes_lookup(self):
  106         return Q(product_variant_type__products__collections=self.collection)
  107
  [end of saleor/product/filters.py]
  </code>
  
  I need you to solve this issue by generating a single patch file that I can apply directly to this repository using git apply. Please respond with a single patch file in the following format.
  <patch>
  diff --git a/file.py b/file.py
  --- a/file.py
  +++ b/file.py
  @@ -1,27 +1,35 @@
   def euclidean(a, b):
  -    while b:
  -        a, b = b, a % b
  -    return a
  +    if b == 0:
  +        return a
  +    return euclidean(b, a % b)
   
   
   def bresenham(x0, y0, x1, y1):
       points = []
       dx = abs(x1 - x0)
       dy = abs(y1 - y0)
  -    sx = 1 if x0 < x1 else -1
  -    sy = 1 if y0 < y1 else -1
  -    err = dx - dy
  +    x, y = x0, y0
  +    sx = -1 if x0 > x1 else 1
  +    sy = -1 if y0 > y1 else 1
   
  -    while True:
  -        points.append((x0, y0))
  -        if x0 == x1 and y0 == y1:
  -            break
  -        e2 = 2 * err
  -        if e2 > -dy:
  -            err -= dy
  -            x0 += sx
  -        if e2 < dx:
  -            err += dx
  -            y0 += sy
  +    if dx > dy:
  +        err = dx / 2.0
  +        while x != x1:
  +            points.append((x, y))
  +            err -= dy
  +            if err < 0:
  +                y += sy
  +                err += dx
  +            x += sx
  +    else:
  +        err = dy / 2.0
  +        while y != y1:
  +            points.append((x, y))
  +            err -= dx
  +            if err < 0:
  +                x += sx
  +                err += dy
  +            y += sy
  +
  +    points.append((x, y))
       return points
  
  </patch>
golden_diff: diff --git a/saleor/product/filters.py b/saleor/product/filters.py
  --- a/saleor/product/filters.py
  +++ b/saleor/product/filters.py
  @@ -88,10 +88,12 @@
           super().__init__(*args, **kwargs)
   
       def _get_product_attributes_lookup(self):
  -        return Q(product_type__products__category=self.category)
  +        categories = self.category.get_descendants(include_self=True)
  +        return Q(product_type__products__category__in=categories)
   
       def _get_variant_attributes_lookup(self):
  -        return Q(product_variant_type__products__category=self.category)
  +        categories = self.category.get_descendants(include_self=True)
  +        return Q(product_variant_type__products__category__in=categories)
   
   
   class ProductCollectionFilter(ProductFilter):
  
verification_info: {"golden_diff": "diff --git a/saleor/product/filters.py b/saleor/product/filters.py\n--- a/saleor/product/filters.py\n+++ b/saleor/product/filters.py\n@@ -88,10 +88,12 @@\n         super().__init__(*args, **kwargs)\n \n     def _get_product_attributes_lookup(self):\n-        return Q(product_type__products__category=self.category)\n+        categories = self.category.get_descendants(include_self=True)\n+        return Q(product_type__products__category__in=categories)\n \n     def _get_variant_attributes_lookup(self):\n-        return Q(product_variant_type__products__category=self.category)\n+        categories = self.category.get_descendants(include_self=True)\n+        return Q(product_variant_type__products__category__in=categories)\n \n \n class ProductCollectionFilter(ProductFilter):\n", "issue": "Attribute filters are not available in subcategories\n### What I'm trying to achieve\r\n\r\nI'm trying to filter products in subcategories by attributes of this products\r\n\r\n### Steps to reproduce the problem\r\n1.  Create category and then create 2 or more subcategory\r\n2.  Add product to last subcategory\r\n3. Select category, than subcategory and try to filter products by attributes\r\n\r\n### What I expected to happen\r\n\r\nAttribute filters are not available in subcategories! Filters by attributes available only in last subcategory. For example, i have category \"Phones\" with subcategories by companies names -> phone model. If i select last subcategory \"Iphone 8\", i got all filters, but if i select subcategory \"Apple\", i got filter only by price range.\r\n\r\nSo, how to enable these filters? Can i modify some template or python code by myself, or you guys will do it some later?\r\n\r\n### Screenshots\r\n![nofitlers](https://user-images.githubusercontent.com/16798475/44631772-945c1600-a979-11e8-992b-7726533c37b3.png)\r\n![filters](https://user-images.githubusercontent.com/16798475/44632055-33364180-a97d-11e8-97a0-289e9e960a1b.png)\r\n\r\n\n", "before_files": [{"content": "from collections import OrderedDict\n\nfrom django.db.models import Q\nfrom django.forms import CheckboxSelectMultiple\nfrom django.utils.translation import pgettext_lazy\nfrom django_filters import MultipleChoiceFilter, OrderingFilter, RangeFilter\n\nfrom ..core.filters import SortedFilterSet\nfrom .models import Attribute, Product\n\nSORT_BY_FIELDS = OrderedDict([\n    ('name', pgettext_lazy('Product list sorting option', 'name')),\n    ('price', pgettext_lazy('Product list sorting option', 'price')),\n    ('updated_at', pgettext_lazy(\n        'Product list sorting option', 'last updated'))])\n\n\nclass ProductFilter(SortedFilterSet):\n    sort_by = OrderingFilter(\n        label=pgettext_lazy('Product list sorting form', 'Sort by'),\n        fields=SORT_BY_FIELDS.keys(),\n        field_labels=SORT_BY_FIELDS)\n    price = RangeFilter(\n        label=pgettext_lazy('Currency amount', 'Price'))\n\n    class Meta:\n        model = Product\n        fields = []\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.product_attributes, self.variant_attributes = (\n            self._get_attributes())\n        self.filters.update(self._get_product_attributes_filters())\n        self.filters.update(self._get_product_variants_attributes_filters())\n        self.filters = OrderedDict(sorted(self.filters.items()))\n\n    def _get_attributes(self):\n        q_product_attributes = self._get_product_attributes_lookup()\n        q_variant_attributes = self._get_variant_attributes_lookup()\n        product_attributes = (\n            Attribute.objects.all()\n            .prefetch_related('translations', 'values__translations')\n            .filter(q_product_attributes)\n            .distinct())\n        variant_attributes = (\n            Attribute.objects.all()\n            .prefetch_related('translations', 'values__translations')\n            .filter(q_variant_attributes)\n            .distinct())\n        return product_attributes, variant_attributes\n\n    def _get_product_attributes_lookup(self):\n        raise NotImplementedError()\n\n    def _get_variant_attributes_lookup(self):\n        raise NotImplementedError()\n\n    def _get_product_attributes_filters(self):\n        filters = {}\n        for attribute in self.product_attributes:\n            filters[attribute.slug] = MultipleChoiceFilter(\n                field_name='attributes__%s' % attribute.pk,\n                label=attribute.translated.name,\n                widget=CheckboxSelectMultiple,\n                choices=self._get_attribute_choices(attribute))\n        return filters\n\n    def _get_product_variants_attributes_filters(self):\n        filters = {}\n        for attribute in self.variant_attributes:\n            filters[attribute.slug] = MultipleChoiceFilter(\n                field_name='variants__attributes__%s' % attribute.pk,\n                label=attribute.translated.name,\n                widget=CheckboxSelectMultiple,\n                choices=self._get_attribute_choices(attribute))\n        return filters\n\n    def _get_attribute_choices(self, attribute):\n        return [\n            (choice.pk, choice.translated.name)\n            for choice in attribute.values.all()]\n\n\nclass ProductCategoryFilter(ProductFilter):\n    def __init__(self, *args, **kwargs):\n        self.category = kwargs.pop('category')\n        super().__init__(*args, **kwargs)\n\n    def _get_product_attributes_lookup(self):\n        return Q(product_type__products__category=self.category)\n\n    def _get_variant_attributes_lookup(self):\n        return Q(product_variant_type__products__category=self.category)\n\n\nclass ProductCollectionFilter(ProductFilter):\n    def __init__(self, *args, **kwargs):\n        self.collection = kwargs.pop('collection')\n        super().__init__(*args, **kwargs)\n\n    def _get_product_attributes_lookup(self):\n        return Q(product_type__products__collections=self.collection)\n\n    def _get_variant_attributes_lookup(self):\n        return Q(product_variant_type__products__collections=self.collection)\n", "path": "saleor/product/filters.py"}]}