prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Don't overwrite creator when saving jobs
  Since we can provide view and editing permissions to other users (e.g. admins) with row-level permissions we should stop overwriting the creator on every save of a scheduled Spark job since it would prevent an effective trail of ownership and has in the past led to inconsistencies when updating jobs by an admin.
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `atmo/forms/mixins.py`
  Content:
  ```
  1 # This Source Code Form is subject to the terms of the Mozilla Public
  2 # License, v. 2.0. If a copy of the MPL was not distributed with this
  3 # file, you can obtain one at http://mozilla.org/MPL/2.0/.
  4 import uuid
  5 from collections import OrderedDict
  6 
  7 from django import forms
  8 
  9 from .cache import CachedFileCache
  10 from .fields import CachedFileField
  11 from .widgets import CachedFileHiddenInput
  12 
  13 
  14 class AutoClassFormMixin:
  15     """
  16     A form mixin that adds the 'form-control' to all field widgets
  17     automatically
  18     """
  19     class_names = {
  20         'form-control': {
  21             'excluded_widgets': ['file'],
  22         }
  23     }
  24 
  25     def __init__(self, *args, **kwargs):
  26         super().__init__(*args, **kwargs)
  27         for field in list(self.fields.values()):
  28             classes = field.widget.attrs.get('class', '').split(' ')
  29             for class_name, options in list(self.class_names.items()):
  30                 if class_name in classes:
  31                     continue
  32                 excluded_widgets = options.get('excluded_widgets', [])
  33                 if (hasattr(field.widget, 'input_type') and
  34                         field.widget.input_type in excluded_widgets):
  35                     continue
  36                 field.widget.attrs['class'] = ' '.join([class_name] + classes)
  37 
  38 
  39 class CreatedByModelFormMixin(forms.ModelForm):
  40     """
  41     Custom Django form mixin that takes a user object and if the provided
  42     model form instance has a primary key checks if the given user
  43     matches the 'created_by' field.
  44     """
  45     def __init__(self, user, *args, **kwargs):
  46         self.created_by = user
  47         super().__init__(*args, **kwargs)
  48 
  49     def save(self, commit=True):
  50         # create the object without committing, since we haven't
  51         # set the required created_by field yet
  52         obj = super().save(commit=False)
  53 
  54         # set the field to the user that created the object
  55         obj.created_by = self.created_by
  56 
  57         if commit:
  58             # actually start the real object, and return the model object
  59             obj.save()
  60         return obj
  61 
  62     def clean(self):
  63         """
  64         only allow deleting clusters that one created
  65         """
  66         super().clean()
  67         if self.instance.id and self.created_by != self.instance.created_by:
  68             raise forms.ValidationError(
  69                 'Access denied to the data of another user'
  70             )
  71 
  72 
  73 class CachedFileModelFormMixin(forms.ModelForm):
  74     """
  75     A model form mixin that automatically adds additional hidden form fields
  76     to store a random value to be used as the cache key for caching FileField
  77     files on submission. That is needed to prevent having to reselect files
  78     over and over again when form submission fails for the fields other than
  79     the file fields.
  80     """
  81     def __init__(self, *args, **kwargs):
  82         super().__init__(*args, **kwargs)
  83         self.cache = CachedFileCache()
  84         self.cached_filefields = OrderedDict()
  85         self.required_filefields = []
  86 
  87         field_order = []
  88         for name, field in list(self.fields.items()):
  89             # add any found field to the list of order items
  90             field_order.append(name)
  91 
  92             # in case it's a file input
  93             if isinstance(field, CachedFileField):
  94                 # we'll use this later in the clean and save step
  95                 self.cached_filefields[name] = field
  96 
  97                 # store the field that are required so we can validate
  98                 # them optionally in our clean method
  99                 if field.real_required:
  100                     self.required_filefields.append(name)
  101 
  102                 # get the name of the cache key field
  103                 cachekey_input_name = self.cachekey_input_name(name)
  104                 field_order.append(cachekey_input_name)
  105 
  106                 # add the cache key field
  107                 self.fields[cachekey_input_name] = forms.CharField(
  108                     max_length=32,
  109                     widget=CachedFileHiddenInput(),
  110                     initial=uuid.uuid4().hex
  111                 )
  112 
  113         self.order_fields(field_order)
  114 
  115     def cachekey_input_name(self, name):
  116         return name + '-cache'
  117 
  118     def cachekey_input_data(self, field):
  119         name = self.cachekey_input_name(field)
  120         return self.cleaned_data[name]
  121 
  122     def save(self, *args, **kwargs):
  123         # on save get rid of the cache keys
  124         for name in self.cached_filefields:
  125             self.cache.remove(self.cachekey_input_data(name))
  126         return super().save(*args, **kwargs)
  127 
  128     def clean(self):
  129         for field_name in self.cached_filefields:
  130             # get the name of the cache key field name and its value
  131             cache_key = self.cachekey_input_data(field_name)
  132 
  133             # check form data if the file field was submitted
  134             submitted_file = self.cleaned_data.get(field_name)
  135             if submitted_file is None:
  136                 # if not, check the cache and update the cleaned data
  137                 cached_file = self.cache.retrieve(cache_key, field_name)
  138                 if cached_file is None:
  139                     # raise a required validation error if nothing was found
  140                     if field_name in self.required_filefields:
  141                         field = self.cached_filefields[field_name]
  142                         self.add_error(
  143                             field_name,
  144                             forms.ValidationError(
  145                                 field.error_messages['required'],
  146                                 code='required'
  147                             )
  148                         )
  149                 else:
  150                     self.cleaned_data[field_name] = cached_file
  151             else:
  152                 # or store the submitted file for later use (or reset after saving)
  153                 self.cache.store(cache_key, submitted_file)
  154
  ```
  --- 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/atmo/forms/mixins.py b/atmo/forms/mixins.py
  --- a/atmo/forms/mixins.py
  +++ b/atmo/forms/mixins.py
  @@ -5,6 +5,7 @@
   from collections import OrderedDict
   
   from django import forms
  +from django.contrib.auth.models import User
   
   from .cache import CachedFileCache
   from .fields import CachedFileField
  @@ -52,7 +53,10 @@
           obj = super().save(commit=False)
   
           # set the field to the user that created the object
  -        obj.created_by = self.created_by
  +        try:
  +            obj.created_by
  +        except User.DoesNotExist:
  +            obj.created_by = self.created_by
   
           if commit:
               # actually start the real object, and return the model object
  
