Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-unsync for openSUSE:Factory 
checked in at 2025-01-07 20:53:59
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-unsync (Old)
 and      /work/SRC/openSUSE:Factory/.python-unsync.new.1881 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-unsync"

Tue Jan  7 20:53:59 2025 rev:2 rq:1235527 version:1.3.2

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-unsync/python-unsync.changes      
2021-01-02 21:31:21.975455548 +0100
+++ /work/SRC/openSUSE:Factory/.python-unsync.new.1881/python-unsync.changes    
2025-01-07 20:54:36.719872107 +0100
@@ -1,0 +2,19 @@
+Tue Jan  7 08:46:22 UTC 2025 - John Paul Adrian Glaubitz 
<[email protected]>
+
+- Update to version 1.3.2
+  * Delete print("DERP") (#39)
+- from version 1.3.1
+  * Add a multi-process example
+  * Cleanup README
+  * Modify async example in documentation (#36)
+  * Support setting custom event loops (#34)
+  * Refactor lazy initialized unsync class members into properties
+- Switch package to modern Python Stack on SLE-15
+  * Use Python 3.11 on SLE-15 by default
+  * Drop support for older Python versions
+- Switch build system from setuptools to pyproject.toml
+  * Add python-pip and python-wheel to BuildRequires
+  * Replace %python_build with %pyproject_wheel
+  * Replace %python_install with %pyproject_install
+
+-------------------------------------------------------------------

Old:
----
  unsync-1.3.tar.gz

New:
----
  unsync-1.3.2.tar.gz

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

Other differences:
------------------
++++++ python-unsync.spec ++++++
--- /var/tmp/diff_new_pack.UF8nHN/_old  2025-01-07 20:54:37.675911649 +0100
+++ /var/tmp/diff_new_pack.UF8nHN/_new  2025-01-07 20:54:37.679911814 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-unsync
 #
-# Copyright (c) 2021 SUSE LLC
+# Copyright (c) 2025 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -15,17 +15,19 @@
 # Please submit bugfixes or comments via https://bugs.opensuse.org/
 #
 
-%define skip_python2 1
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
+
+%{?sle15_python_module_pythons}
 %define modname unsync
 Name:           python-unsync
-Version:        1.3
+Version:        1.3.2
 Release:        0
 Summary:        Unsynchronize asyncio
 License:        MIT
 URL:            https://github.com/alex-sherman/unsync
 Source:         
https://github.com/alex-sherman/%{modname}/archive/v%{version}.tar.gz#/%{modname}-%{version}.tar.gz
+BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools}
+BuildRequires:  %{python_module wheel}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 BuildArch:      noarch
@@ -62,10 +64,10 @@
 %setup -q -n unsync-%{version}
 
 %build
-%python_build
+%pyproject_wheel
 
 %install
-%python_install
+%pyproject_install
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %check

++++++ unsync-1.3.tar.gz -> unsync-1.3.2.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unsync-1.3/README.md new/unsync-1.3.2/README.md
--- old/unsync-1.3/README.md    2020-12-29 04:48:53.000000000 +0100
+++ new/unsync-1.3.2/README.md  2021-03-27 23:23:06.000000000 +0100
@@ -1,52 +1,64 @@
 # unsync
-Unsynchronize `asyncio` by using an ambient event loop in a separate thread.
+Unsynchronize `asyncio` by using an ambient event loop, or executing in 
separate threads or processes.
 
-# Rules for unsync
-1. Mark all async functions with `@unsync`. May also mark regular functions to 
execute in a separate thread.
-    * All `@unsync` functions, async or not, return an `Unfuture`
-2. All `Futures` must be `Unfutures` which includes the result of an `@unsync` 
function call,
-    or wrapping `Unfuture(asyncio.Future)` or `Unfuture(concurrent.Future)`.
-    `Unfuture` combines the behavior of `asyncio.Future` and 
`concurrent.Future`:
-    * `Unfuture.set_value` is threadsafe unlike `asyncio.Future`
-    * `Unfuture` instances can be awaited, even if made from 
`concurrent.Future`
-    * `Unfuture.result()` is a blocking operation *except* in 
`unsync.loop`/`unsync.thread` where
-    it behaves like `asyncio.Future.result` and will throw an exception if the 
future is not done
-3. Functions will execute in different contexts:
-    * `@unsync` async functions will execute in an event loop in 
`unsync.thread`
-    * `@unsync` regular functions will execute in `unsync.thread_executor`, a 
`ThreadPoolExecutor`
-    * `@unsync(cpu_bound=True)` regular functions will execute in 
`unsync.process_executor`, a `ProcessPoolExecutor`
+# Quick Overview
 
+Functions marked with the `@unsync` decorator will behave in one of the 
following ways:
+* `async` functions will run in the `unsync.loop` event loop executed from 
`unsync.thread`
+* Regular functions will execute in `unsync.thread_executor`, a 
`ThreadPoolExecutor`
+  * Useful for IO bounded work that does not support `asyncio`
+* Regular functions marked with `@unsync(cpu_bound=True)` will execute in 
`unsync.process_executor`, a `ProcessPoolExecutor`
+  * Useful for CPU bounded work
+
+All `@unsync` functions will return an `Unfuture` object.
+This new future type combines the behavior of `asyncio.Future` and 
`concurrent.Future` with the following changes:
+* `Unfuture.set_result` is threadsafe unlike `asyncio.Future`
+* `Unfuture` instances can be awaited, even if made from `concurrent.Future`
+* `Unfuture.result()` is a blocking operation *except* in 
`unsync.loop`/`unsync.thread` where
+    it behaves like `asyncio.Future.result` and will throw an exception if the 
future is not done
 
 # Examples
 ## Simple Sleep
 A simple sleeping example with `asyncio`:
 ```python
 async def sync_async():
-    await asyncio.sleep(0.1)
+    await asyncio.sleep(1)
     return 'I hate event loops'
 
-result = asyncio.run(sync_async())
-print(result)
+
+async def main():
+    future1 = asyncio.create_task(sync_async())
+    future2 = asyncio.create_task(sync_async())
+
+    await future1, future2
+
+    print(future1.result() + future2.result())
+
+asyncio.run(main())
+# Takes 1 second to run
 ```
 
 Same example with `unsync`:
 ```python
 @unsync
 async def unsync_async():
-    await asyncio.sleep(0.1)
+    await asyncio.sleep(1)
     return 'I like decorators'
 
-print(unsync_async().result())
+unfuture1 = unsync_async()
+unfuture2 = unsync_async()
+print(unfuture1.result() + unfuture2.result())
+# Takes 1 second to run
 ```
 
-## Threading a synchronous function
+## Multi-threading an IO-bound function
 Synchronous functions can be made to run asynchronously by executing them in a 
`concurrent.ThreadPoolExecutor`.
 This can be easily accomplished by marking the regular function `@unsync`.
 ```python
 @unsync
 def non_async_function(seconds):
     time.sleep(seconds)
-    return 'Run in parallel!'
+    return 'Run concurrently!'
 
 start = time.time()
 tasks = [non_async_function(0.1) for _ in range(10)]
@@ -55,11 +67,11 @@
 ```
 Which prints:
 
-    ['Run in parallel!', 'Run in parallel!', ...]
+    ['Run concurrently!', 'Run concurrently!', ...]
     Executed in 0.10807514190673828 seconds
 
 ## Continuations
-Using Unfuture.then chains asynchronous calls and returns an Unfuture that 
wraps both the source, and continuation.
+Using `Unfuture.then` chains asynchronous calls and returns an `Unfuture` that 
wraps both the source, and continuation.
 The continuation is invoked with the source Unfuture as the first argument.
 Continuations can be regular functions (which will execute synchronously), or 
`@unsync` functions.
 ```python
@@ -120,7 +132,7 @@
 
     {0: 2, 1: 4, 2: 6, 3: 8, 4: 10, 5: 12, 6: 14, 7: 16, 8: 18, 9: 20}
     Executed in 0.22115683555603027 seconds
-    
+
 ## Preserving typing
 As far as we know it is not possible to change the return type of a method or 
function using a decorator.
 Therefore, we need a workaround to properly use IntelliSense. You have three 
options in general:
@@ -143,4 +155,21 @@
 
     future_result = function_name('b')
     self.assertEqual('ba', future_result.result())
-   ```
\ No newline at end of file
+   ```
+
+## Custom Event Loops
+In order to use custom event loops, be sure to set the event loop policy 
before calling any `@unsync` methods.
+For example, to use `uvloop` simply:
+
+```python
+import unsync
+import uvloop
+
+@unsync
+async def main():
+    # Main entry-point.
+    ...
+
+uvloop.install() # Equivalent to 
asyncio.set_event_loop_policy(EventLoopPolicy())
+main()
+```
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unsync-1.3/examples/process_executor.py 
new/unsync-1.3.2/examples/process_executor.py
--- old/unsync-1.3/examples/process_executor.py 1970-01-01 01:00:00.000000000 
+0100
+++ new/unsync-1.3.2/examples/process_executor.py       2021-03-27 
23:23:06.000000000 +0100
@@ -0,0 +1,22 @@
+import time
+
+from unsync import unsync
+
+
+def cpu_bound_function(operations):
+    for i in range(int(operations)):
+        pass
+    return 'Run in parallel!'
+
+# Could also be applied as a decorator above
+unsync_cpu_bound_function = unsync(cpu_bound=True)(cpu_bound_function)
+
+if __name__ == "__main__":
+    start = time.time()
+    print([cpu_bound_function(5e7) for _ in range(10)])
+    print('Non-unsync executed in {} seconds'.format(time.time() - start))
+
+    start = time.time()
+    tasks = [unsync_cpu_bound_function(5e7) for _ in range(10)]
+    print([task.result() for task in tasks])
+    print('unsync executed in {} seconds'.format(time.time() - start))
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unsync-1.3/setup.py new/unsync-1.3.2/setup.py
--- old/unsync-1.3/setup.py     2020-12-29 04:48:53.000000000 +0100
+++ new/unsync-1.3.2/setup.py   2021-03-27 23:23:06.000000000 +0100
@@ -3,7 +3,7 @@
 
 setup(
     name='unsync',
-    version='1.3',
+    version='1.3.2',
     packages=['unsync'],
     url='https://github.com/alex-sherman/unsync',
     license='MIT',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unsync-1.3/test/test_custom_event_loop.py 
new/unsync-1.3.2/test/test_custom_event_loop.py
--- old/unsync-1.3/test/test_custom_event_loop.py       1970-01-01 
01:00:00.000000000 +0100
+++ new/unsync-1.3.2/test/test_custom_event_loop.py     2021-03-27 
23:23:06.000000000 +0100
@@ -0,0 +1,23 @@
+from unittest import TestCase
+import asyncio
+
+from unsync import unsync
+
+
+class TestEventLoopPolicy(asyncio.DefaultEventLoopPolicy):
+    def new_event_loop(self):
+        loop = super().new_event_loop()
+        loop.derp = "faff"
+        return loop
+
+asyncio.set_event_loop_policy(TestEventLoopPolicy())
+
+
+class CustomEventTest(TestCase):
+    def test_custom_event_loop(self):
+        @unsync
+        async def method():
+            return True
+
+        self.assertTrue(method().result())
+        self.assertEqual(unsync.loop.derp, "faff")
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/unsync-1.3/unsync/unsync.py 
new/unsync-1.3.2/unsync/unsync.py
--- old/unsync-1.3/unsync/unsync.py     2020-12-29 04:48:53.000000000 +0100
+++ new/unsync-1.3.2/unsync/unsync.py   2021-03-27 23:23:06.000000000 +0100
@@ -7,16 +7,39 @@
 from threading import Thread
 from typing import Generic, TypeVar
 
+class unsync_meta(type):
 
-class unsync(object):
+    def _init_loop(cls):
+        cls._loop = asyncio.new_event_loop()
+        cls._thread = Thread(target=cls._thread_target, args=(cls._loop,), 
daemon=True)
+        cls._thread.start()
+
+    @property
+    def loop(cls):
+        if getattr(cls, '_loop', None) is None:
+            unsync_meta._init_loop(cls)
+        return cls._loop
+
+    @property
+    def thread(cls):
+        if getattr(cls, '_thread', None) is None:
+            unsync_meta._init_loop(cls)
+        return cls._thread
+
+    @property
+    def process_executor(cls):
+        if getattr(cls, '_process_executor', None) is None:
+            cls._process_executor = concurrent.futures.ProcessPoolExecutor()
+        return cls._process_executor
+
+
+class unsync(object, metaclass=unsync_meta):
     thread_executor = concurrent.futures.ThreadPoolExecutor()
     process_executor = None
-    loop = asyncio.new_event_loop()
-    thread = None
     unsync_functions = {}
 
     @staticmethod
-    def thread_target(loop):
+    def _thread_target(loop):
         asyncio.set_event_loop(loop)
         loop.run_forever()
 
@@ -52,8 +75,6 @@
             future = self.func(*args, **kwargs)
         else:
             if self.cpu_bound:
-                if unsync.process_executor is None:
-                    unsync.process_executor = 
concurrent.futures.ProcessPoolExecutor()
                 future = unsync.process_executor.submit(
                     _multiprocess_target, (self.func.__module__, 
self.func.__name__), *args, **kwargs)
             else:
@@ -136,6 +157,3 @@
             return await result
         return result
 
-
-unsync.thread = Thread(target=unsync.thread_target, args=(unsync.loop,), 
daemon=True)
-unsync.thread.start()

Reply via email to