cengal.parallel_execution.coroutines.integrations.qt.pyside6.versions.v_0.pyside6

  1#!/usr/bin/env python
  2# coding=utf-8
  3
  4# Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>
  5# 
  6# Licensed under the Apache License, Version 2.0 (the "License");
  7# you may not use this file except in compliance with the License.
  8# You may obtain a copy of the License at
  9# 
 10#     http://www.apache.org/licenses/LICENSE-2.0
 11# 
 12# Unless required by applicable law or agreed to in writing, software
 13# distributed under the License is distributed on an "AS IS" BASIS,
 14# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 15# See the License for the specific language governing permissions and
 16# limitations under the License.
 17
 18
 19__all__ = [
 20    'WrongQtVersion', 
 21    'exec_app', 
 22    'execa', 
 23    'aemit_signal', 
 24    'aemit', 
 25    'by_coro', 
 26    'aby_coro', 
 27    'modal_blocking', 
 28    'amodal_blocking', 
 29    'block_main_loop', 
 30    'ablock_main_loop', 
 31    'modal', 
 32    'amodal', 
 33    'CoroSlot', 
 34    'CSlot', 
 35    'coro_slot_implicit', 
 36    'cslot_implicit', 
 37    'csloti', 
 38    'csi', 
 39    'coro_slot_gly_patched', 
 40    'cslot_gly_patched', 
 41    'cslotglyp', 
 42    'cslotgp', 
 43    'csgp', 
 44    'coro_slot_agly_patched', 
 45    'cslot_agly_patched', 
 46    'cslotaglyp', 
 47    'cslotagp', 
 48    'csagp', 
 49    'coro_slot_explicit', 
 50    'cslot_explicit', 
 51    'cslotex', 
 52    'csex', 
 53    'qt_exec_in_coro', 
 54    'aqt_exec_in_coro', 
 55    'CoroThreadWorker', 
 56    'CoroThreadWithWorker',
 57]
 58
 59
 60"""
 61Module Docstring
 62Docstrings: http://www.python.org/dev/peps/pep-0257/
 63"""
 64
 65__author__ = "ButenkoMS <gtalk@butenkoms.space>"
 66__copyright__ = "Copyright © 2012-2024 ButenkoMS. All rights reserved. Contacts: <gtalk@butenkoms.space>"
 67__credits__ = ["ButenkoMS <gtalk@butenkoms.space>", ]
 68__license__ = "Apache License, Version 2.0"
 69__version__ = "4.4.1"
 70__maintainer__ = "ButenkoMS <gtalk@butenkoms.space>"
 71__email__ = "gtalk@butenkoms.space"
 72# __status__ = "Prototype"
 73__status__ = "Development"
 74# __status__ = "Production"
 75
 76
 77from cengal.parallel_execution.coroutines.coro_scheduler import CoroScheduler, CoroSchedulerType, Interface, Coro, AnyWorker, current_interface, current_coro_scheduler, cs_coro, cs_acoro
 78from cengal.parallel_execution.coroutines.coro_standard_services.loop_yield import gly, CoroPriority, gly_patched, agly_patched
 79from cengal.parallel_execution.coroutines.coro_standard_services.run_coro import RunCoro
 80from cengal.parallel_execution.coroutines.coro_standard_services.put_coro import PutCoro
 81from cengal.parallel_execution.coroutines.coro_standard_services.asyncio_loop import AsyncioLoopRequest
 82from cengal.parallel_execution.coroutines.coro_standard_services.async_event_bus import AsyncEventBusRequest, try_send_async_event
 83from cengal.parallel_execution.coroutines.coro_standard_services.simple_yield import Yield
 84from cengal.parallel_execution.coroutines.coro_standard_services.shutdown_loop import ShutdownLoop
 85from cengal.parallel_execution.coroutines.coro_standard_services.instance import InstanceRequest
 86from cengal.parallel_execution.coroutines.coro_tools.run_in_loop import run_in_loop
 87from cengal.parallel_execution.coroutines.integrations.qt.common.exceptions import WrongQtVersion
 88from cengal.code_flow_control.smart_values import ValueHolder
 89from cengal.data_generation.id_generator import IDGenerator
 90
 91from PySide6.QtCore import Slot, QObject, Qt, QTimer, Signal, QThread
 92from PySide6.QtWidgets import QApplication
 93
 94from inspect import signature, Signature
 95from contextlib import contextmanager, asynccontextmanager
 96from functools import wraps, update_wrapper, partial
 97from typing import Optional, Any, Callable, Hashable
 98
 99
