Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

aiocoap: Adjust to subtle API change #536

Closed
wants to merge 1 commit into from
Closed

aiocoap: Adjust to subtle API change #536

wants to merge 1 commit into from

Conversation

chrysn
Copy link
Contributor

@chrysn chrysn commented Aug 16, 2022

This is an attempt to make pytradfri robust against the change in chrysn/aiocoap#271.

I didn't make myself familiar with the pytradfri testing setup yet -- would CI cover this one?

Copy link
Contributor

@MartinHjelmare MartinHjelmare left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I suggest another approach.

Side note: Not being able to create a task from a coroutine is very unexpected in a library API. I'd recommend to think about that change carefully.

pytradfri/api/aiocoap_api.py Outdated Show resolved Hide resolved
@chrysn
Copy link
Contributor Author

chrysn commented Aug 16, 2022

On the API change policy, I'd have considered "awaitable" the more relevant distinction than by which kind of awaitable that is backed. Thing is, the creation should used an async context manager right away -- any better suggestions for migrating? (I've tried to wrap things as good as possible to support both ctx = await create_client_context() and async with create_client_context() as ctx:, just like open does, but I can't subclass or otherwise mock or modify a coroutine object)

@MartinHjelmare
Copy link
Contributor

How common is it that applications want to use a context manager for the protocol to shutdown?

See-Also: chrysn/aiocoap#271

Co-authored-by: Martin Hjelmare <marhje52@gmail.com>
@chrysn
Copy link
Contributor Author

chrysn commented Aug 16, 2022

I honestly don't know, but especially when dealing with beginner programs, I found that the shutdown as often not performed, leading to warnings at cleanup and protocol misbehavior (observations not cancelled). I haven't switched over the CLI components yet (essentially waiting for this to not cause trouble, which it now does), but I expect things to be easier there too.

Is there any documentation or other rough consensus of the await self.foo.shutdown() pattern that it would be preferable to asynchronous context managers?