verification_info: {"golden_diff": "diff --git a/atmo/forms/mixins.py b/atmo/forms/mixins.py\n--- a/atmo/forms/mixins.py\n+++ b/atmo/forms/mixins.py\n@@ -5,6 +5,7 @@\n from collections import OrderedDict\n \n from django import forms\n+from django.contrib.auth.models import User\n \n from .cache import CachedFileCache\n from .fields import CachedFileField\n@@ -52,7 +53,10 @@\n         obj = super().save(commit=False)\n \n         # set the field to the user that created the object\n-        obj.created_by = self.created_by\n+        try:\n+            obj.created_by\n+        except User.DoesNotExist:\n+            obj.created_by = self.created_by\n \n         if commit:\n             # actually start the real object, and return the model object\n", "issue": "Don't overwrite creator when saving jobs\nSince we can provide view and editing permissions to other users (e.g. admins) with row-level permissions we should stop overwriting the creator on every save of a scheduled Spark job since it would prevent an effective trail of ownership and has in the past led to inconsistencies when updating jobs by an admin.\n", "before_files": [{"content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, you can obtain one at http://mozilla.org/MPL/2.0/.\nimport uuid\nfrom collections import OrderedDict\n\nfrom django import forms\n\nfrom .cache import CachedFileCache\nfrom .fields import CachedFileField\nfrom .widgets import CachedFileHiddenInput\n\n\nclass AutoClassFormMixin:\n    \"\"\"\n    A form mixin that adds the 'form-control' to all field widgets\n    automatically\n    \"\"\"\n    class_names = {\n        'form-control': {\n            'excluded_widgets': ['file'],\n        }\n    }\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        for field in list(self.fields.values()):\n            classes = field.widget.attrs.get('class', '').split(' ')\n            for class_name, options in list(self.class_names.items()):\n                if class_name in classes:\n                    continue\n                excluded_widgets = options.get('excluded_widgets', [])\n                if (hasattr(field.widget, 'input_type') and\n                        field.widget.input_type in excluded_widgets):\n                    continue\n                field.widget.attrs['class'] = ' '.join([class_name] + classes)\n\n\nclass CreatedByModelFormMixin(forms.ModelForm):\n    \"\"\"\n    Custom Django form mixin that takes a user object and if the provided\n    model form instance has a primary key checks if the given user\n    matches the 'created_by' field.\n    \"\"\"\n    def __init__(self, user, *args, **kwargs):\n        self.created_by = user\n        super().__init__(*args, **kwargs)\n\n    def save(self, commit=True):\n        # create the object without committing, since we haven't\n        # set the required created_by field yet\n        obj = super().save(commit=False)\n\n        # set the field to the user that created the object\n        obj.created_by = self.created_by\n\n        if commit:\n            # actually start the real object, and return the model object\n            obj.save()\n        return obj\n\n    def clean(self):\n        \"\"\"\n        only allow deleting clusters that one created\n        \"\"\"\n        super().clean()\n        if self.instance.id and self.created_by != self.instance.created_by:\n            raise forms.ValidationError(\n                'Access denied to the data of another user'\n            )\n\n\nclass CachedFileModelFormMixin(forms.ModelForm):\n    \"\"\"\n    A model form mixin that automatically adds additional hidden form fields\n    to store a random value to be used as the cache key for caching FileField\n    files on submission. That is needed to prevent having to reselect files\n    over and over again when form submission fails for the fields other than\n    the file fields.\n    \"\"\"\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.cache = CachedFileCache()\n        self.cached_filefields = OrderedDict()\n        self.required_filefields = []\n\n        field_order = []\n        for name, field in list(self.fields.items()):\n            # add any found field to the list of order items\n            field_order.append(name)\n\n            # in case it's a file input\n            if isinstance(field, CachedFileField):\n                # we'll use this later in the clean and save step\n                self.cached_filefields[name] = field\n\n                # store the field that are required so we can validate\n                # them optionally in our clean method\n                if field.real_required:\n                    self.required_filefields.append(name)\n\n                # get the name of the cache key field\n                cachekey_input_name = self.cachekey_input_name(name)\n                field_order.append(cachekey_input_name)\n\n                # add the cache key field\n                self.fields[cachekey_input_name] = forms.CharField(\n                    max_length=32,\n                    widget=CachedFileHiddenInput(),\n                    initial=uuid.uuid4().hex\n                )\n\n        self.order_fields(field_order)\n\n    def cachekey_input_name(self, name):\n        return name + '-cache'\n\n    def cachekey_input_data(self, field):\n        name = self.cachekey_input_name(field)\n        return self.cleaned_data[name]\n\n    def save(self, *args, **kwargs):\n        # on save get rid of the cache keys\n        for name in self.cached_filefields:\n            self.cache.remove(self.cachekey_input_data(name))\n        return super().save(*args, **kwargs)\n\n    def clean(self):\n        for field_name in self.cached_filefields:\n            # get the name of the cache key field name and its value\n            cache_key = self.cachekey_input_data(field_name)\n\n            # check form data if the file field was submitted\n            submitted_file = self.cleaned_data.get(field_name)\n            if submitted_file is None:\n                # if not, check the cache and update the cleaned data\n                cached_file = self.cache.retrieve(cache_key, field_name)\n                if cached_file is None:\n                    # raise a required validation error if nothing was found\n                    if field_name in self.required_filefields:\n                        field = self.cached_filefields[field_name]\n                        self.add_error(\n                            field_name,\n                            forms.ValidationError(\n                                field.error_messages['required'],\n                                code='required'\n                            )\n                        )\n                else:\n                    self.cleaned_data[field_name] = cached_file\n            else:\n                # or store the submitted file for later use (or reset after saving)\n                self.cache.store(cache_key, submitted_file)\n", "path": "atmo/forms/mixins.py"}], "after_files": [{"content": "# This Source Code Form is subject to the terms of the Mozilla Public\n# License, v. 2.0. If a copy of the MPL was not distributed with this\n# file, you can obtain one at http://mozilla.org/MPL/2.0/.\nimport uuid\nfrom collections import OrderedDict\n\nfrom django import forms\nfrom django.contrib.auth.models import User\n\nfrom .cache import CachedFileCache\nfrom .fields import CachedFileField\nfrom .widgets import CachedFileHiddenInput\n\n\nclass AutoClassFormMixin:\n    \"\"\"\n    A form mixin that adds the 'form-control' to all field widgets\n    automatically\n    \"\"\"\n    class_names = {\n        'form-control': {\n            'excluded_widgets': ['file'],\n        }\n    }\n\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        for field in list(self.fields.values()):\n            classes = field.widget.attrs.get('class', '').split(' ')\n            for class_name, options in list(self.class_names.items()):\n                if class_name in classes:\n                    continue\n                excluded_widgets = options.get('excluded_widgets', [])\n                if (hasattr(field.widget, 'input_type') and\n                        field.widget.input_type in excluded_widgets):\n                    continue\n                field.widget.attrs['class'] = ' '.join([class_name] + classes)\n\n\nclass CreatedByModelFormMixin(forms.ModelForm):\n    \"\"\"\n    Custom Django form mixin that takes a user object and if the provided\n    model form instance has a primary key checks if the given user\n    matches the 'created_by' field.\n    \"\"\"\n    def __init__(self, user, *args, **kwargs):\n        self.created_by = user\n        super().__init__(*args, **kwargs)\n\n    def save(self, commit=True):\n        # create the object without committing, since we haven't\n        # set the required created_by field yet\n        obj = super().save(commit=False)\n\n        # set the field to the user that created the object\n        try:\n            obj.created_by\n        except User.DoesNotExist:\n            obj.created_by = self.created_by\n\n        if commit:\n            # actually start the real object, and return the model object\n            obj.save()\n        return obj\n\n    def clean(self):\n        \"\"\"\n        only allow deleting clusters that one created\n        \"\"\"\n        super().clean()\n        if self.instance.id and self.created_by != self.instance.created_by:\n            raise forms.ValidationError(\n                'Access denied to the data of another user'\n            )\n\n\nclass CachedFileModelFormMixin(forms.ModelForm):\n    \"\"\"\n    A model form mixin that automatically adds additional hidden form fields\n    to store a random value to be used as the cache key for caching FileField\n    files on submission. That is needed to prevent having to reselect files\n    over and over again when form submission fails for the fields other than\n    the file fields.\n    \"\"\"\n    def __init__(self, *args, **kwargs):\n        super().__init__(*args, **kwargs)\n        self.cache = CachedFileCache()\n        self.cached_filefields = OrderedDict()\n        self.required_filefields = []\n\n        field_order = []\n        for name, field in list(self.fields.items()):\n            # add any found field to the list of order items\n            field_order.append(name)\n\n            # in case it's a file input\n            if isinstance(field, CachedFileField):\n                # we'll use this later in the clean and save step\n                self.cached_filefields[name] = field\n\n                # store the field that are required so we can validate\n                # them optionally in our clean method\n                if field.real_required:\n                    self.required_filefields.append(name)\n\n                # get the name of the cache key field\n                cachekey_input_name = self.cachekey_input_name(name)\n                field_order.append(cachekey_input_name)\n\n                # add the cache key field\n                self.fields[cachekey_input_name] = forms.CharField(\n                    max_length=32,\n                    widget=CachedFileHiddenInput(),\n                    initial=uuid.uuid4().hex\n                )\n\n        self.order_fields(field_order)\n\n    def cachekey_input_name(self, name):\n        return name + '-cache'\n\n    def cachekey_input_data(self, field):\n        name = self.cachekey_input_name(field)\n        return self.cleaned_data[name]\n\n    def save(self, *args, **kwargs):\n        # on save get rid of the cache keys\n        for name in self.cached_filefields:\n            self.cache.remove(self.cachekey_input_data(name))\n        return super().save(*args, **kwargs)\n\n    def clean(self):\n        for field_name in self.cached_filefields:\n            # get the name of the cache key field name and its value\n            cache_key = self.cachekey_input_data(field_name)\n\n            # check form data if the file field was submitted\n            submitted_file = self.cleaned_data.get(field_name)\n            if submitted_file is None:\n                # if not, check the cache and update the cleaned data\n                cached_file = self.cache.retrieve(cache_key, field_name)\n                if cached_file is None:\n                    # raise a required validation error if nothing was found\n                    if field_name in self.required_filefields:\n                        field = self.cached_filefields[field_name]\n                        self.add_error(\n                            field_name,\n                            forms.ValidationError(\n                                field.error_messages['required'],\n                                code='required'\n                            )\n                        )\n                else:\n                    self.cleaned_data[field_name] = cached_file\n            else:\n                # or store the submitted file for later use (or reset after saving)\n                self.cache.store(cache_key, submitted_file)\n", "path": "atmo/forms/mixins.py"}]}