prompt: You will be provided with a partial code base and an issue statement explaining a problem to resolve.
  <issue>
  Hitting a server error when accessing a Tag page of a Tag without any resoures associated to it
  This is a regression from https://github.com/mozilla/pontoon/commit/1dcd7382221f7b943b9b743ee32322f7233f6a86.
  
  </issue>
  <code>
  [start of pontoon/tags/utils.py]
  1 from django.db.models import Q, Max, Sum
  2 
  3 from pontoon.base.models import TranslatedResource, Translation
  4 from pontoon.tags.models import Tag
  5 
  6 
  7 class Tags:
  8     """This provides an API for retrieving related ``Tags`` for given filters,
  9     providing statistical information and latest activity data.
  10     """
  11 
  12     def __init__(self, **kwargs):
  13         self.project = kwargs.get("project")
  14         self.locale = kwargs.get("locale")
  15         self.slug = kwargs.get("slug")
  16         self.tag = Tag.objects.filter(project=self.project, slug=self.slug).first()
  17 
  18     def get(self):
  19         tags = (
  20             Tag.objects.filter(project=self.project, resources__isnull=False)
  21             .distinct()
  22             .order_by("-priority", "name")
  23         )
  24 
  25         chart = self.chart(Q(), "resource__tag")
  26         latest_activity = self.latest_activity(Q(), "resource__tag")
  27         for tag in tags:
  28             tag.chart = chart.get(tag.pk)
  29             tag.latest_activity = latest_activity.get(tag.pk)
  30 
  31         return tags
  32 
  33     def get_tag_locales(self):
  34         tag = self.tag
  35 
  36         if tag is None:
  37             return None
  38 
  39         chart = self.chart(Q(resource__tag=self.tag), "resource__tag")
  40         tag.chart = chart.get(tag.pk)
  41         tag.locales = self.project.locales.all()
  42 
  43         locale_chart = self.chart(Q(resource__tag=self.tag), "locale")
  44         locale_latest_activity = self.latest_activity(
  45             Q(resource__tag=self.tag), "locale"
  46         )
  47         for locale in tag.locales:
  48             locale.chart = locale_chart.get(locale.pk)
  49             locale.latest_activity = locale_latest_activity.get(locale.pk)
  50 
  51         return tag
  52 
  53     def chart(self, query, group_by):
  54         trs = (
  55             self.translated_resources.filter(query)
  56             .values(group_by)
  57             .annotate(
  58                 total_strings=Sum("resource__total_strings"),
  59                 approved_strings=Sum("approved_strings"),
  60                 pretranslated_strings=Sum("pretranslated_strings"),
  61                 strings_with_errors=Sum("strings_with_errors"),
  62                 strings_with_warnings=Sum("strings_with_warnings"),
  63                 unreviewed_strings=Sum("unreviewed_strings"),
  64             )
  65         )
  66 
  67         return {
  68             tr[group_by]: TranslatedResource.get_chart_dict(
  69                 TranslatedResource(**{key: tr[key] for key in list(tr.keys())[1:]})
  70             )
  71             for tr in trs
  72         }
  73 
  74     def latest_activity(self, query, group_by):
  75         latest_activity = {}
  76         dates = {}
  77         translations = Translation.objects.none()
  78 
  79         trs = (
  80             self.translated_resources.exclude(latest_translation__isnull=True)
  81             .filter(query)
  82             .values(group_by)
  83             .annotate(
  84                 date=Max("latest_translation__date"),
  85                 approved_date=Max("latest_translation__approved_date"),
  86             )
  87         )
  88 
  89         for tr in trs:
  90             date = max(tr["date"], tr["approved_date"] or tr["date"])
  91             dates[date] = tr[group_by]
  92             prefix = "entity__" if group_by == "resource__tag" else ""
  93 
  94             # Find translations with matching date and tag/locale
  95             translations |= Translation.objects.filter(
  96                 Q(**{"date": date, f"{prefix}{group_by}": tr[group_by]})
  97             ).prefetch_related("user", "approved_user")
  98 
  99         for t in translations:
  100             key = dates[t.latest_activity["date"]]
  101             latest_activity[key] = t.latest_activity
  102 
  103         return latest_activity
  104 
  105     @property
  106     def translated_resources(self):
  107         trs = TranslatedResource.objects
  108 
  109         if self.project is not None:
  110             trs = trs.filter(resource__project=self.project)
  111 
  112         if self.locale is not None:
  113             trs = trs.filter(locale=self.locale)
  114 
  115         return trs
  116
  [end of pontoon/tags/utils.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/pontoon/tags/utils.py b/pontoon/tags/utils.py
  --- a/pontoon/tags/utils.py
  +++ b/pontoon/tags/utils.py
  @@ -13,7 +13,9 @@
           self.project = kwargs.get("project")
           self.locale = kwargs.get("locale")
           self.slug = kwargs.get("slug")
  -        self.tag = Tag.objects.filter(project=self.project, slug=self.slug).first()
  +        self.tag = Tag.objects.filter(
  +            project=self.project, slug=self.slug, resources__isnull=False
  +        ).first()
   
       def get(self):
           tags = (
  
verification_info: {"golden_diff": "diff --git a/pontoon/tags/utils.py b/pontoon/tags/utils.py\n--- a/pontoon/tags/utils.py\n+++ b/pontoon/tags/utils.py\n@@ -13,7 +13,9 @@\n         self.project = kwargs.get(\"project\")\n         self.locale = kwargs.get(\"locale\")\n         self.slug = kwargs.get(\"slug\")\n-        self.tag = Tag.objects.filter(project=self.project, slug=self.slug).first()\n+        self.tag = Tag.objects.filter(\n+            project=self.project, slug=self.slug, resources__isnull=False\n+        ).first()\n \n     def get(self):\n         tags = (\n", "issue": "Hitting a server error when accessing a Tag page of a Tag without any resoures associated to it\nThis is a regression from https://github.com/mozilla/pontoon/commit/1dcd7382221f7b943b9b743ee32322f7233f6a86.\n", "before_files": [{"content": "from django.db.models import Q, Max, Sum\n\nfrom pontoon.base.models import TranslatedResource, Translation\nfrom pontoon.tags.models import Tag\n\n\nclass Tags:\n    \"\"\"This provides an API for retrieving related ``Tags`` for given filters,\n    providing statistical information and latest activity data.\n    \"\"\"\n\n    def __init__(self, **kwargs):\n        self.project = kwargs.get(\"project\")\n        self.locale = kwargs.get(\"locale\")\n        self.slug = kwargs.get(\"slug\")\n        self.tag = Tag.objects.filter(project=self.project, slug=self.slug).first()\n\n    def get(self):\n        tags = (\n            Tag.objects.filter(project=self.project, resources__isnull=False)\n            .distinct()\n            .order_by(\"-priority\", \"name\")\n        )\n\n        chart = self.chart(Q(), \"resource__tag\")\n        latest_activity = self.latest_activity(Q(), \"resource__tag\")\n        for tag in tags:\n            tag.chart = chart.get(tag.pk)\n            tag.latest_activity = latest_activity.get(tag.pk)\n\n        return tags\n\n    def get_tag_locales(self):\n        tag = self.tag\n\n        if tag is None:\n            return None\n\n        chart = self.chart(Q(resource__tag=self.tag), \"resource__tag\")\n        tag.chart = chart.get(tag.pk)\n        tag.locales = self.project.locales.all()\n\n        locale_chart = self.chart(Q(resource__tag=self.tag), \"locale\")\n        locale_latest_activity = self.latest_activity(\n            Q(resource__tag=self.tag), \"locale\"\n        )\n        for locale in tag.locales:\n            locale.chart = locale_chart.get(locale.pk)\n            locale.latest_activity = locale_latest_activity.get(locale.pk)\n\n        return tag\n\n    def chart(self, query, group_by):\n        trs = (\n            self.translated_resources.filter(query)\n            .values(group_by)\n            .annotate(\n                total_strings=Sum(\"resource__total_strings\"),\n                approved_strings=Sum(\"approved_strings\"),\n                pretranslated_strings=Sum(\"pretranslated_strings\"),\n                strings_with_errors=Sum(\"strings_with_errors\"),\n                strings_with_warnings=Sum(\"strings_with_warnings\"),\n                unreviewed_strings=Sum(\"unreviewed_strings\"),\n            )\n        )\n\n        return {\n            tr[group_by]: TranslatedResource.get_chart_dict(\n                TranslatedResource(**{key: tr[key] for key in list(tr.keys())[1:]})\n            )\n            for tr in trs\n        }\n\n    def latest_activity(self, query, group_by):\n        latest_activity = {}\n        dates = {}\n        translations = Translation.objects.none()\n\n        trs = (\n            self.translated_resources.exclude(latest_translation__isnull=True)\n            .filter(query)\n            .values(group_by)\n            .annotate(\n                date=Max(\"latest_translation__date\"),\n                approved_date=Max(\"latest_translation__approved_date\"),\n            )\n        )\n\n        for tr in trs:\n            date = max(tr[\"date\"], tr[\"approved_date\"] or tr[\"date\"])\n            dates[date] = tr[group_by]\n            prefix = \"entity__\" if group_by == \"resource__tag\" else \"\"\n\n            # Find translations with matching date and tag/locale\n            translations |= Translation.objects.filter(\n                Q(**{\"date\": date, f\"{prefix}{group_by}\": tr[group_by]})\n            ).prefetch_related(\"user\", \"approved_user\")\n\n        for t in translations:\n            key = dates[t.latest_activity[\"date\"]]\n            latest_activity[key] = t.latest_activity\n\n        return latest_activity\n\n    @property\n    def translated_resources(self):\n        trs = TranslatedResource.objects\n\n        if self.project is not None:\n            trs = trs.filter(resource__project=self.project)\n\n        if self.locale is not None:\n            trs = trs.filter(locale=self.locale)\n\n        return trs\n", "path": "pontoon/tags/utils.py"}]}