[edit: To clarify, I'm still considering reverting that change in aiocoap to ... somehow use a different migration strategy to async context managers, such that it would not break the original code here.]

@MartinHjelmare
Copy link
Contributor

MartinHjelmare commented Aug 16, 2022

In my experience, context managers for clients and similar APIs work well and is nice for smaller applications, eg CLIs, but are not useful for larger applications that have longer runtimes and more complex needs around setting up and shutting down. The context manager requires the application to shutdown in the same code context that sets up, but that's often not convenient or possible in larger applications.

Maybe instead extend the Context signature with parameters matching Context.create_client_context and await create_client_context (or similar non classmethod) in __aenter__ of Context?

That way users can conveniently use a context manager to get a protocol, but existing applications that don't need that retains the existing API.

@chrysn
Copy link
Contributor Author

chrysn commented Aug 17, 2022

I'm reverting the breakage in aiocoap and will go for some different contstructor (possibly really just Context() as you suggest) for the context manager. Thus, there is no further need for this PR.

Thanks for your input!

@chrysn chrysn closed this Aug 17, 2022
@chrysn
Copy link
Contributor Author

chrysn commented Sep 22, 2022

I usually keep forks and branches of closed PRs around for reference, but in this case that's impractical as pytradfri forks suffer from dependabot/dependabot-core#2804.

To keep the patch around, this was it:

commit 81983dd309ea9b14b0e60e7c30d4b37d5a91ce47 (HEAD -> aiocoap-next, mine/aiocoap-next)
Author: chrysn <chrysn@fsfe.org>
Date:   Tue Aug 16 10:16:13 2022 +0200

    aiocoap: Adjust to subtle API change
    
    See-Also: https://github.com/chrysn/aiocoap/issues/271
    
    Co-authored-by: Martin Hjelmare <marhje52@gmail.com>

diff --git a/pytradfri/api/aiocoap_api.py b/pytradfri/api/aiocoap_api.py
index 314192d..31ec5f3 100644
--- a/pytradfri/api/aiocoap_api.py
+++ b/pytradfri/api/aiocoap_api.py
@@ -74,7 +74,8 @@ class APIFactory:
         self._host = host
         self._psk_id = psk_id
         self._observations_err_callbacks: list[Callable[[Exception], None]] = []
-        self._protocol: asyncio.Task[Context] | None = None
+        self._protocol: Context | None = None
+        self._protocol_creation_lock = asyncio.Lock()
         self._reset_lock = asyncio.Lock()
         self._shutdown = False
 
@@ -100,9 +101,10 @@ class APIFactory:
 
     async def _get_protocol(self) -> Context:
         """Get the protocol for the request."""
-        if self._protocol is None:
-            self._protocol = asyncio.create_task(Context.create_client_context())
-        return await self._protocol
+        async with self._protocol_creation_lock:
+            if self._protocol is None:
+                self._protocol = await Context.create_client_context()
+        return self._protocol
 
     async def _reset_protocol(self, exc: BaseException | None = None) -> None:
         """Reset the protocol if an error occurs."""

MartinHjelmare pushed a commit that referenced this pull request Oct 3, 2022
Bumps [pytest-cov](https://github.com/pytest-dev/pytest-cov) from 3.0.0
to 4.0.0.
<details>
<summary>Changelog</summary>
<p><em>Sourced from <a
href="https://github.com/pytest-dev/pytest-cov/blob/master/CHANGELOG.rst">pytest-cov's
changelog</a>.</em></p>
<blockquote>
<h2>4.0.0 (2022-09-28)</h2>
<p><strong>Note that this release drops support for
multiprocessing.</strong></p>
<ul>
<li>
<p><code>--cov-fail-under</code> no longer causes <code>pytest
--collect-only</code> to fail
Contributed by Zac Hatfield-Dodds in
<code>[#511](pytest-dev/pytest-cov#511)
&lt;https://github.com/pytest-dev/pytest-cov/pull/511&gt;</code>_.</p>
</li>
<li>
<p>Dropped support for multiprocessing (mostly because <code>issue 82408
&lt;https://github.com/python/cpython/issues/82408&gt;</code>_). This
feature was
mostly working but very broken in certain scenarios and made the test
suite very flaky and slow.</p>
<p>There is builtin multiprocessing support in coverage and you can
migrate to that. All you need is this in your
<code>.coveragerc</code>::</p>
<p>[run]
concurrency = multiprocessing
parallel = true
sigterm = true</p>
</li>
<li>
<p>Fixed deprecation in <code>setup.py</code> by trying to import
setuptools before distutils.
Contributed by Ben Greiner in
<code>[#545](pytest-dev/pytest-cov#545)
&lt;https://github.com/pytest-dev/pytest-cov/pull/545&gt;</code>_.</p>
</li>
<li>
<p>Removed undesirable new lines that were displayed while reporting was
disabled.
Contributed by Delgan in
<code>[#540](pytest-dev/pytest-cov#540)
&lt;https://github.com/pytest-dev/pytest-cov/pull/540&gt;</code>_.</p>
</li>
<li>
<p>Documentation fixes.
Contributed by Andre Brisco in
<code>[#543](pytest-dev/pytest-cov#543)
&lt;https://github.com/pytest-dev/pytest-cov/pull/543&gt;</code>_
and Colin O'Dell in
<code>[#525](pytest-dev/pytest-cov#525)
&lt;https://github.com/pytest-dev/pytest-cov/pull/525&gt;</code>_.</p>
</li>
<li>
<p>Added support for LCOV output format via
<code>--cov-report=lcov</code>. Only works with coverage 6.3+.
Contributed by Christian Fetzer in
<code>[#536](pytest-dev/pytest-cov#536)
&lt;https://github.com/pytest-dev/pytest-cov/issues/536&gt;</code>_.</p>
</li>
<li>
<p>Modernized pytest hook implementation.
Contributed by Bruno Oliveira in
<code>[#549](pytest-dev/pytest-cov#549)
&lt;https://github.com/pytest-dev/pytest-cov/pull/549&gt;</code>_
and Ronny Pfannschmidt in
<code>[#550](pytest-dev/pytest-cov#550)
&lt;https://github.com/pytest-dev/pytest-cov/pull/550&gt;</code>_.</p>
</li>
</ul>
</blockquote>
</details>
<details>
<summary>Commits</summary>
<ul>
<li><a
href="https://github.com/pytest-dev/pytest-cov/commit/28db055bebbf3ee016a2144c8b69dd7b80b48cc5"><code>28db055</code></a>
Bump version: 3.0.0 → 4.0.0</li>
<li><a
href="https://github.com/pytest-dev/pytest-cov/commit/57e9354a86f658556fe6f15f07625c4b9a9ddf53"><code>57e9354</code></a>
Really update the changelog.</li>
<li><a
href="https://github.com/pytest-dev/pytest-cov/commit/56b810b91c9ae15d1462633c6a8a1b522ebf8e65"><code>56b810b</code></a>
Update chagelog.</li>
<li><a
href="https://github.com/pytest-dev/pytest-cov/commit/f7fced579e36b72b57e14768026467e4c4511a40"><code>f7fced5</code></a>
Add support for LCOV output</li>
<li><a
href="https://github.com/pytest-dev/pytest-cov/commit/1211d3134bb74abb7b00c3c2209091aaab440417"><code>1211d31</code></a>
Fix flake8 error</li>
<li><a
href="https://github.com/pytest-dev/pytest-cov/commit/b077753f5d9d200815fe500d0ef23e306784e65b"><code>b077753</code></a>
Use modern approach to specify hook options</li>
<li><a
href="https://github.com/pytest-dev/pytest-cov/commit/00713b3fec90cb8c98a9e4bfb3212e574c08e67b"><code>00713b3</code></a>
removed incorrect docs on <code>data_file</code>.</li>
<li><a
href="https://github.com/pytest-dev/pytest-cov/commit/b3dda36fddd3ca75689bb3645cd320aa8392aaf3"><code>b3dda36</code></a>
Improve workflow with a collecting status check. (<a
href="https://github-redirect.dependabot.com/pytest-dev/pytest-cov/issues/548">#548</a>)</li>
<li><a
href="https://github.com/pytest-dev/pytest-cov/commit/218419f665229d61356f1eea3ddc8e18aa21f87c"><code>218419f</code></a>
Prevent undesirable new lines to be displayed when report is
disabled</li>
<li><a
href="https://github.com/pytest-dev/pytest-cov/commit/60b73ec673c60942a3cf052ee8a1fdc442840558"><code>60b73ec</code></a>
migrate build command from distutils to setuptools</li>
<li>Additional commits viewable in <a
href="https://github.com/pytest-dev/pytest-cov/compare/v3.0.0...v4.0.0">compare
view</a></li>
</ul>
</details>
<br />


[![Dependabot compatibility
score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=pytest-cov&package-manager=pip&previous-version=3.0.0&new-version=4.0.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)

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 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>

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants