Repository: pulp/pulpcore

Issue:
[noissue]: Update aiohttp requirement from <3.9.1,>=3.8.1 to >=3.8.1,<3.9.2
Updates the requirements on [aiohttp](https://github.com/aio-libs/aiohttp) to permit the latest version.
<details>
<summary>Release notes</summary>
<p><em>Sourced from <a href="https://github.com/aio-libs/aiohttp/releases">aiohttp's releases</a>.</em></p>
<blockquote>
<h2>3.9.1</h2>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed importing aiohttp under PyPy on Windows.</p>
<p>(<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7848">#7848</a>)</p>
</li>
<li>
<p>Fixed async concurrency safety in websocket compressor.</p>
<p>(<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7865">#7865</a>)</p>
</li>
<li>
<p>Fixed <code>ClientResponse.close()</code> releasing the connection instead of closing.</p>
<p>(<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7869">#7869</a>)</p>
</li>
<li>
<p>Fixed a regression where connection may get closed during upgrade. -- by :user:<code>Dreamsorcerer</code></p>
<p>(<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7879">#7879</a>)</p>
</li>
<li>
<p>Fixed messages being reported as upgraded without an Upgrade header in Python parser. -- by :user:<code>Dreamsorcerer</code></p>
<p>(<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7895">#7895</a>)</p>
</li>
</ul>
<hr />
</blockquote>
</details>
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a href="https://github.com/aio-libs/aiohttp/blob/master/CHANGES.rst">aiohttp's changelog</a>.</em></p>
<blockquote>
<h1>3.9.1 (2023-11-26)</h1>
<h2>Bugfixes</h2>
<ul>
<li>
<p>Fixed importing aiohttp under PyPy on Windows.</p>
<p><code>[#7848](https://github.com/aio-libs/aiohttp/issues/7848) &lt;https://github.com/aio-libs/aiohttp/issues/7848&gt;</code>_</p>
</li>
<li>
<p>Fixed async concurrency safety in websocket compressor.</p>
<p><code>[#7865](https://github.com/aio-libs/aiohttp/issues/7865) &lt;https://github.com/aio-libs/aiohttp/issues/7865&gt;</code>_</p>
</li>
<li>
<p>Fixed <code>ClientResponse.close()</code> releasing the connection instead of closing.</p>
<p><code>[#7869](https://github.com/aio-libs/aiohttp/issues/7869) &lt;https://github.com/aio-libs/aiohttp/issues/7869&gt;</code>_</p>
</li>
<li>
<p>Fixed a regression where connection may get closed during upgrade. -- by :user:<code>Dreamsorcerer</code></p>
<p><code>[#7879](https://github.com/aio-libs/aiohttp/issues/7879) &lt;https://github.com/aio-libs/aiohttp/issues/7879&gt;</code>_</p>
</li>
<li>
<p>Fixed messages being reported as upgraded without an Upgrade header in Python parser. -- by :user:<code>Dreamsorcerer</code></p>
<p><code>[#7895](https://github.com/aio-libs/aiohttp/issues/7895) &lt;https://github.com/aio-libs/aiohttp/issues/7895&gt;</code>_</p>
</li>
</ul>
<hr />
<h1>3.9.0 (2023-11-18)</h1>
<h2>Features</h2>
<ul>
<li>
<p>Introduced <code>AppKey</code> for static typing support of <code>Application</code> storage.
See <a href="https://docs.aiohttp.org/en/stable/web_advanced.html#application-s-config">https://docs.aiohttp.org/en/stable/web_advanced.html#application-s-config</a></p>
<p><code>[#5864](https://github.com/aio-libs/aiohttp/issues/5864) &lt;https://github.com/aio-libs/aiohttp/issues/5864&gt;</code>_</p>
</li>
<li>
<p>Added a graceful shutdown period which allows pending tasks to complete before the application's cleanup is called.
The period can be adjusted with the <code>shutdown_timeout</code> parameter. -- by :user:<code>Dreamsorcerer</code>.
See <a href="https://docs.aiohttp.org/en/latest/web_advanced.html#graceful-shutdown">https://docs.aiohttp.org/en/latest/web_advanced.html#graceful-shutdown</a></p>
<p><code>[#7188](https://github.com/aio-libs/aiohttp/issues/7188) &lt;https://github.com/aio-libs/aiohttp/issues/7188&gt;</code>_</p>
</li>
<li>
<p>Added <code>handler_cancellation &lt;https://docs.aiohttp.org/en/stable/web_advanced.html#web-handler-cancellation&gt;</code>_ parameter to cancel web handler on client disconnection. -- by :user:<code>mosquito</code>
This (optionally) reintroduces a feature removed in a previous release.</p>
</li>
</ul>
<!-- raw HTML omitted -->
</blockquote>
<p>... (truncated)</p>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a href="https://github.com/aio-libs/aiohttp/commit/6333c026422c6b0fe57ff63cde4104e2d00f47f4"><code>6333c02</code></a> Release v3.9.1 (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7911">#7911</a>)</li>
<li><a href="https://github.com/aio-libs/aiohttp/commit/9dbd273093d6af6f5e1481816b05a7192860b440"><code>9dbd273</code></a> [PR <a href="https://redirect.github.com/aio-libs/aiohttp/issues/7673">#7673</a>/aa7d1a8f backport][3.9] Document release process (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7909">#7909</a>)</li>
<li><a href="https://github.com/aio-libs/aiohttp/commit/dd175b6b89564dc74fba0692a8a5f9a9b38e528a"><code>dd175b6</code></a> Fix regression with connection upgrade (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7879">#7879</a>) (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7908">#7908</a>)</li>
<li><a href="https://github.com/aio-libs/aiohttp/commit/946523d6380bd79e13146557432f46f6f9bbd53f"><code>946523d</code></a> Fix flaky websocket test (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7902">#7902</a>) (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7904">#7904</a>)</li>
<li><a href="https://github.com/aio-libs/aiohttp/commit/ddc2a26c9e0c43fd1229e4424f2a30d1b10ced13"><code>ddc2a26</code></a> [PR <a href="https://redirect.github.com/aio-libs/aiohttp/issues/7896">#7896</a>/9a7cfe77 backport][3.9] Fix some flaky tests (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7900">#7900</a>)</li>
<li><a href="https://github.com/aio-libs/aiohttp/commit/2ae4d6ffdd015f622bfb75dee98ad629240cccc4"><code>2ae4d6f</code></a> Message is not upgraded if Upgrade header is missing (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7895">#7895</a>) (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7898">#7898</a>)</li>
<li><a href="https://github.com/aio-libs/aiohttp/commit/bb111012706d3ef9edc525be3d8d4df410ad847f"><code>bb11101</code></a> Restore async concurrency safety to websocket compressor (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7865">#7865</a>) (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7889">#7889</a>)</li>
<li><a href="https://github.com/aio-libs/aiohttp/commit/6dd0122417f00ed4b2b353226a1b164b6463a245"><code>6dd0122</code></a> Update dependabot.yml (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7888">#7888</a>)</li>
<li><a href="https://github.com/aio-libs/aiohttp/commit/41a9f1f5b9b2630b1f4b971811c7ef8f016262fb"><code>41a9f1f</code></a> Bump mypy from 1.7.0 to 1.7.1 (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7882">#7882</a>)</li>
<li><a href="https://github.com/aio-libs/aiohttp/commit/a04970150c6ce9fda22c9f63d947845f79148b4c"><code>a049701</code></a> Fix usage of proxy.py in test_proxy_functional (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7773">#7773</a>)  (<a href="https://redirect.github.com/aio-libs/aiohttp/issues/7876">#7876</a>)</li>
<li>Additional commits viewable in <a href="https://github.com/aio-libs/aiohttp/compare/v3.8.1...v3.9.1">compare view</a></li>
</ul>
</details>
<br />


Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting `@dependabot rebase`.

[//]: # (dependabot-automerge-start)
[//]: # (dependabot-automerge-end)

---

<details>
<summary>Dependabot commands and options</summary>
<br />

You can trigger Dependabot actions by commenting on this PR:
- `@dependabot rebase` will rebase this PR
- `@dependabot recreate` will recreate this PR, overwriting any edits that have been made to it
- `@dependabot merge` will merge this PR after your CI passes on it
- `@dependabot squash and merge` will squash and merge this PR after your CI passes on it
- `@dependabot cancel merge` will cancel a previously requested merge and block automerging
- `@dependabot reopen` will reopen this PR if it is closed
- `@dependabot close` will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
- `@dependabot show <dependency name> ignore conditions` will show all of the ignore conditions of the specified dependency
- `@dependabot ignore this major version` will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this minor version` will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
- `@dependabot ignore this dependency` will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)


</details>


Discussion:

Resolving patch:
diff --git a/pulpcore/app/serializers/content.py b/pulpcore/app/serializers/content.py
--- a/pulpcore/app/serializers/content.py
+++ b/pulpcore/app/serializers/content.py
@@ -99,6 +99,7 @@ class ArtifactSerializer(base.ModelSerializer):
 
     file = serializers.FileField(
         help_text=_("The stored file."),
+        allow_empty_file=True,
         required=False
     )
 


Test patch:
diff --git a/pulpcore/tests/functional/api/test_crd_artifacts.py b/pulpcore/tests/functional/api/test_crd_artifacts.py
--- a/pulpcore/tests/functional/api/test_crd_artifacts.py
+++ b/pulpcore/tests/functional/api/test_crd_artifacts.py
@@ -54,11 +54,31 @@ def test_upload_valid_attrs(self):
             for keys in itertools.combinations(file_attrs, i):
                 data = {key: file_attrs[key] for key in keys}
                 with self.subTest(data=data):
-                    self._do_upload_valid_attrs(data)
+                    self._do_upload_valid_attrs(data, self.file)
 
-    def _do_upload_valid_attrs(self, data):
+    def test_upload_empty_file(self):
+        """Upload an empty file.
+
+        For each possible combination of ``sha256`` and ``size`` (including
+        neither), do the following:
+
+        1. Upload a file with the chosen combination of attributes.
+        2. Verify that an artifact has been created, and that it has valid
+           attributes.
+        3. Delete the artifact, and verify that its attributes are
+           inaccessible.
+        """
+        empty_file = b''
+        file_attrs = {'sha256': hashlib.sha256(empty_file).hexdigest(), 'size': 0}
+        for i in range(len(file_attrs) + 1):
+            for keys in itertools.combinations(file_attrs, i):
+                data = {key: file_attrs[key] for key in keys}
+                with self.subTest(data=data):
+                    self._do_upload_valid_attrs(data, files={'file': empty_file})
+
+    def _do_upload_valid_attrs(self, data, files):
         """Upload a file with the given attributes."""
-        artifact = self.client.post(ARTIFACTS_PATH, data=data, files=self.file)
+        artifact = self.client.post(ARTIFACTS_PATH, data=data, files=files)
         self.addCleanup(self.client.delete, artifact['_href'])
         read_artifact = self.client.get(artifact['_href'])
         for key, val in artifact.items():