100YIELD_ALLOWED_EVENT = 'QT_yield_allowed_event'
101YIELD_IN_WORK_EVENT = 'QT_yield_in_work_event'
102MODAL_RESULT_EVENT = 'QT_modal_result_event'
103MODAL_COUNTER = IDGenerator()
104
105
106def exec_app(app, default_priority: CoroPriority = CoroPriority.normal) -> int:
107    if not isinstance(app, QApplication):
108        raise WrongQtVersion('Qt version is not PySide6')
109    
110    timer = QTimer()
111    ly = gly(default_priority)
112    yield_allowed: ValueHolder[bool] = ValueHolder(True, True)
113    yield_in_work: ValueHolder[bool] = ValueHolder(True, True)
114    def yield_func():
115        if yield_allowed.value:
116            yield_in_work.value = True
117            ly()
118        else:
119            yield_in_work.value = False
120
121    i: Interface = current_interface()
122    i(InstanceRequest().set(YIELD_ALLOWED_EVENT, yield_allowed))
123    i(InstanceRequest().set(YIELD_IN_WORK_EVENT, yield_in_work))
124    timer.timeout.connect(yield_func, Qt.ConnectionType.QueuedConnection)
125    timer.start(0)
126    def cleanup_callback():
127        timer.stop()
128
129    app.aboutToQuit.connect(cleanup_callback)
130    return app.exec()
131
132
133execa = exec_app
134
135
136async def aemit_signal(signal, *args, **kwargs):
137    i: Interface = current_interface()
138    def coro(i: Interface):
139        signal.emit(*args, **kwargs)
140    
141    return await i(RunCoro, coro)
142
143
144aemit = aemit_signal
145
146
147def by_coro(callable: Callable, *args, **kwargs):
148    def coro(i: Interface):
149        callable(*args, **kwargs)
150    
151    return current_interface()(RunCoro, coro)
152
153
154async def aby_coro(callable: Callable, *args, **kwargs):
155    def coro(i: Interface):
156        callable(*args, **kwargs)
157    
158    return await current_interface()(RunCoro, coro)
159
160
161def stop_yield_to_main_loop():
162    i: Interface = current_interface()
163    yield_allowed: ValueHolder[bool] = i(InstanceRequest().wait(YIELD_ALLOWED_EVENT))
164    yield_allowed.value = False
165    yield_in_work: ValueHolder[bool] = i(InstanceRequest().wait(YIELD_IN_WORK_EVENT))
166    while yield_in_work.value:
167        i(Yield)
168
169
170@contextmanager
171def block_main_loop():
172    i: Interface = current_interface()
173    yield_allowed: ValueHolder[bool] = i(InstanceRequest().wait(YIELD_ALLOWED_EVENT))
174    yield_allowed.value = False
175    yield_in_work: ValueHolder[bool] = i(InstanceRequest().wait(YIELD_IN_WORK_EVENT))
176    while yield_in_work.value:
177        i(Yield)
178    
179    try:
180        yield
181    finally:
182        yield_allowed.value = True
183
184
185@asynccontextmanager
186async def ablock_main_loop():
187    i: Interface = current_interface()
188    yield_allowed: ValueHolder[bool] = await i(InstanceRequest().wait(YIELD_ALLOWED_EVENT))
189    yield_allowed.value = False
190    yield_in_work: ValueHolder[bool] = await i(InstanceRequest().wait(YIELD_IN_WORK_EVENT))
191    while yield_in_work.value:
192        await i(Yield)
193    
194    try:
195        yield
196    finally:
197        yield_allowed.value = True
198
199
200def modal_blocking(modal_obj, *args, **kwargs):
201    with block_main_loop():
202        return modal_obj(*args, **kwargs)
203
204
205async def amodal_blocking(modal_obj, *args, **kwargs):
206    async with ablock_main_loop():
207        return modal_obj(*args, **kwargs)
208
209
210def modal(callable_with_modal, *args, **kwargs):
211    class ShowModal(QObject):
212        signal = Signal()
213
214        def __init__(self, cs: CoroSchedulerType, result_event: Hashable):
215            super().__init__()
216            self.cs: CoroSchedulerType = cs
217            self.result_event: Hashable = result_event
218            self.signal.connect(self.show_modal, Qt.ConnectionType.QueuedConnection)
219
220        def show_modal(self):
221            result = callable_with_modal(*args, **kwargs)
222            try_send_async_event(self.cs, self.result_event, result)
223
224    event = (MODAL_RESULT_EVENT, MODAL_COUNTER())
225    sm: ShowModal = ShowModal(current_coro_scheduler(), event)
226    sm.signal.emit()
227    i: Interface = current_interface()
228    return i(AsyncEventBusRequest().wait(event))
229
230
231async def amodal(callable_with_modal, *args, **kwargs):
232    class ShowModal(QObject):
233        signal = Signal()
234
235        def __init__(self, cs: CoroSchedulerType, result_event: Hashable):
236            super().__init__()
237            self.cs: CoroSchedulerType = cs
238            self.result_event: Hashable = result_event
239            self.signal.connect(self.show_modal, Qt.ConnectionType.QueuedConnection)
240
241        def show_modal(self):
242            result = callable_with_modal(*args, **kwargs)
243            try_send_async_event(self.cs, self.result_event, result)
244
245    event = (MODAL_RESULT_EVENT, MODAL_COUNTER())
246    sm: ShowModal = ShowModal(current_coro_scheduler(), event)
247    sm.signal.emit()
248    i: Interface = current_interface()
249    return await i(AsyncEventBusRequest().wait(event))
250
251
252# class CoroSlot(QObject):
253class CoroSlot:
254    def __init__(self, *types: type, name: Optional[str] = None, result: Optional[str] = None) -> None:
255        self._types = types
256        self._name = name
257        self._result = result
258        self._coro = None
259
260    def __call__(self, coro: Coro, method = None) -> Any:
261        method = method or self.implicit_coro_impl
262        return method(coro)
263
264    def implicit_coro_impl(self, coro: Coro) -> Any:
265        self._coro = coro
266
267        def func_wrapper(*args, **kwargs):
268            cs: CoroSchedulerType = current_coro_scheduler()
269            service: PutCoro = cs.get_service_instance(PutCoro)
270            return service._add_direct_request(cs_coro(coro), *args, **kwargs)
271        
272        coro_worker_sign: Signature = signature(coro)
273        update_wrapper(func_wrapper, coro)
274        func_wrapper.__signature__ = coro_worker_sign.replace(parameters=tuple(coro_worker_sign.parameters.values()), return_annotation=coro_worker_sign.return_annotation)
275        return Slot(*self._types, self._name, self._result)(func_wrapper)
276    
277    def implicit_coro(self):
278        return partial(self, method=self.implicit_coro_impl)
279    
280    ic = implicit_coro
281
282    def gly_patched_function_impl(self, func: Callable) -> Any:
283        return self.__call__(gly_patched(func))
284
285    def gly_patched_function(self) -> Any:
286        return partial(self, method=self.gly_patched_function_impl)
287    
288    glypf = gly_patched_function
289    gpf = gly_patched_function
290    gp = gly_patched_function
291
292    def agly_patched_function_impl(self, afunc: Callable) -> Any:
293        return self.__call__(agly_patched(afunc))
294
295    def agly_patched_function(self) -> Any:
296        return partial(self, method=self.agly_patched_function_impl)
297    
298    aglypf = agly_patched_function
299    agpf = agly_patched_function
300    agp = agly_patched_function
301
302    def explicit_coro_impl(self, coro: Coro) -> Any:
303        self._coro = coro
304
305        def func_wrapper(*args, **kwargs):
306            cs: CoroSchedulerType = current_coro_scheduler()
307            service: PutCoro = cs.get_service_instance(PutCoro)
308            return service._add_direct_request(coro, *args, **kwargs)
309        
310        coro_worker_sign: Signature = signature(coro)
311        update_wrapper(func_wrapper, coro)
312        func_wrapper.__signature__ = coro_worker_sign.replace(parameters=tuple(coro_worker_sign.parameters.values())[1:], return_annotation=coro_worker_sign.return_annotation)
313        return Slot(*self._types, self._name, self._result)(func_wrapper)
314
315    def explicit_coro(self) -> Any:
316        return partial(self, method=self.explicit_coro_impl)
317    
318    ec = explicit_coro
319    interface = explicit_coro
320    i = interface
321
322
323CSlot = CoroSlot
324
325
326def coro_slot_implicit(*types: type, name: Optional[str] = None, result: Optional[str] = None):
327    def decorator(coro: Coro) -> Any:
328        return CoroSlot(*types, name=name, result=result).implicit_coro()(coro)
329    
330    return decorator
331
332cslot_implicit = coro_slot_implicit
333csloti = coro_slot_implicit
334csi = coro_slot_implicit
335
336
337def coro_slot_gly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
338    def decorator(func: Callable) -> Any:
339        return CoroSlot(*types, name=name, result=result).gly_patched_function()(func)
340    
341    return decorator
342
343cslot_gly_patched = coro_slot_gly_patched
344cslotglyp = coro_slot_gly_patched
345cslotgp = coro_slot_gly_patched
346csgp = coro_slot_gly_patched
347
348
349def coro_slot_agly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
350    def decorator(afunc: Callable) -> Any:
351        return CoroSlot(*types, name=name, result=result).agly_patched_function()(afunc)
352    
353    return decorator
354
355cslot_agly_patched = coro_slot_agly_patched
356cslotaglyp = coro_slot_agly_patched
357cslotagp = coro_slot_agly_patched
358csagp = coro_slot_gly_patched
359
360
361def coro_slot_explicit(*types: type, name: Optional[str] = None, result: Optional[str] = None):
362    def decorator(coro: Coro) -> Any:
363        return CoroSlot(*types, name=name, result=result).explicit_coro()(coro)
364    
365    return decorator
366
367cslot_explicit = coro_slot_explicit
368cslotex = coro_slot_explicit
369csex = coro_slot_explicit
370
371
372def qt_exec_in_coro(func: Callable, default_priority: CoroPriority = CoroPriority.normal) -> Callable:
373    @wraps(func)
374    def wrapper(*args, **kwargs):
375        cs: CoroSchedulerType = current_coro_scheduler()
376        cs.high_cpu_utilisation_mode = False
377        cs.use_internal_sleep = False
378        i: Interface = current_interface()
379        i(AsyncioLoopRequest().use_higher_level_sleep_manager())
380        i(AsyncioLoopRequest().ensure_loop(interrupt_when_no_requests=True))
381        i(AsyncioLoopRequest().turn_on_loops_intercommunication())
382
383        app_or_tuple = func(*args, **kwargs)
384        on_exit = lambda ret: ret
385        if isinstance(app_or_tuple, QApplication):
386            app = app_or_tuple
387        elif isinstance(app_or_tuple, tuple):
388            app, on_exit = app_or_tuple
389        else:
390            raise RuntimeError("qt_exec_in_coro must return either QApplication or (QApplication, on_exit) tuple")
391        
392        # Run the event loop
393        ret = i(RunCoro, cs_coro(execa), app, default_priority)
394        ret = i(RunCoro, cs_coro(on_exit), ret)
395        i(ShutdownLoop)
396        return ret
397    
398    return cs_coro(wrapper)
399
400
401async def aqt_exec_in_coro(func: Callable, default_priority: CoroPriority = CoroPriority.normal) -> Callable:
402    @wraps(func)
403    async def wrapper(*args, **kwargs):
404        i: Interface = current_interface()
405        await i(AsyncioLoopRequest().ensure_loop(interrupt_when_no_requests=True))
406        await i(AsyncioLoopRequest().turn_on_loops_intercommunication())
407
408        app_or_tuple = func(*args, **kwargs)
409        on_exit = lambda ret: ret
410        if isinstance(app_or_tuple, QApplication):
411            app = app_or_tuple
412        else:
413            app, on_exit = app_or_tuple
414        
415        ret = await i(RunCoro, cs_coro(execa), app, default_priority)
416        ret = await i(RunCoro, cs_coro(on_exit), ret)
417        await i(ShutdownLoop)
418        return ret
419    
420    return cs_acoro(wrapper)
421
422
423class CoroThreadWorker(QObject):
424    def __init__(self, worker: AnyWorker) -> None:
425        super().__init__()
426        self._worker: AnyWorker = worker
427        self._cs: CoroSchedulerType = None
428        self.allowed_to_run = False
429
430    def run(self):
431        self.allowed_to_run = True
432        async def my_worker_wrapper(i: Interface, worker):
433            self._cs = current_coro_scheduler()
434            await i(RunCoro, self.setup)
435            await i(RunCoro, worker)
436        
437        run_in_loop(my_worker_wrapper, self._worker)
438    
439    async def setup(self, i: Interface):
440        await i(AsyncioLoopRequest().ensure_loop(interrupt_when_no_requests=True))
441        await i(AsyncioLoopRequest().turn_on_loops_intercommunication())
442
443    def stop(self):
444        if not self.allowed_to_run:
445            return
446
447        self.allowed_to_run = False
448        async def coro(i: Interface):
449            await i(ShutdownLoop)
450        
451        if self._cs is not None:
452            service: PutCoro = self._cs.get_service_instance(PutCoro)
453            return service._add_direct_request(coro)
454
455
456class CoroThread(QThread):
457    def __init__(self, parent, worker: CoroThreadWorker) -> None:
458        super().__init__(parent)
459        self._worker: CoroThreadWorker = worker
460        self._worker.moveToThread(self)
461        self.started.connect(self._worker.run)
462    
463    def stop(self):
464        self.quit()
465        self.wait()
466
467
468class CoroThreadWithWorker(CoroThreadWorker):
469    def __init__(self, parent, worker: AnyWorker) -> None:
470        super().__init__(worker)
471        self._thread: CoroThread = CoroThread(parent, self)
472    
473    def start(self):
474        self._thread.start()
475    
476    def stop(self):
477        super().stop()
478        self._thread.stop()
class WrongQtVersion(builtins.Exception):
40class WrongQtVersion(Exception):
41    pass

