Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-duet for openSUSE:Factory 
checked in at 2023-04-24 22:31:12
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-duet (Old)
 and      /work/SRC/openSUSE:Factory/.python-duet.new.1533 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-duet"

Mon Apr 24 22:31:12 2023 rev:4 rq:1082327 version:0.2.8

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-duet/python-duet.changes  2022-10-14 
15:42:20.535898659 +0200
+++ /work/SRC/openSUSE:Factory/.python-duet.new.1533/python-duet.changes        
2023-04-24 22:31:24.183578335 +0200
@@ -1,0 +2,10 @@
+Sun Apr 23 20:44:55 UTC 2023 - Dirk Müller <dmuel...@suse.com>
+
+- update to 0.2.8:
+  * Test duet against python 3.11 
+  * Loosen version requirement on typing_extensions
+  * Make Limiter work with cancellation
+  * Add support for overloaded sync callbacks 
+  * Fix timeout clipping in Scheduler.tick 
+
+-------------------------------------------------------------------

Old:
----
  duet-0.2.7.tar.gz

New:
----
  duet-0.2.8.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-duet.spec ++++++
--- /var/tmp/diff_new_pack.0pxgCb/_old  2023-04-24 22:31:24.759581759 +0200
+++ /var/tmp/diff_new_pack.0pxgCb/_new  2023-04-24 22:31:24.763581783 +0200
@@ -1,7 +1,7 @@
 #
 # spec file for package python-duet
 #
-# Copyright (c) 2022 SUSE LLC
+# Copyright (c) 2023 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -19,7 +19,7 @@
 %{?!python_module:%define python_module() python3-%{**}}
 %define skip_python2 1
 Name:           python-duet
-Version:        0.2.7
+Version:        0.2.8
 Release:        0
 Summary:        A simple future-based async library for python
 License:        Apache-2.0

