prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  Append of chunked upload processes raw data
  **Version**
  Please provide the versions of the pulpcore and plugin packages in use, and how they are installed.  If you are using Pulp via Katello, please provide the Katello version.
  
  **Describe the bug**
  A clear and concise description of what the bug is.
  
  **To Reproduce**
  Steps to reproduce the behavior:
  
  **Expected behavior**
  A clear and concise description of what you expected to happen.
  
  **Additional context**
  Add any other context about the problem here.  Please provide links to any previous discussions via Discourse or Bugzilla.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `pulpcore/app/models/upload.py`
  Content:
  ```
  1 import hashlib
  2 import os
  3 
  4 from django.core.files.base import ContentFile
  5 from django.db import models
  6 from django.db.models.signals import post_delete
  7 from django.dispatch import receiver
  8 from rest_framework import serializers
  9 
  10 from pulpcore.app.models import BaseModel, fields, storage
  11 
  12 
  13 class Upload(BaseModel):
  14     """
  15     A chunked upload. Stores chunks until used to create an artifact, etc.
  16 
  17     Fields:
  18 
  19         size (models.BigIntegerField): The size of the file in bytes.
  20     """
  21 
  22     size = models.BigIntegerField()
  23 
  24     def append(self, chunk, offset, sha256=None):
  25         """
  26         Append a chunk to an upload.
  27 
  28         Args:
  29             chunk (File): Binary file to append to the upload file.
  30             offset (int): First byte position to write chunk to.
  31         """
  32         chunk_read = chunk.read()
  33         current_sha256 = hashlib.sha256(chunk_read).hexdigest()
  34         if sha256 and sha256 != current_sha256:
  35             raise serializers.ValidationError("Checksum does not match chunk upload.")
  36 
  37         upload_chunk = UploadChunk(upload=self, offset=offset, size=len(chunk))
  38         filename = os.path.basename(upload_chunk.storage_path(""))
  39         upload_chunk.file.save(filename, ContentFile(chunk_read))
  40 
  41 
  42 class UploadChunk(BaseModel):
  43     """
  44     A chunk for an uploaded file.
  45 
  46     Fields:
  47 
  48         file (fields.FileField): A file where the uploaded chunk is stored.
  49         upload (models.ForeignKey): Upload this chunk belongs to.
  50         offset (models.BigIntegerField): Start of the chunk in bytes.
  51         size (models.BigIntegerField): Size of the chunk in bytes.
  52     """
  53 
  54     def storage_path(self, name):
  55         """
  56         Callable used by FileField to determine where the uploaded file should be stored.
  57 
  58         Args:
  59             name (str): Original name of uploaded file. It is ignored by this method because the
  60                 pulp_id is used to determine a file path instead.
  61         """
  62         return storage.get_upload_chunk_file_path(self.pulp_id)
  63 
  64     file = fields.FileField(null=False, upload_to=storage_path, max_length=255)
  65     upload = models.ForeignKey(Upload, on_delete=models.CASCADE, related_name="chunks")
  66     offset = models.BigIntegerField()
  67     size = models.BigIntegerField()
  68 
  69 
  70 @receiver(post_delete, sender=UploadChunk)
  71 def upload_chunk_delete(instance, **kwargs):
  72     instance.file.delete(save=False)
  73
  ```
  --- 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/pulpcore/app/models/upload.py b/pulpcore/app/models/upload.py
  --- a/pulpcore/app/models/upload.py
  +++ b/pulpcore/app/models/upload.py
  @@ -1,6 +1,8 @@
   import hashlib
   import os
   
  +from gettext import gettext as _
  +
   from django.core.files.base import ContentFile
   from django.db import models
   from django.db.models.signals import post_delete
  @@ -26,17 +28,18 @@
           Append a chunk to an upload.
   
           Args:
  -            chunk (File): Binary file to append to the upload file.
  +            chunk (File): Binary data to append to the upload file.
               offset (int): First byte position to write chunk to.
           """
  -        chunk_read = chunk.read()
  -        current_sha256 = hashlib.sha256(chunk_read).hexdigest()
  -        if sha256 and sha256 != current_sha256:
  -            raise serializers.ValidationError("Checksum does not match chunk upload.")
  +        chunk = chunk.read()
  +        if sha256:
  +            current_sha256 = hashlib.sha256(chunk).hexdigest()
  +            if sha256 != current_sha256:
  +                raise serializers.ValidationError(_("Checksum does not match chunk upload."))
   
           upload_chunk = UploadChunk(upload=self, offset=offset, size=len(chunk))
           filename = os.path.basename(upload_chunk.storage_path(""))
  -        upload_chunk.file.save(filename, ContentFile(chunk_read))
  +        upload_chunk.file.save(filename, ContentFile(chunk))
   
   
   class UploadChunk(BaseModel):
  
verification_info: {"golden_diff": "diff --git a/pulpcore/app/models/upload.py b/pulpcore/app/models/upload.py\n--- a/pulpcore/app/models/upload.py\n+++ b/pulpcore/app/models/upload.py\n@@ -1,6 +1,8 @@\n import hashlib\n import os\n \n+from gettext import gettext as _\n+\n from django.core.files.base import ContentFile\n from django.db import models\n from django.db.models.signals import post_delete\n@@ -26,17 +28,18 @@\n         Append a chunk to an upload.\n \n         Args:\n-            chunk (File): Binary file to append to the upload file.\n+            chunk (File): Binary data to append to the upload file.\n             offset (int): First byte position to write chunk to.\n         \"\"\"\n-        chunk_read = chunk.read()\n-        current_sha256 = hashlib.sha256(chunk_read).hexdigest()\n-        if sha256 and sha256 != current_sha256:\n-            raise serializers.ValidationError(\"Checksum does not match chunk upload.\")\n+        chunk = chunk.read()\n+        if sha256:\n+            current_sha256 = hashlib.sha256(chunk).hexdigest()\n+            if sha256 != current_sha256:\n+                raise serializers.ValidationError(_(\"Checksum does not match chunk upload.\"))\n \n         upload_chunk = UploadChunk(upload=self, offset=offset, size=len(chunk))\n         filename = os.path.basename(upload_chunk.storage_path(\"\"))\n-        upload_chunk.file.save(filename, ContentFile(chunk_read))\n+        upload_chunk.file.save(filename, ContentFile(chunk))\n \n \n class UploadChunk(BaseModel):\n", "issue": "Append of chunked upload processes raw data\n**Version**\r\nPlease provide the versions of the pulpcore and plugin packages in use, and how they are installed.  If you are using Pulp via Katello, please provide the Katello version.\r\n\r\n**Describe the bug**\r\nA clear and concise description of what the bug is.\r\n\r\n**To Reproduce**\r\nSteps to reproduce the behavior:\r\n\r\n**Expected behavior**\r\nA clear and concise description of what you expected to happen.\r\n\r\n**Additional context**\r\nAdd any other context about the problem here.  Please provide links to any previous discussions via Discourse or Bugzilla.\r\n\n", "before_files": [{"content": "import hashlib\nimport os\n\nfrom django.core.files.base import ContentFile\nfrom django.db import models\nfrom django.db.models.signals import post_delete\nfrom django.dispatch import receiver\nfrom rest_framework import serializers\n\nfrom pulpcore.app.models import BaseModel, fields, storage\n\n\nclass Upload(BaseModel):\n    \"\"\"\n    A chunked upload. Stores chunks until used to create an artifact, etc.\n\n    Fields:\n\n        size (models.BigIntegerField): The size of the file in bytes.\n    \"\"\"\n\n    size = models.BigIntegerField()\n\n    def append(self, chunk, offset, sha256=None):\n        \"\"\"\n        Append a chunk to an upload.\n\n        Args:\n            chunk (File): Binary file to append to the upload file.\n            offset (int): First byte position to write chunk to.\n        \"\"\"\n        chunk_read = chunk.read()\n        current_sha256 = hashlib.sha256(chunk_read).hexdigest()\n        if sha256 and sha256 != current_sha256:\n            raise serializers.ValidationError(\"Checksum does not match chunk upload.\")\n\n        upload_chunk = UploadChunk(upload=self, offset=offset, size=len(chunk))\n        filename = os.path.basename(upload_chunk.storage_path(\"\"))\n        upload_chunk.file.save(filename, ContentFile(chunk_read))\n\n\nclass UploadChunk(BaseModel):\n    \"\"\"\n    A chunk for an uploaded file.\n\n    Fields:\n\n        file (fields.FileField): A file where the uploaded chunk is stored.\n        upload (models.ForeignKey): Upload this chunk belongs to.\n        offset (models.BigIntegerField): Start of the chunk in bytes.\n        size (models.BigIntegerField): Size of the chunk in bytes.\n    \"\"\"\n\n    def storage_path(self, name):\n        \"\"\"\n        Callable used by FileField to determine where the uploaded file should be stored.\n\n        Args:\n            name (str): Original name of uploaded file. It is ignored by this method because the\n                pulp_id is used to determine a file path instead.\n        \"\"\"\n        return storage.get_upload_chunk_file_path(self.pulp_id)\n\n    file = fields.FileField(null=False, upload_to=storage_path, max_length=255)\n    upload = models.ForeignKey(Upload, on_delete=models.CASCADE, related_name=\"chunks\")\n    offset = models.BigIntegerField()\n    size = models.BigIntegerField()\n\n\n@receiver(post_delete, sender=UploadChunk)\ndef upload_chunk_delete(instance, **kwargs):\n    instance.file.delete(save=False)\n", "path": "pulpcore/app/models/upload.py"}], "after_files": [{"content": "import hashlib\nimport os\n\nfrom gettext import gettext as _\n\nfrom django.core.files.base import ContentFile\nfrom django.db import models\nfrom django.db.models.signals import post_delete\nfrom django.dispatch import receiver\nfrom rest_framework import serializers\n\nfrom pulpcore.app.models import BaseModel, fields, storage\n\n\nclass Upload(BaseModel):\n    \"\"\"\n    A chunked upload. Stores chunks until used to create an artifact, etc.\n\n    Fields:\n\n        size (models.BigIntegerField): The size of the file in bytes.\n    \"\"\"\n\n    size = models.BigIntegerField()\n\n    def append(self, chunk, offset, sha256=None):\n        \"\"\"\n        Append a chunk to an upload.\n\n        Args:\n            chunk (File): Binary data to append to the upload file.\n            offset (int): First byte position to write chunk to.\n        \"\"\"\n        chunk = chunk.read()\n        if sha256:\n            current_sha256 = hashlib.sha256(chunk).hexdigest()\n            if sha256 != current_sha256:\n                raise serializers.ValidationError(_(\"Checksum does not match chunk upload.\"))\n\n        upload_chunk = UploadChunk(upload=self, offset=offset, size=len(chunk))\n        filename = os.path.basename(upload_chunk.storage_path(\"\"))\n        upload_chunk.file.save(filename, ContentFile(chunk))\n\n\nclass UploadChunk(BaseModel):\n    \"\"\"\n    A chunk for an uploaded file.\n\n    Fields:\n\n        file (fields.FileField): A file where the uploaded chunk is stored.\n        upload (models.ForeignKey): Upload this chunk belongs to.\n        offset (models.BigIntegerField): Start of the chunk in bytes.\n        size (models.BigIntegerField): Size of the chunk in bytes.\n    \"\"\"\n\n    def storage_path(self, name):\n        \"\"\"\n        Callable used by FileField to determine where the uploaded file should be stored.\n\n        Args:\n            name (str): Original name of uploaded file. It is ignored by this method because the\n                pulp_id is used to determine a file path instead.\n        \"\"\"\n        return storage.get_upload_chunk_file_path(self.pulp_id)\n\n    file = fields.FileField(null=False, upload_to=storage_path, max_length=255)\n    upload = models.ForeignKey(Upload, on_delete=models.CASCADE, related_name=\"chunks\")\n    offset = models.BigIntegerField()\n    size = models.BigIntegerField()\n\n\n@receiver(post_delete, sender=UploadChunk)\ndef upload_chunk_delete(instance, **kwargs):\n    instance.file.delete(save=False)\n", "path": "pulpcore/app/models/upload.py"}]}