Common base class for all non-exit exceptions.

Inherited Members
builtins.Exception
Exception
builtins.BaseException
with_traceback
args
def exec_app( app, default_priority: cengal.parallel_execution.coroutines.coro_standard_services.loop_yield.versions.v_0.loop_yield.CoroPriority = <CoroPriority.normal: 1>) -> int:
107def exec_app(app, default_priority: CoroPriority = CoroPriority.normal) -> int:
108    if not isinstance(app, QApplication):
109        raise WrongQtVersion('Qt version is not PySide6')
110    
111    timer = QTimer()
112    ly = gly(default_priority)
113    yield_allowed: ValueHolder[bool] = ValueHolder(True, True)
114    yield_in_work: ValueHolder[bool] = ValueHolder(True, True)
115    def yield_func():
116        if yield_allowed.value:
117            yield_in_work.value = True
118            ly()
119        else:
120            yield_in_work.value = False
121
122    i: Interface = current_interface()
123    i(InstanceRequest().set(YIELD_ALLOWED_EVENT, yield_allowed))
124    i(InstanceRequest().set(YIELD_IN_WORK_EVENT, yield_in_work))
125    timer.timeout.connect(yield_func, Qt.ConnectionType.QueuedConnection)
126    timer.start(0)
127    def cleanup_callback():
128        timer.stop()
129
130    app.aboutToQuit.connect(cleanup_callback)
131    return app.exec()
def execa( app, default_priority: cengal.parallel_execution.coroutines.coro_standard_services.loop_yield.versions.v_0.loop_yield.CoroPriority = <CoroPriority.normal: 1>) -> int:
107def exec_app(app, default_priority: CoroPriority = CoroPriority.normal) -> int:
108    if not isinstance(app, QApplication):
109        raise WrongQtVersion('Qt version is not PySide6')
110    
111    timer = QTimer()
112    ly = gly(default_priority)
113    yield_allowed: ValueHolder[bool] = ValueHolder(True, True)
114    yield_in_work: ValueHolder[bool] = ValueHolder(True, True)
115    def yield_func():
116        if yield_allowed.value:
117            yield_in_work.value = True
118            ly()
119        else:
120            yield_in_work.value = False
121
122    i: Interface = current_interface()
123    i(InstanceRequest().set(YIELD_ALLOWED_EVENT, yield_allowed))
124    i(InstanceRequest().set(YIELD_IN_WORK_EVENT, yield_in_work))
125    timer.timeout.connect(yield_func, Qt.ConnectionType.QueuedConnection)
126    timer.start(0)
127    def cleanup_callback():
128        timer.stop()
129
130    app.aboutToQuit.connect(cleanup_callback)
131    return app.exec()
async def aemit_signal(signal, *args, **kwargs):
137async def aemit_signal(signal, *args, **kwargs):
138    i: Interface = current_interface()
139    def coro(i: Interface):
140        signal.emit(*args, **kwargs)
141    
142    return await i(RunCoro, coro)
async def aemit(signal, *args, **kwargs):
137async def aemit_signal(signal, *args, **kwargs):
138    i: Interface = current_interface()
139    def coro(i: Interface):
140        signal.emit(*args, **kwargs)
141    
142    return await i(RunCoro, coro)
def by_coro(callable: Callable, *args, **kwargs):
148def by_coro(callable: Callable, *args, **kwargs):
149    def coro(i: Interface):
150        callable(*args, **kwargs)
151    
152    return current_interface()(RunCoro, coro)
async def aby_coro(callable: Callable, *args, **kwargs):
155async def aby_coro(callable: Callable, *args, **kwargs):
156    def coro(i: Interface):
157        callable(*args, **kwargs)
158    
159    return await current_interface()(RunCoro, coro)
async def amodal_blocking(modal_obj, *args, **kwargs):
206async def amodal_blocking(modal_obj, *args, **kwargs):
207    async with ablock_main_loop():
208        return modal_obj(*args, **kwargs)
@contextmanager
def block_main_loop():
171@contextmanager
172def block_main_loop():
173    i: Interface = current_interface()
174    yield_allowed: ValueHolder[bool] = i(InstanceRequest().wait(YIELD_ALLOWED_EVENT))
175    yield_allowed.value = False
176    yield_in_work: ValueHolder[bool] = i(InstanceRequest().wait(YIELD_IN_WORK_EVENT))
177    while yield_in_work.value:
178        i(Yield)
179    
180    try:
181        yield
182    finally:
183        yield_allowed.value = True
@asynccontextmanager
async def ablock_main_loop():
186@asynccontextmanager
187async def ablock_main_loop():
188    i: Interface = current_interface()
189    yield_allowed: ValueHolder[bool] = await i(InstanceRequest().wait(YIELD_ALLOWED_EVENT))
190    yield_allowed.value = False
191    yield_in_work: ValueHolder[bool] = await i(InstanceRequest().wait(YIELD_IN_WORK_EVENT))
192    while yield_in_work.value:
193        await i(Yield)
194    
195    try:
196        yield
197    finally:
198        yield_allowed.value = True
async def amodal(callable_with_modal, *args, **kwargs):
232async def amodal(callable_with_modal, *args, **kwargs):
233    class ShowModal(QObject):
234        signal = Signal()
235
236        def __init__(self, cs: CoroSchedulerType, result_event: Hashable):
237            super().__init__()
238            self.cs: CoroSchedulerType = cs
239            self.result_event: Hashable = result_event
240            self.signal.connect(self.show_modal, Qt.ConnectionType.QueuedConnection)
241
242        def show_modal(self):
243            result = callable_with_modal(*args, **kwargs)
244            try_send_async_event(self.cs, self.result_event, result)
245
246    event = (MODAL_RESULT_EVENT, MODAL_COUNTER())
247    sm: ShowModal = ShowModal(current_coro_scheduler(), event)
248    sm.signal.emit()
249    i: Interface = current_interface()
250    return await i(AsyncEventBusRequest().wait(event))
class CoroSlot:
254class CoroSlot:
255    def __init__(self, *types: type, name: Optional[str] = None, result: Optional[str] = None) -> None:
256        self._types = types
257        self._name = name
258        self._result = result
259        self._coro = None
260
261    def __call__(self, coro: Coro, method = None) -> Any:
262        method = method or self.implicit_coro_impl
263        return method(coro)
264
265    def implicit_coro_impl(self, coro: Coro) -> Any:
266        self._coro = coro
267
268        def func_wrapper(*args, **kwargs):
269            cs: CoroSchedulerType = current_coro_scheduler()
270            service: PutCoro = cs.get_service_instance(PutCoro)
271            return service._add_direct_request(cs_coro(coro), *args, **kwargs)
272        
273        coro_worker_sign: Signature = signature(coro)
274        update_wrapper(func_wrapper, coro)
275        func_wrapper.__signature__ = coro_worker_sign.replace(parameters=tuple(coro_worker_sign.parameters.values()), return_annotation=coro_worker_sign.return_annotation)
276        return Slot(*self._types, self._name, self._result)(func_wrapper)
277    
278    def implicit_coro(self):
279        return partial(self, method=self.implicit_coro_impl)
280    
281    ic = implicit_coro
282
283    def gly_patched_function_impl(self, func: Callable) -> Any:
284        return self.__call__(gly_patched(func))
285
286    def gly_patched_function(self) -> Any:
287        return partial(self, method=self.gly_patched_function_impl)
288    
289    glypf = gly_patched_function
290    gpf = gly_patched_function
291    gp = gly_patched_function
292
293    def agly_patched_function_impl(self, afunc: Callable) -> Any:
294        return self.__call__(agly_patched(afunc))
295
296    def agly_patched_function(self) -> Any:
297        return partial(self, method=self.agly_patched_function_impl)
298    
299    aglypf = agly_patched_function
300    agpf = agly_patched_function
301    agp = agly_patched_function
302
303    def explicit_coro_impl(self, coro: Coro) -> Any:
304        self._coro = coro
305
306        def func_wrapper(*args, **kwargs):
307            cs: CoroSchedulerType = current_coro_scheduler()
308            service: PutCoro = cs.get_service_instance(PutCoro)
309            return service._add_direct_request(coro, *args, **kwargs)
310        
311        coro_worker_sign: Signature = signature(coro)
312        update_wrapper(func_wrapper, coro)
313        func_wrapper.__signature__ = coro_worker_sign.replace(parameters=tuple(coro_worker_sign.parameters.values())[1:], return_annotation=coro_worker_sign.return_annotation)
314        return Slot(*self._types, self._name, self._result)(func_wrapper)
315
316    def explicit_coro(self) -> Any:
317        return partial(self, method=self.explicit_coro_impl)
318    
319    ec = explicit_coro
320    interface = explicit_coro
321    i = interface
CoroSlot( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None)
255    def __init__(self, *types: type, name: Optional[str] = None, result: Optional[str] = None) -> None:
256        self._types = types
257        self._name = name
258        self._result = result
259        self._coro = None
def implicit_coro_impl( self, coro: Union[greenlet.greenlet, Awaitable, Coroutine, Generator, AsyncGenerator, Callable]) -> Any:
265    def implicit_coro_impl(self, coro: Coro) -> Any:
266        self._coro = coro
267
268        def func_wrapper(*args, **kwargs):
269            cs: CoroSchedulerType = current_coro_scheduler()
270            service: PutCoro = cs.get_service_instance(PutCoro)
271            return service._add_direct_request(cs_coro(coro), *args, **kwargs)
272        
273        coro_worker_sign: Signature = signature(coro)
274        update_wrapper(func_wrapper, coro)
275        func_wrapper.__signature__ = coro_worker_sign.replace(parameters=tuple(coro_worker_sign.parameters.values()), return_annotation=coro_worker_sign.return_annotation)
276        return Slot(*self._types, self._name, self._result)(func_wrapper)
def implicit_coro(self):
278    def implicit_coro(self):
279        return partial(self, method=self.implicit_coro_impl)
def ic(self):
278    def implicit_coro(self):
279        return partial(self, method=self.implicit_coro_impl)
def gly_patched_function_impl(self, func: Callable) -> Any:
283    def gly_patched_function_impl(self, func: Callable) -> Any:
284        return self.__call__(gly_patched(func))
def gly_patched_function(self) -> Any:
286    def gly_patched_function(self) -> Any:
287        return partial(self, method=self.gly_patched_function_impl)
def glypf(self) -> Any:
286    def gly_patched_function(self) -> Any:
287        return partial(self, method=self.gly_patched_function_impl)
def gpf(self) -> Any:
286    def gly_patched_function(self) -> Any:
287        return partial(self, method=self.gly_patched_function_impl)
def gp(self) -> Any:
286    def gly_patched_function(self) -> Any:
287        return partial(self, method=self.gly_patched_function_impl)
def agly_patched_function_impl(self, afunc: Callable) -> Any:
293    def agly_patched_function_impl(self, afunc: Callable) -> Any:
294        return self.__call__(agly_patched(afunc))
def agly_patched_function(self) -> Any:
296    def agly_patched_function(self) -> Any:
297        return partial(self, method=self.agly_patched_function_impl)
def aglypf(self) -> Any:
296    def agly_patched_function(self) -> Any:
297        return partial(self, method=self.agly_patched_function_impl)
def agpf(self) -> Any:
296    def agly_patched_function(self) -> Any:
297        return partial(self, method=self.agly_patched_function_impl)
def agp(self) -> Any:
296    def agly_patched_function(self) -> Any:
297        return partial(self, method=self.agly_patched_function_impl)
def explicit_coro_impl( self, coro: Union[greenlet.greenlet, Awaitable, Coroutine, Generator, AsyncGenerator, Callable]) -> Any:
303    def explicit_coro_impl(self, coro: Coro) -> Any:
304        self._coro = coro
305
306        def func_wrapper(*args, **kwargs):
307            cs: CoroSchedulerType = current_coro_scheduler()
308            service: PutCoro = cs.get_service_instance(PutCoro)
309            return service._add_direct_request(coro, *args, **kwargs)
310        
311        coro_worker_sign: Signature = signature(coro)
312        update_wrapper(func_wrapper, coro)
313        func_wrapper.__signature__ = coro_worker_sign.replace(parameters=tuple(coro_worker_sign.parameters.values())[1:], return_annotation=coro_worker_sign.return_annotation)
314        return Slot(*self._types, self._name, self._result)(func_wrapper)
def explicit_coro(self) -> Any:
316    def explicit_coro(self) -> Any:
317        return partial(self, method=self.explicit_coro_impl)
def ec(self) -> Any:
316    def explicit_coro(self) -> Any:
317        return partial(self, method=self.explicit_coro_impl)
def interface(self) -> Any:
316    def explicit_coro(self) -> Any:
317        return partial(self, method=self.explicit_coro_impl)
def i(self) -> Any:
316    def explicit_coro(self) -> Any:
317        return partial(self, method=self.explicit_coro_impl)
CSlot = <class 'CoroSlot'>
def coro_slot_implicit( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
327def coro_slot_implicit(*types: type, name: Optional[str] = None, result: Optional[str] = None):
328    def decorator(coro: Coro) -> Any:
329        return CoroSlot(*types, name=name, result=result).implicit_coro()(coro)
330    
331    return decorator
def cslot_implicit( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
327def coro_slot_implicit(*types: type, name: Optional[str] = None, result: Optional[str] = None):
328    def decorator(coro: Coro) -> Any:
329        return CoroSlot(*types, name=name, result=result).implicit_coro()(coro)
330    
331    return decorator
def csloti( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
327def coro_slot_implicit(*types: type, name: Optional[str] = None, result: Optional[str] = None):
328    def decorator(coro: Coro) -> Any:
329        return CoroSlot(*types, name=name, result=result).implicit_coro()(coro)
330    
331    return decorator
def csi( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
327def coro_slot_implicit(*types: type, name: Optional[str] = None, result: Optional[str] = None):
328    def decorator(coro: Coro) -> Any:
329        return CoroSlot(*types, name=name, result=result).implicit_coro()(coro)
330    
331    return decorator
def coro_slot_gly_patched( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
338def coro_slot_gly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
339    def decorator(func: Callable) -> Any:
340        return CoroSlot(*types, name=name, result=result).gly_patched_function()(func)
341    
342    return decorator
def cslot_gly_patched( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
338def coro_slot_gly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
339    def decorator(func: Callable) -> Any:
340        return CoroSlot(*types, name=name, result=result).gly_patched_function()(func)
341    
342    return decorator
def cslotglyp( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
338def coro_slot_gly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
339    def decorator(func: Callable) -> Any:
340        return CoroSlot(*types, name=name, result=result).gly_patched_function()(func)
341    
342    return decorator
def cslotgp( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
338def coro_slot_gly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
339    def decorator(func: Callable) -> Any:
340        return CoroSlot(*types, name=name, result=result).gly_patched_function()(func)
341    
342    return decorator
def csgp( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
338def coro_slot_gly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
339    def decorator(func: Callable) -> Any:
340        return CoroSlot(*types, name=name, result=result).gly_patched_function()(func)
341    
342    return decorator
def coro_slot_agly_patched( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
350def coro_slot_agly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
351    def decorator(afunc: Callable) -> Any:
352        return CoroSlot(*types, name=name, result=result).agly_patched_function()(afunc)
353    
354    return decorator
def cslot_agly_patched( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
350def coro_slot_agly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
351    def decorator(afunc: Callable) -> Any:
352        return CoroSlot(*types, name=name, result=result).agly_patched_function()(afunc)
353    
354    return decorator
def cslotaglyp( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
350def coro_slot_agly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
351    def decorator(afunc: Callable) -> Any:
352        return CoroSlot(*types, name=name, result=result).agly_patched_function()(afunc)
353    
354    return decorator
def cslotagp( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
350def coro_slot_agly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
351    def decorator(afunc: Callable) -> Any:
352        return CoroSlot(*types, name=name, result=result).agly_patched_function()(afunc)
353    
354    return decorator
def csagp( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
338def coro_slot_gly_patched(*types: type, name: Optional[str] = None, result: Optional[str] = None):
339    def decorator(func: Callable) -> Any:
340        return CoroSlot(*types, name=name, result=result).gly_patched_function()(func)
341    
342    return decorator
def coro_slot_explicit( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
362def coro_slot_explicit(*types: type, name: Optional[str] = None, result: Optional[str] = None):
363    def decorator(coro: Coro) -> Any:
364        return CoroSlot(*types, name=name, result=result).explicit_coro()(coro)
365    
366    return decorator
def cslot_explicit( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
362def coro_slot_explicit(*types: type, name: Optional[str] = None, result: Optional[str] = None):
363    def decorator(coro: Coro) -> Any:
364        return CoroSlot(*types, name=name, result=result).explicit_coro()(coro)
365    
366    return decorator
def cslotex( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
362def coro_slot_explicit(*types: type, name: Optional[str] = None, result: Optional[str] = None):
363    def decorator(coro: Coro) -> Any:
364        return CoroSlot(*types, name=name, result=result).explicit_coro()(coro)
365    
366    return decorator
def csex( *types: type, name: Union[str, NoneType] = None, result: Union[str, NoneType] = None):
362def coro_slot_explicit(*types: type, name: Optional[str] = None, result: Optional[str] = None):
363    def decorator(coro: Coro) -> Any:
364        return CoroSlot(*types, name=name, result=result).explicit_coro()(coro)
365    
366    return decorator
def qt_exec_in_coro( func: Callable, default_priority: cengal.parallel_execution.coroutines.coro_standard_services.loop_yield.versions.v_0.loop_yield.CoroPriority = <CoroPriority.normal: 1>) -> Callable:
373def qt_exec_in_coro(func: Callable, default_priority: CoroPriority = CoroPriority.normal) -> Callable:
374    @wraps(func)
375    def wrapper(*args, **kwargs):
376        cs: CoroSchedulerType = current_coro_scheduler()
377        cs.high_cpu_utilisation_mode = False
378        cs.use_internal_sleep = False
379        i: Interface = current_interface()
380        i(AsyncioLoopRequest().use_higher_level_sleep_manager())
381        i(AsyncioLoopRequest().ensure_loop(interrupt_when_no_requests=True))
382        i(AsyncioLoopRequest().turn_on_loops_intercommunication())
383
384        app_or_tuple = func(*args, **kwargs)
385        on_exit = lambda ret: ret
386        if isinstance(app_or_tuple, QApplication):
387            app = app_or_tuple
388        elif isinstance(app_or_tuple, tuple):
389            app, on_exit = app_or_tuple
390        else:
391            raise RuntimeError("qt_exec_in_coro must return either QApplication or (QApplication, on_exit) tuple")
392        
393        # Run the event loop
394        ret = i(RunCoro, cs_coro(execa), app, default_priority)
395        ret = i(RunCoro, cs_coro(on_exit), ret)
396        i(ShutdownLoop)
397        return ret
398    
399    return cs_coro(wrapper)
async def aqt_exec_in_coro( func: Callable, default_priority: cengal.parallel_execution.coroutines.coro_standard_services.loop_yield.versions.v_0.loop_yield.CoroPriority = <CoroPriority.normal: 1>) -> Callable:
402async def aqt_exec_in_coro(func: Callable, default_priority: CoroPriority = CoroPriority.normal) -> Callable:
403    @wraps(func)
404    async def wrapper(*args, **kwargs):
405        i: Interface = current_interface()
406        await i(AsyncioLoopRequest().ensure_loop(interrupt_when_no_requests=True))
407        await i(AsyncioLoopRequest().turn_on_loops_intercommunication())
408
409        app_or_tuple = func(*args, **kwargs)
410        on_exit = lambda ret: ret
411        if isinstance(app_or_tuple, QApplication):
412            app = app_or_tuple
413        else:
414            app, on_exit = app_or_tuple
415        
416        ret = await i(RunCoro, cs_coro(execa), app, default_priority)
417        ret = await i(RunCoro, cs_coro(on_exit), ret)
418        await i(ShutdownLoop)
419        return ret
420    
421    return cs_acoro(wrapper)
class CoroThreadWorker(PySide6.QtCore.QObject):
424class CoroThreadWorker(QObject):
425    def __init__(self, worker: AnyWorker) -> None:
426        super().__init__()
427        self._worker: AnyWorker = worker
428        self._cs: CoroSchedulerType = None
429        self.allowed_to_run = False
430
431    def run(self):
432        self.allowed_to_run = True
433        async def my_worker_wrapper(i: Interface, worker):
434            self._cs = current_coro_scheduler()
435            await i(RunCoro, self.setup)
436            await i(RunCoro, worker)
437        
438        run_in_loop(my_worker_wrapper, self._worker)
439    
440    async def setup(self, i: Interface):
441        await i(AsyncioLoopRequest().ensure_loop(interrupt_when_no_requests=True))
442        await i(AsyncioLoopRequest().turn_on_loops_intercommunication())
443
444    def stop(self):
445        if not self.allowed_to_run:
446            return
447
448        self.allowed_to_run = False
449        async def coro(i: Interface):
450            await i(ShutdownLoop)
451        
452        if self._cs is not None:
453            service: PutCoro = self._cs.get_service_instance(PutCoro)
454            return service._add_direct_request(coro)

QObject(self, parent: Union[PySide6.QtCore.QObject, NoneType] = None) -> None

CoroThreadWorker( worker: Union[cengal.parallel_execution.coroutines.coro_scheduler.versions.v_0.coro_scheduler.ExplicitWorker, collections.abc.Callable[cengal.parallel_execution.coroutines.coro_scheduler.versions.v_0.coro_scheduler.Interface, Any], collections.abc.Callable[cengal.parallel_execution.coroutines.coro_scheduler.versions.v_0.coro_scheduler.Interface, Awaitable[Any]]])
425    def __init__(self, worker: AnyWorker) -> None:
426        super().__init__()
427        self._worker: AnyWorker = worker
428        self._cs: CoroSchedulerType = None
429        self.allowed_to_run = False

__init__(self, parent: Union[PySide6.QtCore.QObject, NoneType] = None) -> None

Initialize self. See help(type(self)) for accurate signature.

allowed_to_run
def run(self):
431    def run(self):
432        self.allowed_to_run = True
433        async def my_worker_wrapper(i: Interface, worker):
434            self._cs = current_coro_scheduler()
435            await i(RunCoro, self.setup)
436            await i(RunCoro, worker)
437        
438        run_in_loop(my_worker_wrapper, self._worker)
async def setup( self, i: cengal.parallel_execution.coroutines.coro_scheduler.versions.v_0.coro_scheduler.Interface):
440    async def setup(self, i: Interface):
441        await i(AsyncioLoopRequest().ensure_loop(interrupt_when_no_requests=True))
442        await i(AsyncioLoopRequest().turn_on_loops_intercommunication())
def stop(self):
444    def stop(self):
445        if not self.allowed_to_run:
446            return
447
448        self.allowed_to_run = False
449        async def coro(i: Interface):
450            await i(ShutdownLoop)
451        
452        if self._cs is not None:
453            service: PutCoro = self._cs.get_service_instance(PutCoro)
454            return service._add_direct_request(coro)
staticMetaObject = PySide6.QtCore.QMetaObject("CoroThreadWorker" inherits "QObject": )
Inherited Members
PySide6.QtCore.QObject
blockSignals
childEvent
children
connect
connectNotify
customEvent
deleteLater
disconnect
disconnectNotify
dumpObjectInfo
dumpObjectTree
dynamicPropertyNames
emit
event
eventFilter
findChild
findChildren
inherits
installEventFilter
isQuickItemType
isSignalConnected
isWidgetType
isWindowType
killTimer
metaObject
moveToThread
objectName
parent
property
receivers
removeEventFilter
sender
senderSignalIndex
setObjectName
setParent
setProperty
signalsBlocked
startTimer
thread
timerEvent
tr
destroyed
objectNameChanged
class CoroThreadWithWorker(CoroThreadWorker):
469class CoroThreadWithWorker(CoroThreadWorker):
470    def __init__(self, parent, worker: AnyWorker) -> None:
471        super().__init__(worker)
472        self._thread: CoroThread = CoroThread(parent, self)
473    
474    def start(self):
475        self._thread.start()
476    
477    def stop(self):
478        super().stop()
479        self._thread.stop()

QObject(self, parent: Union[PySide6.QtCore.QObject, NoneType] = None) -> None

CoroThreadWithWorker( parent, worker: Union[cengal.parallel_execution.coroutines.coro_scheduler.versions.v_0.coro_scheduler.ExplicitWorker, collections.abc.Callable[cengal.parallel_execution.coroutines.coro_scheduler.versions.v_0.coro_scheduler.Interface, Any], collections.abc.Callable[cengal.parallel_execution.coroutines.coro_scheduler.versions.v_0.coro_scheduler.Interface, Awaitable[Any]]])
470    def __init__(self, parent, worker: AnyWorker) -> None:
471        super().__init__(worker)
472        self._thread: CoroThread = CoroThread(parent, self)

__init__(self, parent: Union[PySide6.QtCore.QObject, NoneType] = None) -> None

Initialize self. See help(type(self)) for accurate signature.

def start(self):
474    def start(self):
475        self._thread.start()
def stop(self):
477    def stop(self):
478        super().stop()
479        self._thread.stop()
staticMetaObject = PySide6.QtCore.QMetaObject("CoroThreadWithWorker" inherits "CoroThreadWorker": )
Inherited Members
PySide6.QtCore.QObject
blockSignals
childEvent
children
connect
connectNotify
customEvent
deleteLater
disconnect
disconnectNotify
dumpObjectInfo
dumpObjectTree
dynamicPropertyNames
emit
event
eventFilter
findChild
findChildren
inherits
installEventFilter
isQuickItemType
isSignalConnected
isWidgetType
isWindowType
killTimer
metaObject
moveToThread
objectName
parent
property
receivers
removeEventFilter
sender
senderSignalIndex
setObjectName
setParent
setProperty
signalsBlocked
startTimer
thread
timerEvent
tr
destroyed
objectNameChanged