++++++ duet-0.2.7.tar.gz -> duet-0.2.8.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/.github/workflows/ci.yml 
new/duet-0.2.8/.github/workflows/ci.yml
--- old/duet-0.2.7/.github/workflows/ci.yml     1970-01-01 01:00:00.000000000 
+0100
+++ new/duet-0.2.8/.github/workflows/ci.yml     2023-03-03 00:41:07.000000000 
+0100
@@ -0,0 +1,112 @@
+name: Continuous Integration
+
+on: [pull_request]
+
+jobs:
+  format:
+    name: Format check
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          fetch-depth: 0
+      - uses: actions/setup-python@v3
+        with:
+          python-version: '3.7'
+          architecture: 'x64'
+      - name: Install black
+        run: pip install -r dev/requirements.txt
+      - name: Format
+        run: isort duet --check && black duet --check
+  mypy:
+    name: Type check
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v3
+        with:
+          python-version: '3.7'
+          architecture: 'x64'
+      - name: Install mypy
+        run: pip install -r dev/requirements.txt
+      - name: Type check
+        run: mypy duet
+        env:
+          PYTHONPATH: '.'
+  lint:
+    name: Lint check
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v3
+        with:
+          python-version: '3.7'
+          architecture: 'x64'
+      - name: Install pylint
+        run: pip install -r dev/requirements.txt
+      - name: Lint
+        run: pylint duet
+  import:
+    name: Import check
+    strategy:
+      matrix:
+        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v3
+        with:
+          python-version: ${{ matrix.python-version }}
+          architecture: 'x64'
+      - name: Install requirements
+        run: pip install -r requirements.txt
+      - name: Import duet
+        run: python -c "import duet"
+  test-linux:
+    name: Pytest Linux
+    strategy:
+      matrix:
+        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
+    runs-on: ubuntu-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v3
+        with:
+          python-version: ${{ matrix.python-version }}
+          architecture: 'x64'
+      - name: Install requirements
+        run: pip install -r requirements.txt -r dev/requirements.txt
+      - name: Pytest check
+        run: pytest duet
+  test-windows:
+    name: Pytest Windows
+    strategy:
+      matrix:
+        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
+    runs-on: windows-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v3
+        with:
+          python-version: ${{ matrix.python-version }}
+          architecture: 'x64'
+      - name: Install requirements
+        run: pip install -r requirements.txt -r dev/requirements.txt
+      - name: Pytest Windows
+        run: pytest duet
+  test-macos:
+    name: Pytest MacOS
+    strategy:
+      matrix:
+        python-version: ['3.7', '3.8', '3.9', '3.10', '3.11']
+    runs-on: macos-latest
+    steps:
+      - uses: actions/checkout@v3
+      - uses: actions/setup-python@v3
+        with:
+          python-version: ${{ matrix.python-version }}
+          architecture: 'x64'
+      - name: Install requirements
+        run: pip install -r requirements.txt -r dev/requirements.txt
+      - name: Pytest check
+        run: pytest duet
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/.gitignore new/duet-0.2.8/.gitignore
--- old/duet-0.2.7/.gitignore   1970-01-01 01:00:00.000000000 +0100
+++ new/duet-0.2.8/.gitignore   2021-10-20 20:54:16.000000000 +0200
@@ -0,0 +1,133 @@
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+pip-wheel-metadata/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+#  Usually these files are written by a python script from a template
+#  before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+.python-version
+
+# pipenv
+#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in 
version control.
+#   However, in case of collaboration, if having platform-specific 
dependencies or dependencies
+#   having no cross-platform support, pipenv may install dependencies that 
don't work, or not
+#   install all needed dependencies.
+#Pipfile.lock
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# IDEs
+*.iml
+.idea
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/.mypy.ini new/duet-0.2.8/.mypy.ini
--- old/duet-0.2.7/.mypy.ini    1970-01-01 01:00:00.000000000 +0100
+++ new/duet-0.2.8/.mypy.ini    2023-02-27 21:10:50.000000000 +0100
@@ -0,0 +1,21 @@
+[mypy]
+strict_optional = true
+plugins = duet.typing
+show_error_codes = true
+warn_unused_ignores = true
+
+[mypy-__main__]
+follow_imports = silent
+ignore_missing_imports = true
+
+[mypy-grpc]
+follow_imports = silent
+ignore_missing_imports = true
+
+[mypy-pytest]
+follow_imports = silent
+ignore_missing_imports = true
+
+[mypy-aiocontext]
+follow_imports = silent
+ignore_missing_imports = true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/.pylintrc new/duet-0.2.8/.pylintrc
--- old/duet-0.2.7/.pylintrc    1970-01-01 01:00:00.000000000 +0100
+++ new/duet-0.2.8/.pylintrc    2021-02-10 22:37:09.000000000 +0100
@@ -0,0 +1,40 @@
+[config]
+disable=all
+max-line-length=100
+enable=
+    anomalous-backslash-in-string,
+    bad-option-value,
+    bad-reversed-sequence,
+    bad-super-call,
+    continue-in-finally,
+    dangerous-default-value,
+    duplicate-argument-name,
+    expression-not-assigned,
+    f-string-without-interpolation,
+    function-redefined,
+    init-is-generator,
+    line-too-long,
+    mixed-indentation,
+    nonexistent-operator,
+    not-in-loop,
+    no-value-for-parameter
+    pointless-statement,
+    pointless-string-statement,
+    redefined-builtin,
+    relative-import,
+    return-arg-in-generator,
+    return-in-init,
+    return-outside-function,
+    singleton-comparison,
+    syntax-error,
+    undefined-variable,
+    unnecessary-pass,
+    unreachable,
+    unrecognized-inline-option,
+    unused-import,
+    unused-variable,
+    unused-wildcard-import,
+    wildcard-import,
+    wrong-import-order,
+    wrong-import-position,
+    yield-outside-function
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/AUTHORS new/duet-0.2.8/AUTHORS
--- old/duet-0.2.7/AUTHORS      1970-01-01 01:00:00.000000000 +0100
+++ new/duet-0.2.8/AUTHORS      2021-02-06 16:18:23.000000000 +0100
@@ -0,0 +1,7 @@
+# This is the list of Duet's significant contributors.
+#
+# This does not necessarily list everyone who has contributed code,
+# especially since many employees of one corporation may be contributing.
+# To see the full list of contributors, see the revision history in
+# source control.
+Google LLC
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/CONTRIBUTING.md 
new/duet-0.2.8/CONTRIBUTING.md
--- old/duet-0.2.7/CONTRIBUTING.md      1970-01-01 01:00:00.000000000 +0100
+++ new/duet-0.2.8/CONTRIBUTING.md      2021-02-05 23:48:38.000000000 +0100
@@ -0,0 +1,29 @@
+# How to Contribute
+
+We'd love to accept your patches and contributions to this project. There are
+just a few small guidelines you need to follow.
+
+## Contributor License Agreement
+
+Contributions to this project must be accompanied by a Contributor License
+Agreement (CLA). You (or your employer) retain the copyright to your
+contribution; this simply gives us permission to use and redistribute your
+contributions as part of the project. Head over to
+<https://cla.developers.google.com/> to see your current agreements on file or
+to sign a new one.
+
+You generally only need to submit a CLA once, so if you've already submitted 
one
+(even if it was for a different project), you probably don't need to do it
+again.
+
+## Code Reviews
+
+All submissions, including submissions by project members, require review. We
+use GitHub pull requests for this purpose. Consult
+[GitHub Help](https://help.github.com/articles/about-pull-requests/) for more
+information on using pull requests.
+
+## Community Guidelines
+
+This project follows
+[Google's Open Source Community 
Guidelines](https://opensource.google/conduct/).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/PKG-INFO new/duet-0.2.8/PKG-INFO
--- old/duet-0.2.7/PKG-INFO     2022-06-18 03:52:56.991586000 +0200
+++ new/duet-0.2.8/PKG-INFO     2023-04-12 21:44:36.036382400 +0200
@@ -1,52 +1,49 @@
 Metadata-Version: 2.1
 Name: duet
-Version: 0.2.7
+Version: 0.2.8
 Summary: A simple future-based async library for python.
 Home-page: http://github.com/google/duet
 Author: The Duet Authors
 Author-email: maf...@google.com
 License: Apache 2
+Description: # duet
+        
+        A simple future-based async library for python
+        
+        Duet takes inspiration from the amazing 
[trio](https://trio.readthedocs.io/en/stable/)
+        library and the [structured 
concurrency](https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/)
+        approach to async programming that it uses.
+        However, duet differs from trio in two major ways:
+        
+        - Instead of a full-blown implementation of asynchronous IO, duet 
relies  on the
+          `Future` interface for parallelism, and provides a way to run 
async/await
+          coroutines around those `Future`s. This is useful if you are using 
an API that
+          returns futures, such as RPC libraries like gRPC. The standard 
`Future`
+          interface does not implement `__await__` directly, so `Future` 
instances must
+          be wrapped in `duet.AwaitableFuture`.
+        
+        - duet is re-entrant. At the top level, you run async code by calling
+          `duet.run(foo)`. Inside `foo` suppose you call a function that has 
not yet
+          been fully refactored to be asynchronous, but itself calls 
`duet.run(bar)`.
+          Most async libraries, including `trio` and `asyncio`, will raise an 
exception
+          if you try to "re-enter" the event loop in this way, but duet allows 
it. We
+          have found that this can simplify the process of refactoring code to 
be
+          asynchronous because you don't have to completely separate the sync 
and async
+          parts of your codebase all at once.
+        
+        ## Installation
+          
+        Install from pypi:
+        
+        ```
+        pip install duet
+        ```
+        
+        ## Note
+        
+        duet is not an official Google project.
+        
 Platform: UNKNOWN
 Requires-Python: >=3.7.0
 Description-Content-Type: text/markdown
 Provides-Extra: dev_env
-License-File: LICENSE
-
-# duet
-
-A simple future-based async library for python
-
-Duet takes inspiration from the amazing 
[trio](https://trio.readthedocs.io/en/stable/)
-library and the [structured 
concurrency](https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/)
-approach to async programming that it uses.
-However, duet differs from trio in two major ways:
-
-- Instead of a full-blown implementation of asynchronous IO, duet relies  on 
the
-  `Future` interface for parallelism, and provides a way to run async/await
-  coroutines around those `Future`s. This is useful if you are using an API 
that
-  returns futures, such as RPC libraries like gRPC. The standard `Future`
-  interface does not implement `__await__` directly, so `Future` instances must
-  be wrapped in `duet.AwaitableFuture`.
-
-- duet is re-entrant. At the top level, you run async code by calling
-  `duet.run(foo)`. Inside `foo` suppose you call a function that has not yet
-  been fully refactored to be asynchronous, but itself calls `duet.run(bar)`.
-  Most async libraries, including `trio` and `asyncio`, will raise an exception
-  if you try to "re-enter" the event loop in this way, but duet allows it. We
-  have found that this can simplify the process of refactoring code to be
-  asynchronous because you don't have to completely separate the sync and async
-  parts of your codebase all at once.
-
-## Installation
-  
-Install from pypi:
-
-```
-pip install duet
-```
-
-## Note
-
-duet is not an official Google project.
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/dev/build new/duet-0.2.8/dev/build
--- old/duet-0.2.7/dev/build    1970-01-01 01:00:00.000000000 +0100
+++ new/duet-0.2.8/dev/build    2021-09-30 10:10:16.000000000 +0200
@@ -0,0 +1,31 @@
+#!/usr/bin/env sh
+
+if [ -d "dist" ]; then
+  rm -rf dist/
+fi
+
+for arg in "$@"; do
+  case $arg in
+    --pre)
+      SRC_VERSION_LINE=$(cat "duet/_version.py" | tail -n 1)
+      SRC_VERSION=$(echo $SRC_VERSION_LINE | cut -d'"' -f 2)
+      if [[ ${SRC_VERSION} != *"dev" ]]; then
+        echo "Version doesn't end in dev: ${SRC_VERSION_LINE}" >&2
+        exit 1
+      fi
+      export DUET_PRE_RELEASE_VERSION="${SRC_VERSION}$(date "+%Y%m%d%H%M%S")"
+      echo "pre-release version: ${DUET_PRE_RELEASE_VERSION}"
+      ;;
+
+    --upload)
+      export UPLOAD="yes"
+      ;;
+  esac
+done
+
+python setup.py sdist bdist_wheel
+
+if [ -n "${UPLOAD}" ]; then
+  echo "uploading..."
+  twine upload dist/*
+fi
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/dev/check new/duet-0.2.8/dev/check
--- old/duet-0.2.7/dev/check    1970-01-01 01:00:00.000000000 +0100
+++ new/duet-0.2.8/dev/check    2021-02-10 22:37:09.000000000 +0100
@@ -0,0 +1,7 @@
+#!/usr/bin/env sh
+
+black duet/
+isort duet/
+mypy duet/
+pylint duet/
+pytest duet/
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/duet/_version.py 
new/duet-0.2.8/duet/_version.py
--- old/duet-0.2.7/duet/_version.py     2022-06-18 03:35:26.000000000 +0200
+++ new/duet-0.2.8/duet/_version.py     2023-04-12 21:43:44.000000000 +0200
@@ -12,4 +12,4 @@
 # See the License for the specific language governing permissions and
 # limitations under the License.
 
-__version__ = "0.2.7"
+__version__ = "0.2.8"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/duet/api.py new/duet-0.2.8/duet/api.py
--- old/duet-0.2.7/duet/api.py  2022-06-18 03:23:31.000000000 +0200
+++ new/duet-0.2.8/duet/api.py  2023-04-12 21:17:44.000000000 +0200
@@ -51,9 +51,25 @@
     Returns:
         The final result of the async function.
     """
-    with impl.Scheduler() as scheduler:
+    scheduler = impl.Scheduler()
+    scheduler.init_signals()
+    try:
         task = scheduler.spawn(func(*args, **kwds))
-    return task.result
+        try:
+            while scheduler.active_tasks:
+                scheduler.tick()
+        except BaseException as exc:
+            for task in scheduler.active_tasks:
+                task.interrupt(None, exc)
+            while scheduler.active_tasks:
+                try:
+                    scheduler.tick()
+                except BaseException:
+                    pass
+            raise
+        return task.result
+    finally:
+        scheduler.cleanup_signals()
 
 
 def sync(f: Callable[..., Awaitable[T]]) -> Callable[..., T]:
@@ -205,8 +221,11 @@
                 async for i, arg in aenumerate(iterable):
                     slot = await limiter.acquire()
                     gen_scope.spawn(task, i, arg, slot)
-        except Exception as e:
+        except BaseException as e:
             collector.error(e)
+            if isinstance(e, GeneratorExit):
+                # Raise to avoid "coroutine ignored GeneratorExit" errors.
+                raise
         else:
             collector.done()
 
@@ -322,7 +341,7 @@
     try:
         yield scope
         await finish_tasks()
-    except (impl.Interrupt, Exception) as exc:
+    except BaseException as exc:
         # Interrupt remaining tasks.
         for task in tasks:
             if not task.done:
@@ -418,13 +437,15 @@
 
     def _release(self):
         self._count -= 1
-        if self._waiters:
+        # Release the first waiter that has not yet been cancelled.
+        while self._waiters:
             f = self._waiters.popleft()
-            f.try_set_result(None)
+            if f.try_set_result(None):
+                break
         if self._available_waiters:
             for f in self._available_waiters:
                 f.try_set_result(None)
-            self._available_waiters = []
+            self._available_waiters.clear()
 
     async def available(self) -> None:
         """Wait until this limiter is available (i.e. not full to capacity).
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/duet/api_test.py 
new/duet-0.2.8/duet/api_test.py
--- old/duet-0.2.7/duet/api_test.py     2022-06-18 03:22:49.000000000 +0200
+++ new/duet-0.2.8/duet/api_test.py     2023-02-27 21:10:50.000000000 +0100
@@ -14,11 +14,12 @@
 
 import abc
 import concurrent.futures
+import contextlib
 import inspect
 import sys
 import time
 import traceback
-from typing import List
+from typing import List, Tuple
 
 import pytest
 
@@ -338,12 +339,58 @@
         # Ensure that all spawned tasks completed in the right order.
         assert completed == list(range(4))
 
+    @duet.sync
+    async def test_cancel(self) -> None:
+        limiter = duet.Limiter(1)
+
+        async def func(
+            ready: duet.AwaitableFuture[duet.Scope], done: 
duet.AwaitableFuture[Tuple[bool, bool]]
+        ) -> None:
+            """Acquired and release the lock, and record what happened."""
+            async with duet.new_scope(timeout=1) as scope:
+                ready.set_result(scope)
+                acquired = False
+                cancelled = False
+                try:
+                    async with limiter:
+                        acquired = True
+                except duet.CancelledError:
+                    cancelled = True
+                done.set_result((acquired, cancelled))
+
+        async with contextlib.AsyncExitStack() as exit_stack:
+            scope = await exit_stack.enter_async_context(duet.new_scope())
+
+            # first acquire the lock
+            await exit_stack.enter_async_context(limiter)
+
+            # now spawn two coroutines that will attempt to acquire the lock
+            ready1 = duet.AwaitableFuture[duet.Scope]()
+            done1 = duet.AwaitableFuture[Tuple[bool, bool]]()
+            scope.spawn(func, ready1, done1)
+            scope1 = await ready1
+
+            ready2 = duet.AwaitableFuture[duet.Scope]()
+            done2 = duet.AwaitableFuture[Tuple[bool, bool]]()
+            scope.spawn(func, ready2, done2)
+            _scope2 = await ready2
+
+            # cancel the first waiting coroutine
+            scope1.cancel()
+
+        # ensure that first coroutine was cancelled and second coroutine got 
the lock.
+        async with duet.new_scope(timeout=0.1):
+            acquired1, cancelled1 = await done1
+            acquired2, cancelled2 = await done2
+            assert cancelled1 and not acquired1
+            assert acquired2 and not cancelled2
+
 
 @duet.sync
 async def test_sleep():
     start = time.time()
     await duet.sleep(0.5)
-    assert abs((time.time() - start) - 0.5) < 0.2
+    assert abs((time.time() - start) - 0.5) < 0.3
 
 
 @duet.sync
@@ -352,7 +399,7 @@
     with pytest.raises(TimeoutError):
         async with duet.timeout_scope(0.5):
             await duet.sleep(10)
-    assert abs((time.time() - start) - 0.5) < 0.2
+    assert abs((time.time() - start) - 0.5) < 0.3
 
 
 @duet.sync
@@ -360,7 +407,7 @@
     start = time.time()
     for _ in range(5):
         await duet.sleep(0.1)
-    assert abs((time.time() - start) - 0.5) < 0.2
+    assert abs((time.time() - start) - 0.5) < 0.3
 
 
 @duet.sync
@@ -370,7 +417,7 @@
         async with duet.timeout_scope(0.5):
             for _ in range(5):
                 await duet.sleep(0.2)
-    assert abs((time.time() - start) - 0.5) < 0.2
+    assert abs((time.time() - start) - 0.5) < 0.3
 
 
 class TestScope:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/duet/impl.py new/duet-0.2.8/duet/impl.py
--- old/duet-0.2.7/duet/impl.py 2022-06-18 03:23:31.000000000 +0200
+++ new/duet-0.2.8/duet/impl.py 2023-04-12 21:17:44.000000000 +0200
@@ -131,7 +131,7 @@
             self._result = e.value
             self._state = TaskState.SUCCEEDED
             return
-        except (Interrupt, Exception) as error:
+        except BaseException as error:
             self._error = error
             self._state = TaskState.FAILED
             if self.main_task:
@@ -392,7 +392,7 @@
                     break
                 try:
                     ready_tasks = self._ready_tasks.get_all(
-                        min(0, max(timeout, threading.TIMEOUT_MAX))
+                        max(0, min(timeout, threading.TIMEOUT_MAX))
                     )
                     break
                 except TimeoutError:
@@ -441,35 +441,13 @@
             frame = frame.f_back
         return False
 
-    def __enter__(self):
+    def init_signals(self):
         if (
             threading.current_thread() == threading.main_thread()
             and signal.getsignal(signal.SIGINT) == signal.default_int_handler
         ):
             self._prev_signal = signal.signal(signal.SIGINT, self._interrupt)
-        return self
 
-    def __exit__(self, exc_type, exc, tb):
-        def finish_tasks(error=None):
-            if error:
-                for task in self.active_tasks:
-                    task.interrupt(None, error)
-            while self.active_tasks:
-                try:
-                    self.tick()
-                except Exception:
-                    if not error:
-                        raise
-
-        try:
-            if exc:
-                finish_tasks(exc)
-            else:
-                try:
-                    finish_tasks()
-                except Exception as exc:
-                    finish_tasks(exc)
-                    raise
-        finally:
-            if self._prev_signal:
-                signal.signal(signal.SIGINT, self._prev_signal)
+    def cleanup_signals(self):
+        if self._prev_signal:
+            signal.signal(signal.SIGINT, self._prev_signal)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/duet/typing.py 
new/duet-0.2.8/duet/typing.py
--- old/duet-0.2.7/duet/typing.py       2022-05-04 09:11:02.000000000 +0200
+++ new/duet-0.2.8/duet/typing.py       2023-02-27 21:10:50.000000000 +0100
@@ -18,10 +18,10 @@
 
https://mypy.readthedocs.io/en/stable/extending_mypy.html#extending-mypy-using-plugins
 """
 
-from typing import Callable, Optional
+from typing import Callable, List, Optional
 
 from mypy.plugin import FunctionContext, Plugin
-from mypy.types import CallableType, get_proper_type, Instance, Type
+from mypy.types import CallableType, get_proper_type, Instance, Overloaded, 
Type
 
 
 def duet_sync_callback(ctx: FunctionContext) -> Type:
@@ -37,10 +37,27 @@
     functions wrapped by duet.sync.
     """
     func_type = get_proper_type(ctx.arg_types[0][0])
-    if not isinstance(func_type, CallableType):
+    if not isinstance(func_type, (CallableType, Overloaded)):
         ctx.api.msg.fail(f"expected Callable[..., Awaitable[T]], got 
{func_type}", ctx.context)
         return ctx.default_return_type
 
+    if isinstance(func_type, CallableType):
+        return modify_callable(func_type, ctx)
+
+    # func_type is overloaded
+    overloaded_callables: List[CallableType] = []
+    for ft in func_type.items:
+        overload_type = modify_callable(ft, ctx)
+        if not isinstance(overload_type, CallableType):
+            ctx.api.msg.fail(
+                f"expected overloaded type to be callable, got 
{overload_type}", ctx.context
+            )
+            return ctx.default_return_type
+        overloaded_callables.append(overload_type)
+    return Overloaded(overloaded_callables)
+
+
+def modify_callable(func_type: CallableType, ctx: FunctionContext) -> Type:
     # Note that the return type of an async function is Coroutine[Any, Any, T],
     # which is a subtype of Awaitable[T]. See:
     # https://mypy.readthedocs.io/en/stable/more_types.html#typing-async-await
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/duet.egg-info/PKG-INFO 
new/duet-0.2.8/duet.egg-info/PKG-INFO
--- old/duet-0.2.7/duet.egg-info/PKG-INFO       2022-06-18 03:52:56.000000000 
+0200
+++ new/duet-0.2.8/duet.egg-info/PKG-INFO       2023-04-12 21:44:35.000000000 
+0200
@@ -1,52 +1,49 @@
 Metadata-Version: 2.1
 Name: duet
-Version: 0.2.7
+Version: 0.2.8
 Summary: A simple future-based async library for python.
 Home-page: http://github.com/google/duet
 Author: The Duet Authors
 Author-email: maf...@google.com
 License: Apache 2
+Description: # duet
+        
+        A simple future-based async library for python
+        
+        Duet takes inspiration from the amazing 
[trio](https://trio.readthedocs.io/en/stable/)
+        library and the [structured 
concurrency](https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/)
+        approach to async programming that it uses.
+        However, duet differs from trio in two major ways:
+        
+        - Instead of a full-blown implementation of asynchronous IO, duet 
relies  on the
+          `Future` interface for parallelism, and provides a way to run 
async/await
+          coroutines around those `Future`s. This is useful if you are using 
an API that
+          returns futures, such as RPC libraries like gRPC. The standard 
`Future`
+          interface does not implement `__await__` directly, so `Future` 
instances must
+          be wrapped in `duet.AwaitableFuture`.
+        
+        - duet is re-entrant. At the top level, you run async code by calling
+          `duet.run(foo)`. Inside `foo` suppose you call a function that has 
not yet
+          been fully refactored to be asynchronous, but itself calls 
`duet.run(bar)`.
+          Most async libraries, including `trio` and `asyncio`, will raise an 
exception
+          if you try to "re-enter" the event loop in this way, but duet allows 
it. We
+          have found that this can simplify the process of refactoring code to 
be
+          asynchronous because you don't have to completely separate the sync 
and async
+          parts of your codebase all at once.
+        
+        ## Installation
+          
+        Install from pypi:
+        
+        ```
+        pip install duet
+        ```
+        
+        ## Note
+        
+        duet is not an official Google project.
+        
 Platform: UNKNOWN
 Requires-Python: >=3.7.0
 Description-Content-Type: text/markdown
 Provides-Extra: dev_env
-License-File: LICENSE
-
-# duet
-
-A simple future-based async library for python
-
-Duet takes inspiration from the amazing 
[trio](https://trio.readthedocs.io/en/stable/)
-library and the [structured 
concurrency](https://vorpus.org/blog/notes-on-structured-concurrency-or-go-statement-considered-harmful/)
-approach to async programming that it uses.
-However, duet differs from trio in two major ways:
-
-- Instead of a full-blown implementation of asynchronous IO, duet relies  on 
the
-  `Future` interface for parallelism, and provides a way to run async/await
-  coroutines around those `Future`s. This is useful if you are using an API 
that
-  returns futures, such as RPC libraries like gRPC. The standard `Future`
-  interface does not implement `__await__` directly, so `Future` instances must
-  be wrapped in `duet.AwaitableFuture`.
-
-- duet is re-entrant. At the top level, you run async code by calling
-  `duet.run(foo)`. Inside `foo` suppose you call a function that has not yet
-  been fully refactored to be asynchronous, but itself calls `duet.run(bar)`.
-  Most async libraries, including `trio` and `asyncio`, will raise an exception
-  if you try to "re-enter" the event loop in this way, but duet allows it. We
-  have found that this can simplify the process of refactoring code to be
-  asynchronous because you don't have to completely separate the sync and async
-  parts of your codebase all at once.
-
-## Installation
-  
-Install from pypi:
-
-```
-pip install duet
-```
-
-## Note
-
-duet is not an official Google project.
-
-
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/duet.egg-info/SOURCES.txt 
new/duet-0.2.8/duet.egg-info/SOURCES.txt
--- old/duet-0.2.7/duet.egg-info/SOURCES.txt    2022-06-18 03:52:56.000000000 
+0200
+++ new/duet-0.2.8/duet.egg-info/SOURCES.txt    2023-04-12 21:44:35.000000000 
+0200
@@ -1,3 +1,8 @@
+.gitignore
+.mypy.ini
+.pylintrc
+AUTHORS
+CONTRIBUTING.md
 LICENSE
 MANIFEST.in
 README.md
@@ -5,6 +10,9 @@
 requirements.txt
 setup.cfg
 setup.py
+.github/workflows/ci.yml
+dev/build
+dev/check
 dev/requirements.txt
 duet/__init__.py
 duet/_version.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/duet.egg-info/requires.txt 
new/duet-0.2.8/duet.egg-info/requires.txt
--- old/duet-0.2.7/duet.egg-info/requires.txt   2022-06-18 03:52:56.000000000 
+0200
+++ new/duet-0.2.8/duet.egg-info/requires.txt   2023-04-12 21:44:35.000000000 
+0200
@@ -1,6 +1,6 @@
 
 [:python_version <= "3.7"]
-typing-extensions==3.10.0
+typing-extensions>=3.10.0
 
 [dev_env]
 black==22.3.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/duet-0.2.7/requirements.txt 
new/duet-0.2.8/requirements.txt
--- old/duet-0.2.7/requirements.txt     2022-06-18 03:22:49.000000000 +0200
+++ new/duet-0.2.8/requirements.txt     2023-04-12 21:35:44.000000000 +0200
@@ -1 +1 @@
-typing-extensions == 3.10.0; python_version <= '3.7'
+typing-extensions >= 3.10.0; python_version <= '3.7'

Reply via email to