prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  single module project without timeline is missing any discription
  my single module project [https://meinberlin-dev.liqd.net/projects/schillerkasse-ihre-kiezkasse-fur-den-schillerkiez/](url) which is module Kiezkasse should have a phase information. It is currently running.
  
  ![Bildschirmfoto 2019-07-05 um 14 17 04](https://user-images.githubusercontent.com/35491681/60721991-e1acfa80-9f2f-11e9-950f-cf28dd3e7645.png)
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `meinberlin/apps/contrib/mixins.py`
  Content:
  ```
  1 from django import forms
  2 from django.db.models import Max
  3 from django.db.models import Min
  4 from django.db.models import Q
  5 from django.urls import resolve
  6 from django.utils.translation import ugettext_lazy as _
  7 from django.views import generic
  8 
  9 from adhocracy4.modules.models import Module
  10 
  11 RIGHT_OF_USE_LABEL = _('I hereby confirm that the copyrights for this '
  12                        'photo are with me or that I have received '
  13                        'rights of use from the author. I also confirm '
  14                        'that the privacy rights of depicted third persons '
  15                        'are not violated. ')
  16 
  17 
  18 class DynamicChoicesMixin(object):
  19     """Dynamic choices mixin.
  20 
  21     Add callable functionality to filters that support the ``choices``
  22     argument. If the ``choices`` is callable, then it **must** accept the
  23     ``view`` object as a single argument.
  24     The ``view`` object may be None if the parent FilterSet is not class based.
  25 
  26     This is useful for dymanic ``choices`` determined properties on the
  27     ``view`` object.
  28     """
  29 
  30     def __init__(self, *args, **kwargs):
  31         self.choices = kwargs.pop('choices')
  32         super().__init__(*args, **kwargs)
  33 
  34     def get_choices(self, view):
  35         choices = self.choices
  36 
  37         if callable(choices):
  38             return choices(view)
  39         return choices
  40 
  41     @property
  42     def field(self):
  43         choices = self.get_choices(getattr(self, 'view', None))
  44 
  45         if choices is not None:
  46             self.extra['choices'] = choices
  47 
  48         return super(DynamicChoicesMixin, self).field
  49 
  50 
  51 class ImageRightOfUseMixin(forms.ModelForm):
  52     right_of_use = forms.BooleanField(required=False, label=RIGHT_OF_USE_LABEL)
  53 
  54     def __init__(self, *args, **kwargs):
  55         super().__init__(*args, **kwargs)
  56         if self.instance.image:
  57             self.initial['right_of_use'] = True
  58 
  59     def clean(self):
  60         cleaned_data = super().clean()
  61         image = cleaned_data.get('image')
  62         right_of_use = cleaned_data.get('right_of_use')
  63         if image and not right_of_use:
  64             self.add_error('right_of_use',
  65                            _("You want to upload an image. "
  66                              "Please check that you have the "
  67                              "right of use for the image."))
  68 
  69 
  70 class ModuleClusterMixin:
  71 
  72     def _get_module_dict(self, count, start_date, end_date):
  73         return {
  74             'count': count,
  75             'date': start_date,
  76             'end_date': end_date,
  77             'modules': []
  78         }
  79 
  80     def get_module_clusters(self, modules):
  81         modules = modules\
  82             .exclude(Q(start_date=None) | Q(end_date=None))
  83         clusters = []
  84         try:
  85             start_date = modules.first().start_date
  86             end_date = modules.first().end_date
  87             count = 1
  88             first_cluster = self._get_module_dict(
  89                 count, start_date, end_date)
  90             first_cluster['modules'].append(modules.first())
  91             current_cluster = first_cluster
  92             clusters.append(first_cluster)
  93 
  94             for module in modules[1:]:
  95                 if module.start_date > end_date:
  96                     start_date = module.start_date
  97                     end_date = module.end_date
  98                     count += 1
  99                     next_cluster = self._get_module_dict(
  100                         count, start_date, end_date)
  101                     next_cluster['modules'].append(module)
  102                     current_cluster = next_cluster
  103                     clusters.append(next_cluster)
  104                 else:
  105                     current_cluster['modules'].append(module)
  106                     if module.end_date > end_date:
  107                         end_date = module.end_date
  108                         current_cluster['end_date'] = end_date
  109         except AttributeError:
  110             return clusters
  111         if len(clusters) == 1:
  112             clusters[0]['title'] = _('Online Participation')
  113         return clusters
  114 
  115 
  116 class DisplayProjectOrModuleMixin(generic.base.ContextMixin,
  117                                   ModuleClusterMixin):
  118 
  119     def module_clusters(self, modules):
  120         return super().get_module_clusters(modules)
  121 
  122     @property
  123     def url_name(self):
  124         return resolve(self.request.path_info).url_name
  125 
  126     @property
  127     def other_modules(self):
  128         modules = Module.objects.filter(project=self.project)\
  129             .annotate(start_date=Min('phase__start_date'))\
  130             .annotate(end_date=Max('phase__end_date'))\
  131             .order_by('start_date')
  132 
  133         for cluster in self.module_clusters(modules):
  134             if self.module in cluster['modules']:
  135                 idx = cluster['modules'].index(self.module)
  136                 modules = cluster['modules']
  137                 return modules, idx
  138         return []
  139 
  140     @property
  141     def extends(self):
  142         if self.url_name == 'module-detail':
  143             return 'a4modules/module_detail.html'
  144         return 'meinberlin_projects/project_detail.html'
  145 
  146     def get_context_data(self, **kwargs):
  147         context = super().get_context_data(**kwargs)
  148         context['url_name'] = self.url_name
  149         context['extends'] = self.extends
  150         if self.url_name == 'module-detail':
  151             cluster, idx = self.other_modules
  152             next_module = None
  153             previous_module = None
  154             try:
  155                 next_module = cluster[idx + 1]
  156             except IndexError:
  157                 pass
  158             try:
  159                 previous_module = cluster[idx - 1]
  160             except IndexError:
  161                 pass
  162             context['other_modules'] = cluster
  163             context['index'] = idx + 1
  164             context['next'] = next_module
  165             context['previous'] = previous_module
  166         return context
  167
  ```
  --- 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()
  
  ```
  
golden_diff: diff --git a/meinberlin/apps/contrib/mixins.py b/meinberlin/apps/contrib/mixins.py
  --- a/meinberlin/apps/contrib/mixins.py
  +++ b/meinberlin/apps/contrib/mixins.py
  @@ -156,7 +156,8 @@
               except IndexError:
                   pass
               try:
  -                previous_module = cluster[idx - 1]
  +                if idx > 0:
  +                    previous_module = cluster[idx - 1]
               except IndexError:
                   pass
               context['other_modules'] = cluster
  
verification_info: {"golden_diff": "diff --git a/meinberlin/apps/contrib/mixins.py b/meinberlin/apps/contrib/mixins.py\n--- a/meinberlin/apps/contrib/mixins.py\n+++ b/meinberlin/apps/contrib/mixins.py\n@@ -156,7 +156,8 @@\n             except IndexError:\n                 pass\n             try:\n-                previous_module = cluster[idx - 1]\n+                if idx > 0:\n+                    previous_module = cluster[idx - 1]\n             except IndexError:\n                 pass\n             context['other_modules'] = cluster\n", "issue": "single module project without timeline is missing any discription\nmy single module project [https://meinberlin-dev.liqd.net/projects/schillerkasse-ihre-kiezkasse-fur-den-schillerkiez/](url) which is module Kiezkasse should have a phase information. It is currently running.\r\n\r\n![Bildschirmfoto 2019-07-05 um 14 17 04](https://user-images.githubusercontent.com/35491681/60721991-e1acfa80-9f2f-11e9-950f-cf28dd3e7645.png)\r\n\n", "before_files": [{"content": "from django import forms\nfrom django.db.models import Max\nfrom django.db.models import Min\nfrom django.db.models import Q\nfrom django.urls import resolve\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.views import generic\n\nfrom adhocracy4.modules.models import Module\n\nRIGHT_OF_USE_LABEL = _('I hereby confirm that the copyrights for this '\n                       'photo are with me or that I have received '\n                       'rights of use from the author. I also confirm '\n                       'that the privacy rights of depicted third persons '\n                       'are not violated. ')\n\n\nclass DynamicChoicesMixin(object):\n    \"\"\"Dynamic choices mixin.\n\n    Add callable functionality to filters that support the ``choices``\n    argument. If the ``choices`` is callable, then it **must** accept the\n    ``view`` object as a single argument.\n    The ``view`` object may be None if the parent FilterSet is not class based.\n\n    This is useful for dymanic ``choices`` determined properties on the\n    ``view`` object.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.choices = kwargs.pop('choices')\n        super().__init__(*args, **kwargs)\n\n    def get_choices(self, view):\n        choices = self.choices\n\n        if callable(choices):\n            return choices(view)\n        return choices\n\n    @property\n    def field(self):\n        choices = self.get_choices(getattr(self, 'view', None))\n\n        if choices is not None:\n            self.extra['choices'] = choices\n\n        return super(DynamicChoicesMixin, self).field\n\n\nclass ImageRightOfUseMixin(forms.ModelForm):\n    right_of_use = forms.BooleanField(required=False, label=RIGHT_OF_USE_LABEL)\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self.instance.image:\n            self.initial['right_of_use'] = True\n\n    def clean(self):\n        cleaned_data = super().clean()\n        image = cleaned_data.get('image')\n        right_of_use = cleaned_data.get('right_of_use')\n        if image and not right_of_use:\n            self.add_error('right_of_use',\n                           _(\"You want to upload an image. \"\n                             \"Please check that you have the \"\n                             \"right of use for the image.\"))\n\n\nclass ModuleClusterMixin:\n\n    def _get_module_dict(self, count, start_date, end_date):\n        return {\n            'count': count,\n            'date': start_date,\n            'end_date': end_date,\n            'modules': []\n        }\n\n    def get_module_clusters(self, modules):\n        modules = modules\\\n            .exclude(Q(start_date=None) | Q(end_date=None))\n        clusters = []\n        try:\n            start_date = modules.first().start_date\n            end_date = modules.first().end_date\n            count = 1\n            first_cluster = self._get_module_dict(\n                count, start_date, end_date)\n            first_cluster['modules'].append(modules.first())\n            current_cluster = first_cluster\n            clusters.append(first_cluster)\n\n            for module in modules[1:]:\n                if module.start_date > end_date:\n                    start_date = module.start_date\n                    end_date = module.end_date\n                    count += 1\n                    next_cluster = self._get_module_dict(\n                        count, start_date, end_date)\n                    next_cluster['modules'].append(module)\n                    current_cluster = next_cluster\n                    clusters.append(next_cluster)\n                else:\n                    current_cluster['modules'].append(module)\n                    if module.end_date > end_date:\n                        end_date = module.end_date\n                        current_cluster['end_date'] = end_date\n        except AttributeError:\n            return clusters\n        if len(clusters) == 1:\n            clusters[0]['title'] = _('Online Participation')\n        return clusters\n\n\nclass DisplayProjectOrModuleMixin(generic.base.ContextMixin,\n                                  ModuleClusterMixin):\n\n    def module_clusters(self, modules):\n        return super().get_module_clusters(modules)\n\n    @property\n    def url_name(self):\n        return resolve(self.request.path_info).url_name\n\n    @property\n    def other_modules(self):\n        modules = Module.objects.filter(project=self.project)\\\n            .annotate(start_date=Min('phase__start_date'))\\\n            .annotate(end_date=Max('phase__end_date'))\\\n            .order_by('start_date')\n\n        for cluster in self.module_clusters(modules):\n            if self.module in cluster['modules']:\n                idx = cluster['modules'].index(self.module)\n                modules = cluster['modules']\n                return modules, idx\n        return []\n\n    @property\n    def extends(self):\n        if self.url_name == 'module-detail':\n            return 'a4modules/module_detail.html'\n        return 'meinberlin_projects/project_detail.html'\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['url_name'] = self.url_name\n        context['extends'] = self.extends\n        if self.url_name == 'module-detail':\n            cluster, idx = self.other_modules\n            next_module = None\n            previous_module = None\n            try:\n                next_module = cluster[idx + 1]\n            except IndexError:\n                pass\n            try:\n                previous_module = cluster[idx - 1]\n            except IndexError:\n                pass\n            context['other_modules'] = cluster\n            context['index'] = idx + 1\n            context['next'] = next_module\n            context['previous'] = previous_module\n        return context\n", "path": "meinberlin/apps/contrib/mixins.py"}], "after_files": [{"content": "from django import forms\nfrom django.db.models import Max\nfrom django.db.models import Min\nfrom django.db.models import Q\nfrom django.urls import resolve\nfrom django.utils.translation import ugettext_lazy as _\nfrom django.views import generic\n\nfrom adhocracy4.modules.models import Module\n\nRIGHT_OF_USE_LABEL = _('I hereby confirm that the copyrights for this '\n                       'photo are with me or that I have received '\n                       'rights of use from the author. I also confirm '\n                       'that the privacy rights of depicted third persons '\n                       'are not violated. ')\n\n\nclass DynamicChoicesMixin(object):\n    \"\"\"Dynamic choices mixin.\n\n    Add callable functionality to filters that support the ``choices``\n    argument. If the ``choices`` is callable, then it **must** accept the\n    ``view`` object as a single argument.\n    The ``view`` object may be None if the parent FilterSet is not class based.\n\n    This is useful for dymanic ``choices`` determined properties on the\n    ``view`` object.\n    \"\"\"\n\n    def __init__(self, *args, **kwargs):\n        self.choices = kwargs.pop('choices')\n        super().__init__(*args, **kwargs)\n\n    def get_choices(self, view):\n        choices = self.choices\n\n        if callable(choices):\n            return choices(view)\n        return choices\n\n    @property\n    def field(self):\n        choices = self.get_choices(getattr(self, 'view', None))\n\n        if choices is not None:\n            self.extra['choices'] = choices\n\n        return super(DynamicChoicesMixin, self).field\n\n\nclass ImageRightOfUseMixin(forms.ModelForm):\n    right_of_use = forms.BooleanField(required=False, label=RIGHT_OF_USE_LABEL)\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        if self.instance.image:\n            self.initial['right_of_use'] = True\n\n    def clean(self):\n        cleaned_data = super().clean()\n        image = cleaned_data.get('image')\n        right_of_use = cleaned_data.get('right_of_use')\n        if image and not right_of_use:\n            self.add_error('right_of_use',\n                           _(\"You want to upload an image. \"\n                             \"Please check that you have the \"\n                             \"right of use for the image.\"))\n\n\nclass ModuleClusterMixin:\n\n    def _get_module_dict(self, count, start_date, end_date):\n        return {\n            'count': count,\n            'date': start_date,\n            'end_date': end_date,\n            'modules': []\n        }\n\n    def get_module_clusters(self, modules):\n        modules = modules\\\n            .exclude(Q(start_date=None) | Q(end_date=None))\n        clusters = []\n        try:\n            start_date = modules.first().start_date\n            end_date = modules.first().end_date\n            count = 1\n            first_cluster = self._get_module_dict(\n                count, start_date, end_date)\n            first_cluster['modules'].append(modules.first())\n            current_cluster = first_cluster\n            clusters.append(first_cluster)\n\n            for module in modules[1:]:\n                if module.start_date > end_date:\n                    start_date = module.start_date\n                    end_date = module.end_date\n                    count += 1\n                    next_cluster = self._get_module_dict(\n                        count, start_date, end_date)\n                    next_cluster['modules'].append(module)\n                    current_cluster = next_cluster\n                    clusters.append(next_cluster)\n                else:\n                    current_cluster['modules'].append(module)\n                    if module.end_date > end_date:\n                        end_date = module.end_date\n                        current_cluster['end_date'] = end_date\n        except AttributeError:\n            return clusters\n        if len(clusters) == 1:\n            clusters[0]['title'] = _('Online Participation')\n        return clusters\n\n\nclass DisplayProjectOrModuleMixin(generic.base.ContextMixin,\n                                  ModuleClusterMixin):\n\n    def module_clusters(self, modules):\n        return super().get_module_clusters(modules)\n\n    @property\n    def url_name(self):\n        return resolve(self.request.path_info).url_name\n\n    @property\n    def other_modules(self):\n        modules = Module.objects.filter(project=self.project)\\\n            .annotate(start_date=Min('phase__start_date'))\\\n            .annotate(end_date=Max('phase__end_date'))\\\n            .order_by('start_date')\n\n        for cluster in self.module_clusters(modules):\n            if self.module in cluster['modules']:\n                idx = cluster['modules'].index(self.module)\n                modules = cluster['modules']\n                return modules, idx\n        return []\n\n    @property\n    def extends(self):\n        if self.url_name == 'module-detail':\n            return 'a4modules/module_detail.html'\n        return 'meinberlin_projects/project_detail.html'\n\n    def get_context_data(self, **kwargs):\n        context = super().get_context_data(**kwargs)\n        context['url_name'] = self.url_name\n        context['extends'] = self.extends\n        if self.url_name == 'module-detail':\n            cluster, idx = self.other_modules\n            next_module = None\n            previous_module = None\n            try:\n                next_module = cluster[idx + 1]\n            except IndexError:\n                pass\n            try:\n                if idx > 0:\n                    previous_module = cluster[idx - 1]\n            except IndexError:\n                pass\n            context['other_modules'] = cluster\n            context['index'] = idx + 1\n            context['next'] = next_module\n            context['previous'] = previous_module\n        return context\n", "path": "meinberlin/apps/contrib/mixins.py"}]}