Remove decorators and use async/await instead
This commit is contained in:
parent
a3627e7547
commit
7d189ce2e1
@ -1,4 +0,0 @@
|
||||
Decorators
|
||||
==========
|
||||
|
||||
.. autoclass:: gaphas.decorators.g_async
|
@ -57,7 +57,6 @@ Gaphas is released under the terms of the Apache Software License, version 2.0.
|
||||
quadtree
|
||||
table
|
||||
tree
|
||||
decorators
|
||||
|
||||
.. _Cairo: https://cairographics.org
|
||||
.. _Model-View-Controller: https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller
|
||||
|
@ -10,13 +10,16 @@ It sports a small canvas and some trivial operations:
|
||||
- Delete focused item
|
||||
- Exports to SVG and PNG
|
||||
"""
|
||||
import asyncio
|
||||
import math
|
||||
import sys
|
||||
|
||||
import cairo
|
||||
import gi
|
||||
from gi.events import GLibEventLoopPolicy
|
||||
|
||||
# fmt: off
|
||||
|
||||
gi.require_version("Gtk", "4.0")
|
||||
from gi.repository import Gtk
|
||||
# fmt: on
|
||||
@ -417,6 +420,7 @@ def main():
|
||||
|
||||
app.connect("activate", activate)
|
||||
|
||||
asyncio.set_event_loop_policy(GLibEventLoopPolicy())
|
||||
app.run()
|
||||
|
||||
|
||||
|
@ -1,103 +0,0 @@
|
||||
"""Custom decorators."""
|
||||
import functools
|
||||
import inspect
|
||||
import logging
|
||||
import threading
|
||||
|
||||
from gi.repository import GLib
|
||||
|
||||
log = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class g_async:
|
||||
"""Instead of calling the function, schedule an idle handler at a given
|
||||
priority. This requires the async'ed method to be called from within the
|
||||
GTK main loop. Otherwise the method is executed directly.
|
||||
|
||||
If a function's first argument is "self", it's considered a method.
|
||||
|
||||
Calling the async function from outside the gtk main loop will
|
||||
yield immediate execution.
|
||||
|
||||
A function can also be a generator. The generator will be fully executed.
|
||||
If run in the main loop, an empty iterator will be returned.
|
||||
A generator is "single" by default. Because of the nature of generators
|
||||
the first invocation will run till completion.
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
single: bool = False,
|
||||
timeout: int = 0,
|
||||
priority: int = GLib.PRIORITY_DEFAULT_IDLE,
|
||||
) -> None:
|
||||
self.single = single
|
||||
self.timeout = timeout
|
||||
self.priority = priority
|
||||
|
||||
def source(self, func):
|
||||
timeout = self.timeout
|
||||
s = GLib.Timeout(timeout) if timeout > 0 else GLib.Idle()
|
||||
s.set_callback(func)
|
||||
s.priority = self.priority
|
||||
return s
|
||||
|
||||
def __call__(self, func):
|
||||
is_method = inspect.getfullargspec(func).args[:1] == ["self"]
|
||||
is_generator = inspect.isgeneratorfunction(func)
|
||||
source_attr = f"__g_async__{func.__name__}"
|
||||
|
||||
@functools.wraps(func)
|
||||
def wrapper(*args, **kwargs):
|
||||
# execute directly if we're not in the main loop
|
||||
if GLib.main_depth() == 0:
|
||||
return func(*args, **kwargs)
|
||||
elif is_generator:
|
||||
# We can only run one generator at a time
|
||||
holder = args[0] if is_method else func
|
||||
source = getattr(holder, source_attr, 0)
|
||||
if source:
|
||||
return
|
||||
|
||||
iterator = func(*args, **kwargs)
|
||||
|
||||
def async_wrapper(*_args):
|
||||
try:
|
||||
next(iterator)
|
||||
except Exception:
|
||||
delattr(holder, source_attr)
|
||||
return GLib.SOURCE_REMOVE
|
||||
return GLib.SOURCE_CONTINUE
|
||||
|
||||
source = self.source(async_wrapper)
|
||||
setattr(holder, source_attr, source)
|
||||
source.attach()
|
||||
return ()
|
||||
elif self.single:
|
||||
# Idle handlers should be registered per instance
|
||||
holder = args[0] if is_method else func
|
||||
source = getattr(holder, source_attr, 0)
|
||||
if source:
|
||||
return
|
||||
|
||||
def async_wrapper(*_args):
|
||||
log.debug("async: %s %s %s", func, args, kwargs)
|
||||
try:
|
||||
func(*args, **kwargs)
|
||||
finally:
|
||||
delattr(holder, source_attr)
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
||||
source = self.source(async_wrapper)
|
||||
setattr(holder, source_attr, source)
|
||||
source.attach()
|
||||
else:
|
||||
|
||||
def async_wrapper(*_args):
|
||||
log.debug("async: %s %s %s", func, args, kwargs)
|
||||
func(*args, **kwargs)
|
||||
return GLib.SOURCE_REMOVE
|
||||
|
||||
self.source(async_wrapper).attach()
|
||||
|
||||
return wrapper
|
@ -1,13 +1,13 @@
|
||||
"""This module contains everything to display a model on a screen."""
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from math import isclose
|
||||
from collections.abc import Collection, Iterable
|
||||
|
||||
import cairo
|
||||
from gi.repository import Graphene, GLib, GObject, Gtk
|
||||
from gi.repository import Graphene, GObject, Gtk
|
||||
|
||||
from gaphas.decorators import g_async
|
||||
from gaphas.geometry import Rect, Rectangle
|
||||
from gaphas.item import Item
|
||||
from gaphas.matrix import Matrix
|
||||
@ -88,6 +88,8 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable):
|
||||
self._back_buffer: cairo.Surface | None = None
|
||||
self._back_buffer_needs_resizing = True
|
||||
|
||||
self._update_task: asyncio.Task | None = None
|
||||
|
||||
self._controllers: set[Gtk.EventController] = set()
|
||||
|
||||
self.set_can_focus(True)
|
||||
@ -152,6 +154,8 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable):
|
||||
self._selection.clear()
|
||||
self._dirty_items.clear()
|
||||
self._qtree.clear()
|
||||
if self._update_task:
|
||||
self._update_task.cancel()
|
||||
|
||||
self._model = model
|
||||
|
||||
@ -277,22 +281,31 @@ class GtkView(Gtk.DrawingArea, Gtk.Scrollable):
|
||||
if items or removed_items:
|
||||
self.update()
|
||||
|
||||
@g_async(single=True, priority=GLib.PRIORITY_DEFAULT)
|
||||
def update(self) -> None:
|
||||
def update(self) -> asyncio.Task:
|
||||
"""Update view status according to the items updated in the model."""
|
||||
model = self._model
|
||||
if not model:
|
||||
return
|
||||
|
||||
dirty_items = self.all_dirty_items()
|
||||
model.update_now(dirty_items)
|
||||
dirty_items |= self.all_dirty_items()
|
||||
async def _update():
|
||||
model = self._model
|
||||
if not model:
|
||||
return
|
||||
|
||||
old_bb = self._qtree.soft_bounds
|
||||
self.update_bounding_box(dirty_items)
|
||||
if self._qtree.soft_bounds != old_bb:
|
||||
self.update_scrolling()
|
||||
self.update_back_buffer()
|
||||
dirty_items = self.all_dirty_items()
|
||||
model.update_now(dirty_items)
|
||||
dirty_items |= self.all_dirty_items()
|
||||
|
||||
old_bb = self._qtree.soft_bounds
|
||||
self.update_bounding_box(dirty_items)
|
||||
if self._qtree.soft_bounds != old_bb:
|
||||
self.update_scrolling()
|
||||
self.update_back_buffer()
|
||||
|
||||
def clear_task(task):
|
||||
self._update_task = None
|
||||
|
||||
if not self._update_task:
|
||||
self._update_task = asyncio.create_task(_update())
|
||||
self._update_task.add_done_callback(clear_task)
|
||||
return self._update_task
|
||||
|
||||
def all_dirty_items(self) -> set[Item]:
|
||||
"""Return all dirty items, clearing the marked items."""
|
||||
|
232
poetry.lock
generated
232
poetry.lock
generated
@ -13,13 +13,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "babel"
|
||||
version = "2.15.0"
|
||||
version = "2.16.0"
|
||||
description = "Internationalization utilities"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"},
|
||||
{file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"},
|
||||
{file = "babel-2.16.0-py3-none-any.whl", hash = "sha256:368b5b98b37c06b7daf6696391c3240c938b37767d4584413e8438c5c435fa8b"},
|
||||
{file = "babel-2.16.0.tar.gz", hash = "sha256:d1f3554ca26605fe173f3de0c65f750f5a42f924499bf134de6423582298e316"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@ -169,63 +169,83 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "coverage"
|
||||
version = "7.5.3"
|
||||
version = "7.6.1"
|
||||
description = "Code coverage measurement for Python"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "coverage-7.5.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:a6519d917abb15e12380406d721e37613e2a67d166f9fb7e5a8ce0375744cd45"},
|
||||
{file = "coverage-7.5.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:aea7da970f1feccf48be7335f8b2ca64baf9b589d79e05b9397a06696ce1a1ec"},
|
||||
{file = "coverage-7.5.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:923b7b1c717bd0f0f92d862d1ff51d9b2b55dbbd133e05680204465f454bb286"},
|
||||
{file = "coverage-7.5.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62bda40da1e68898186f274f832ef3e759ce929da9a9fd9fcf265956de269dbc"},
|
||||
{file = "coverage-7.5.3-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d8b7339180d00de83e930358223c617cc343dd08e1aa5ec7b06c3a121aec4e1d"},
|
||||
{file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:25a5caf742c6195e08002d3b6c2dd6947e50efc5fc2c2205f61ecb47592d2d83"},
|
||||
{file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:05ac5f60faa0c704c0f7e6a5cbfd6f02101ed05e0aee4d2822637a9e672c998d"},
|
||||
{file = "coverage-7.5.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:239a4e75e09c2b12ea478d28815acf83334d32e722e7433471fbf641c606344c"},
|
||||
{file = "coverage-7.5.3-cp310-cp310-win32.whl", hash = "sha256:a5812840d1d00eafae6585aba38021f90a705a25b8216ec7f66aebe5b619fb84"},
|
||||
{file = "coverage-7.5.3-cp310-cp310-win_amd64.whl", hash = "sha256:33ca90a0eb29225f195e30684ba4a6db05dbef03c2ccd50b9077714c48153cac"},
|
||||
{file = "coverage-7.5.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f81bc26d609bf0fbc622c7122ba6307993c83c795d2d6f6f6fd8c000a770d974"},
|
||||
{file = "coverage-7.5.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7cec2af81f9e7569280822be68bd57e51b86d42e59ea30d10ebdbb22d2cb7232"},
|
||||
{file = "coverage-7.5.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:55f689f846661e3f26efa535071775d0483388a1ccfab899df72924805e9e7cd"},
|
||||
{file = "coverage-7.5.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:50084d3516aa263791198913a17354bd1dc627d3c1639209640b9cac3fef5807"},
|
||||
{file = "coverage-7.5.3-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:341dd8f61c26337c37988345ca5c8ccabeff33093a26953a1ac72e7d0103c4fb"},
|
||||
{file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:ab0b028165eea880af12f66086694768f2c3139b2c31ad5e032c8edbafca6ffc"},
|
||||
{file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:5bc5a8c87714b0c67cfeb4c7caa82b2d71e8864d1a46aa990b5588fa953673b8"},
|
||||
{file = "coverage-7.5.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:38a3b98dae8a7c9057bd91fbf3415c05e700a5114c5f1b5b0ea5f8f429ba6614"},
|
||||
{file = "coverage-7.5.3-cp311-cp311-win32.whl", hash = "sha256:fcf7d1d6f5da887ca04302db8e0e0cf56ce9a5e05f202720e49b3e8157ddb9a9"},
|
||||
{file = "coverage-7.5.3-cp311-cp311-win_amd64.whl", hash = "sha256:8c836309931839cca658a78a888dab9676b5c988d0dd34ca247f5f3e679f4e7a"},
|
||||
{file = "coverage-7.5.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:296a7d9bbc598e8744c00f7a6cecf1da9b30ae9ad51c566291ff1314e6cbbed8"},
|
||||
{file = "coverage-7.5.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:34d6d21d8795a97b14d503dcaf74226ae51eb1f2bd41015d3ef332a24d0a17b3"},
|
||||
{file = "coverage-7.5.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8e317953bb4c074c06c798a11dbdd2cf9979dbcaa8ccc0fa4701d80042d4ebf1"},
|
||||
{file = "coverage-7.5.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:705f3d7c2b098c40f5b81790a5fedb274113373d4d1a69e65f8b68b0cc26f6db"},
|
||||
{file = "coverage-7.5.3-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1196e13c45e327d6cd0b6e471530a1882f1017eb83c6229fc613cd1a11b53cd"},
|
||||
{file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:015eddc5ccd5364dcb902eaecf9515636806fa1e0d5bef5769d06d0f31b54523"},
|
||||
{file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:fd27d8b49e574e50caa65196d908f80e4dff64d7e592d0c59788b45aad7e8b35"},
|
||||
{file = "coverage-7.5.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:33fc65740267222fc02975c061eb7167185fef4cc8f2770267ee8bf7d6a42f84"},
|
||||
{file = "coverage-7.5.3-cp312-cp312-win32.whl", hash = "sha256:7b2a19e13dfb5c8e145c7a6ea959485ee8e2204699903c88c7d25283584bfc08"},
|
||||
{file = "coverage-7.5.3-cp312-cp312-win_amd64.whl", hash = "sha256:0bbddc54bbacfc09b3edaec644d4ac90c08ee8ed4844b0f86227dcda2d428fcb"},
|
||||
{file = "coverage-7.5.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:f78300789a708ac1f17e134593f577407d52d0417305435b134805c4fb135adb"},
|
||||
{file = "coverage-7.5.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b368e1aee1b9b75757942d44d7598dcd22a9dbb126affcbba82d15917f0cc155"},
|
||||
{file = "coverage-7.5.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f836c174c3a7f639bded48ec913f348c4761cbf49de4a20a956d3431a7c9cb24"},
|
||||
{file = "coverage-7.5.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:244f509f126dc71369393ce5fea17c0592c40ee44e607b6d855e9c4ac57aac98"},
|
||||
{file = "coverage-7.5.3-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4c2872b3c91f9baa836147ca33650dc5c172e9273c808c3c3199c75490e709d"},
|
||||
{file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:dd4b3355b01273a56b20c219e74e7549e14370b31a4ffe42706a8cda91f19f6d"},
|
||||
{file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:f542287b1489c7a860d43a7d8883e27ca62ab84ca53c965d11dac1d3a1fab7ce"},
|
||||
{file = "coverage-7.5.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:75e3f4e86804023e991096b29e147e635f5e2568f77883a1e6eed74512659ab0"},
|
||||
{file = "coverage-7.5.3-cp38-cp38-win32.whl", hash = "sha256:c59d2ad092dc0551d9f79d9d44d005c945ba95832a6798f98f9216ede3d5f485"},
|
||||
{file = "coverage-7.5.3-cp38-cp38-win_amd64.whl", hash = "sha256:fa21a04112c59ad54f69d80e376f7f9d0f5f9123ab87ecd18fbb9ec3a2beed56"},
|
||||
{file = "coverage-7.5.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:f5102a92855d518b0996eb197772f5ac2a527c0ec617124ad5242a3af5e25f85"},
|
||||
{file = "coverage-7.5.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d1da0a2e3b37b745a2b2a678a4c796462cf753aebf94edcc87dcc6b8641eae31"},
|
||||
{file = "coverage-7.5.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8383a6c8cefba1b7cecc0149415046b6fc38836295bc4c84e820872eb5478b3d"},
|
||||
{file = "coverage-7.5.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9aad68c3f2566dfae84bf46295a79e79d904e1c21ccfc66de88cd446f8686341"},
|
||||
{file = "coverage-7.5.3-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2e079c9ec772fedbade9d7ebc36202a1d9ef7291bc9b3a024ca395c4d52853d7"},
|
||||
{file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:bde997cac85fcac227b27d4fb2c7608a2c5f6558469b0eb704c5726ae49e1c52"},
|
||||
{file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:990fb20b32990b2ce2c5f974c3e738c9358b2735bc05075d50a6f36721b8f303"},
|
||||
{file = "coverage-7.5.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:3d5a67f0da401e105753d474369ab034c7bae51a4c31c77d94030d59e41df5bd"},
|
||||
{file = "coverage-7.5.3-cp39-cp39-win32.whl", hash = "sha256:e08c470c2eb01977d221fd87495b44867a56d4d594f43739a8028f8646a51e0d"},
|
||||
{file = "coverage-7.5.3-cp39-cp39-win_amd64.whl", hash = "sha256:1d2a830ade66d3563bb61d1e3c77c8def97b30ed91e166c67d0632c018f380f0"},
|
||||
{file = "coverage-7.5.3-pp38.pp39.pp310-none-any.whl", hash = "sha256:3538d8fb1ee9bdd2e2692b3b18c22bb1c19ffbefd06880f5ac496e42d7bb3884"},
|
||||
{file = "coverage-7.5.3.tar.gz", hash = "sha256:04aefca5190d1dc7a53a4c1a5a7f8568811306d7a8ee231c42fb69215571944f"},
|
||||
{file = "coverage-7.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b06079abebbc0e89e6163b8e8f0e16270124c154dc6e4a47b413dd538859af16"},
|
||||
{file = "coverage-7.6.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cf4b19715bccd7ee27b6b120e7e9dd56037b9c0681dcc1adc9ba9db3d417fa36"},
|
||||
{file = "coverage-7.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e61c0abb4c85b095a784ef23fdd4aede7a2628478e7baba7c5e3deba61070a02"},
|
||||
{file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:fd21f6ae3f08b41004dfb433fa895d858f3f5979e7762d052b12aef444e29afc"},
|
||||
{file = "coverage-7.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f59d57baca39b32db42b83b2a7ba6f47ad9c394ec2076b084c3f029b7afca23"},
|
||||
{file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a1ac0ae2b8bd743b88ed0502544847c3053d7171a3cff9228af618a068ed9c34"},
|
||||
{file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:e6a08c0be454c3b3beb105c0596ebdc2371fab6bb90c0c0297f4e58fd7e1012c"},
|
||||
{file = "coverage-7.6.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f5796e664fe802da4f57a168c85359a8fbf3eab5e55cd4e4569fbacecc903959"},
|
||||
{file = "coverage-7.6.1-cp310-cp310-win32.whl", hash = "sha256:7bb65125fcbef8d989fa1dd0e8a060999497629ca5b0efbca209588a73356232"},
|
||||
{file = "coverage-7.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:3115a95daa9bdba70aea750db7b96b37259a81a709223c8448fa97727d546fe0"},
|
||||
{file = "coverage-7.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:7dea0889685db8550f839fa202744652e87c60015029ce3f60e006f8c4462c93"},
|
||||
{file = "coverage-7.6.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ed37bd3c3b063412f7620464a9ac1314d33100329f39799255fb8d3027da50d3"},
|
||||
{file = "coverage-7.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d85f5e9a5f8b73e2350097c3756ef7e785f55bd71205defa0bfdaf96c31616ff"},
|
||||
{file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9bc572be474cafb617672c43fe989d6e48d3c83af02ce8de73fff1c6bb3c198d"},
|
||||
{file = "coverage-7.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c0420b573964c760df9e9e86d1a9a622d0d27f417e1a949a8a66dd7bcee7bc6"},
|
||||
{file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1f4aa8219db826ce6be7099d559f8ec311549bfc4046f7f9fe9b5cea5c581c56"},
|
||||
{file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:fc5a77d0c516700ebad189b587de289a20a78324bc54baee03dd486f0855d234"},
|
||||
{file = "coverage-7.6.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:b48f312cca9621272ae49008c7f613337c53fadca647d6384cc129d2996d1133"},
|
||||
{file = "coverage-7.6.1-cp311-cp311-win32.whl", hash = "sha256:1125ca0e5fd475cbbba3bb67ae20bd2c23a98fac4e32412883f9bcbaa81c314c"},
|
||||
{file = "coverage-7.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:8ae539519c4c040c5ffd0632784e21b2f03fc1340752af711f33e5be83a9d6c6"},
|
||||
{file = "coverage-7.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:95cae0efeb032af8458fc27d191f85d1717b1d4e49f7cb226cf526ff28179778"},
|
||||
{file = "coverage-7.6.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:5621a9175cf9d0b0c84c2ef2b12e9f5f5071357c4d2ea6ca1cf01814f45d2391"},
|
||||
{file = "coverage-7.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:260933720fdcd75340e7dbe9060655aff3af1f0c5d20f46b57f262ab6c86a5e8"},
|
||||
{file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:07e2ca0ad381b91350c0ed49d52699b625aab2b44b65e1b4e02fa9df0e92ad2d"},
|
||||
{file = "coverage-7.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c44fee9975f04b33331cb8eb272827111efc8930cfd582e0320613263ca849ca"},
|
||||
{file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:877abb17e6339d96bf08e7a622d05095e72b71f8afd8a9fefc82cf30ed944163"},
|
||||
{file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3e0cadcf6733c09154b461f1ca72d5416635e5e4ec4e536192180d34ec160f8a"},
|
||||
{file = "coverage-7.6.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c3c02d12f837d9683e5ab2f3d9844dc57655b92c74e286c262e0fc54213c216d"},
|
||||
{file = "coverage-7.6.1-cp312-cp312-win32.whl", hash = "sha256:e05882b70b87a18d937ca6768ff33cc3f72847cbc4de4491c8e73880766718e5"},
|
||||
{file = "coverage-7.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:b5d7b556859dd85f3a541db6a4e0167b86e7273e1cdc973e5b175166bb634fdb"},
|
||||
{file = "coverage-7.6.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a4acd025ecc06185ba2b801f2de85546e0b8ac787cf9d3b06e7e2a69f925b106"},
|
||||
{file = "coverage-7.6.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:a6d3adcf24b624a7b778533480e32434a39ad8fa30c315208f6d3e5542aeb6e9"},
|
||||
{file = "coverage-7.6.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0c212c49b6c10e6951362f7c6df3329f04c2b1c28499563d4035d964ab8e08c"},
|
||||
{file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e81d7a3e58882450ec4186ca59a3f20a5d4440f25b1cff6f0902ad890e6748a"},
|
||||
{file = "coverage-7.6.1-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:78b260de9790fd81e69401c2dc8b17da47c8038176a79092a89cb2b7d945d060"},
|
||||
{file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:a78d169acd38300060b28d600344a803628c3fd585c912cacc9ea8790fe96862"},
|
||||
{file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2c09f4ce52cb99dd7505cd0fc8e0e37c77b87f46bc9c1eb03fe3bc9991085388"},
|
||||
{file = "coverage-7.6.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:6878ef48d4227aace338d88c48738a4258213cd7b74fd9a3d4d7582bb1d8a155"},
|
||||
{file = "coverage-7.6.1-cp313-cp313-win32.whl", hash = "sha256:44df346d5215a8c0e360307d46ffaabe0f5d3502c8a1cefd700b34baf31d411a"},
|
||||
{file = "coverage-7.6.1-cp313-cp313-win_amd64.whl", hash = "sha256:8284cf8c0dd272a247bc154eb6c95548722dce90d098c17a883ed36e67cdb129"},
|
||||
{file = "coverage-7.6.1-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:d3296782ca4eab572a1a4eca686d8bfb00226300dcefdf43faa25b5242ab8a3e"},
|
||||
{file = "coverage-7.6.1-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:502753043567491d3ff6d08629270127e0c31d4184c4c8d98f92c26f65019962"},
|
||||
{file = "coverage-7.6.1-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6a89ecca80709d4076b95f89f308544ec8f7b4727e8a547913a35f16717856cb"},
|
||||
{file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a318d68e92e80af8b00fa99609796fdbcdfef3629c77c6283566c6f02c6d6704"},
|
||||
{file = "coverage-7.6.1-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13b0a73a0896988f053e4fbb7de6d93388e6dd292b0d87ee51d106f2c11b465b"},
|
||||
{file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:4421712dbfc5562150f7554f13dde997a2e932a6b5f352edcce948a815efee6f"},
|
||||
{file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:166811d20dfea725e2e4baa71fffd6c968a958577848d2131f39b60043400223"},
|
||||
{file = "coverage-7.6.1-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:225667980479a17db1048cb2bf8bfb39b8e5be8f164b8f6628b64f78a72cf9d3"},
|
||||
{file = "coverage-7.6.1-cp313-cp313t-win32.whl", hash = "sha256:170d444ab405852903b7d04ea9ae9b98f98ab6d7e63e1115e82620807519797f"},
|
||||
{file = "coverage-7.6.1-cp313-cp313t-win_amd64.whl", hash = "sha256:b9f222de8cded79c49bf184bdbc06630d4c58eec9459b939b4a690c82ed05657"},
|
||||
{file = "coverage-7.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:6db04803b6c7291985a761004e9060b2bca08da6d04f26a7f2294b8623a0c1a0"},
|
||||
{file = "coverage-7.6.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:f1adfc8ac319e1a348af294106bc6a8458a0f1633cc62a1446aebc30c5fa186a"},
|
||||
{file = "coverage-7.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a95324a9de9650a729239daea117df21f4b9868ce32e63f8b650ebe6cef5595b"},
|
||||
{file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b43c03669dc4618ec25270b06ecd3ee4fa94c7f9b3c14bae6571ca00ef98b0d3"},
|
||||
{file = "coverage-7.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8929543a7192c13d177b770008bc4e8119f2e1f881d563fc6b6305d2d0ebe9de"},
|
||||
{file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:a09ece4a69cf399510c8ab25e0950d9cf2b42f7b3cb0374f95d2e2ff594478a6"},
|
||||
{file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9054a0754de38d9dbd01a46621636689124d666bad1936d76c0341f7d71bf569"},
|
||||
{file = "coverage-7.6.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0dbde0f4aa9a16fa4d754356a8f2e36296ff4d83994b2c9d8398aa32f222f989"},
|
||||
{file = "coverage-7.6.1-cp38-cp38-win32.whl", hash = "sha256:da511e6ad4f7323ee5702e6633085fb76c2f893aaf8ce4c51a0ba4fc07580ea7"},
|
||||
{file = "coverage-7.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:3f1156e3e8f2872197af3840d8ad307a9dd18e615dc64d9ee41696f287c57ad8"},
|
||||
{file = "coverage-7.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:abd5fd0db5f4dc9289408aaf34908072f805ff7792632250dcb36dc591d24255"},
|
||||
{file = "coverage-7.6.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:547f45fa1a93154bd82050a7f3cddbc1a7a4dd2a9bf5cb7d06f4ae29fe94eaf8"},
|
||||
{file = "coverage-7.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:645786266c8f18a931b65bfcefdbf6952dd0dea98feee39bd188607a9d307ed2"},
|
||||
{file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9e0b2df163b8ed01d515807af24f63de04bebcecbd6c3bfeff88385789fdf75a"},
|
||||
{file = "coverage-7.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:609b06f178fe8e9f89ef676532760ec0b4deea15e9969bf754b37f7c40326dbc"},
|
||||
{file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:702855feff378050ae4f741045e19a32d57d19f3e0676d589df0575008ea5004"},
|
||||
{file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:2bdb062ea438f22d99cba0d7829c2ef0af1d768d1e4a4f528087224c90b132cb"},
|
||||
{file = "coverage-7.6.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:9c56863d44bd1c4fe2abb8a4d6f5371d197f1ac0ebdee542f07f35895fc07f36"},
|
||||
{file = "coverage-7.6.1-cp39-cp39-win32.whl", hash = "sha256:6e2cd258d7d927d09493c8df1ce9174ad01b381d4729a9d8d4e38670ca24774c"},
|
||||
{file = "coverage-7.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:06a737c882bd26d0d6ee7269b20b12f14a8704807a01056c80bb881a4b2ce6ca"},
|
||||
{file = "coverage-7.6.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:e9a6e0eb86070e8ccaedfbd9d38fec54864f3125ab95419970575b42af7541df"},
|
||||
{file = "coverage-7.6.1.tar.gz", hash = "sha256:953510dfb7b12ab69d20135a0662397f077c59b1e6379a768e97c59d852ee51d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
@ -247,13 +267,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "exceptiongroup"
|
||||
version = "1.2.1"
|
||||
version = "1.2.2"
|
||||
description = "Backport of PEP 654 (exception groups)"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
files = [
|
||||
{file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"},
|
||||
{file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"},
|
||||
{file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"},
|
||||
{file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
@ -300,22 +320,22 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "importlib-metadata"
|
||||
version = "7.1.0"
|
||||
version = "8.2.0"
|
||||
description = "Read metadata from Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"},
|
||||
{file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"},
|
||||
{file = "importlib_metadata-8.2.0-py3-none-any.whl", hash = "sha256:11901fa0c2f97919b288679932bb64febaeacf289d18ac84dd68cb2e74213369"},
|
||||
{file = "importlib_metadata-8.2.0.tar.gz", hash = "sha256:72e8d4399996132204f9a16dcc751af254a48f8d1b20b9ff0f98d4a8f901e73d"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
zipp = ">=0.5"
|
||||
|
||||
[package.extras]
|
||||
docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
perf = ["ipython"]
|
||||
testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"]
|
||||
test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "iniconfig"
|
||||
@ -416,13 +436,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "packaging"
|
||||
version = "24.0"
|
||||
version = "24.1"
|
||||
description = "Core utilities for Python packages"
|
||||
optional = false
|
||||
python-versions = ">=3.7"
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"},
|
||||
{file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"},
|
||||
{file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"},
|
||||
{file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -526,6 +546,24 @@ pytest = ">=7.2"
|
||||
[package.extras]
|
||||
dev = ["black", "check-manifest", "check-wheel-contents", "coverage", "flake8", "mypy", "pyroma"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-asyncio"
|
||||
version = "0.23.8"
|
||||
description = "Pytest support for asyncio"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "pytest_asyncio-0.23.8-py3-none-any.whl", hash = "sha256:50265d892689a5faefb84df80819d1ecef566eb3549cf915dfb33569359d1ce2"},
|
||||
{file = "pytest_asyncio-0.23.8.tar.gz", hash = "sha256:759b10b33a6dc61cce40a8bd5205e302978bbbcc00e279a8b61d9a6a3c82e4d3"},
|
||||
]
|
||||
|
||||
[package.dependencies]
|
||||
pytest = ">=7.0.0,<9"
|
||||
|
||||
[package.extras]
|
||||
docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"]
|
||||
testing = ["coverage (>=6.2)", "hypothesis (>=5.7.1)"]
|
||||
|
||||
[[package]]
|
||||
name = "pytest-cov"
|
||||
version = "5.0.0"
|
||||
@ -578,13 +616,13 @@ files = [
|
||||
|
||||
[[package]]
|
||||
name = "soupsieve"
|
||||
version = "2.5"
|
||||
version = "2.6"
|
||||
description = "A modern CSS selector implementation for Beautiful Soup."
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "soupsieve-2.5-py3-none-any.whl", hash = "sha256:eaa337ff55a1579b6549dc679565eac1e3d000563bcb1c8ab0d0fefbc0c2cdc7"},
|
||||
{file = "soupsieve-2.5.tar.gz", hash = "sha256:5663d5a7b3bfaeee0bc4372e7fc48f9cff4940b3eec54a6451cc5299f1097690"},
|
||||
{file = "soupsieve-2.6-py3-none-any.whl", hash = "sha256:e72c4ff06e4fb6e4b5a9f0f55fe6e81514581fca1515028625d0f299c602ccc9"},
|
||||
{file = "soupsieve-2.6.tar.gz", hash = "sha256:e2e68417777af359ec65daac1057404a3c8a5455bb8abc36f1a9866ab1a51abb"},
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@ -642,49 +680,49 @@ docs = ["furo", "ipython", "myst-parser", "sphinx-copybutton", "sphinx-inline-ta
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-applehelp"
|
||||
version = "1.0.8"
|
||||
version = "2.0.0"
|
||||
description = "sphinxcontrib-applehelp is a Sphinx extension which outputs Apple help books"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "sphinxcontrib_applehelp-1.0.8-py3-none-any.whl", hash = "sha256:cb61eb0ec1b61f349e5cc36b2028e9e7ca765be05e49641c97241274753067b4"},
|
||||
{file = "sphinxcontrib_applehelp-1.0.8.tar.gz", hash = "sha256:c40a4f96f3776c4393d933412053962fac2b84f4c99a7982ba42e09576a70619"},
|
||||
{file = "sphinxcontrib_applehelp-2.0.0-py3-none-any.whl", hash = "sha256:4cd3f0ec4ac5dd9c17ec65e9ab272c9b867ea77425228e68ecf08d6b28ddbdb5"},
|
||||
{file = "sphinxcontrib_applehelp-2.0.0.tar.gz", hash = "sha256:2f29ef331735ce958efa4734873f084941970894c6090408b079c61b2e1c06d1"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
lint = ["docutils-stubs", "flake8", "mypy"]
|
||||
lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
|
||||
standalone = ["Sphinx (>=5)"]
|
||||
test = ["pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-devhelp"
|
||||
version = "1.0.6"
|
||||
version = "2.0.0"
|
||||
description = "sphinxcontrib-devhelp is a sphinx extension which outputs Devhelp documents"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "sphinxcontrib_devhelp-1.0.6-py3-none-any.whl", hash = "sha256:6485d09629944511c893fa11355bda18b742b83a2b181f9a009f7e500595c90f"},
|
||||
{file = "sphinxcontrib_devhelp-1.0.6.tar.gz", hash = "sha256:9893fd3f90506bc4b97bdb977ceb8fbd823989f4316b28c3841ec128544372d3"},
|
||||
{file = "sphinxcontrib_devhelp-2.0.0-py3-none-any.whl", hash = "sha256:aefb8b83854e4b0998877524d1029fd3e6879210422ee3780459e28a1f03a8a2"},
|
||||
{file = "sphinxcontrib_devhelp-2.0.0.tar.gz", hash = "sha256:411f5d96d445d1d73bb5d52133377b4248ec79db5c793ce7dbe59e074b4dd1ad"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
lint = ["docutils-stubs", "flake8", "mypy"]
|
||||
lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
|
||||
standalone = ["Sphinx (>=5)"]
|
||||
test = ["pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-htmlhelp"
|
||||
version = "2.0.5"
|
||||
version = "2.1.0"
|
||||
description = "sphinxcontrib-htmlhelp is a sphinx extension which renders HTML help files"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "sphinxcontrib_htmlhelp-2.0.5-py3-none-any.whl", hash = "sha256:393f04f112b4d2f53d93448d4bce35842f62b307ccdc549ec1585e950bc35e04"},
|
||||
{file = "sphinxcontrib_htmlhelp-2.0.5.tar.gz", hash = "sha256:0dc87637d5de53dd5eec3a6a01753b1ccf99494bd756aafecd74b4fa9e729015"},
|
||||
{file = "sphinxcontrib_htmlhelp-2.1.0-py3-none-any.whl", hash = "sha256:166759820b47002d22914d64a075ce08f4c46818e17cfc9470a9786b759b19f8"},
|
||||
{file = "sphinxcontrib_htmlhelp-2.1.0.tar.gz", hash = "sha256:c9e2916ace8aad64cc13a0d233ee22317f2b9025b9cf3295249fa985cc7082e9"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
lint = ["docutils-stubs", "flake8", "mypy"]
|
||||
lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
|
||||
standalone = ["Sphinx (>=5)"]
|
||||
test = ["html5lib", "pytest"]
|
||||
|
||||
@ -704,33 +742,33 @@ test = ["flake8", "mypy", "pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-qthelp"
|
||||
version = "1.0.7"
|
||||
version = "2.0.0"
|
||||
description = "sphinxcontrib-qthelp is a sphinx extension which outputs QtHelp documents"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "sphinxcontrib_qthelp-1.0.7-py3-none-any.whl", hash = "sha256:e2ae3b5c492d58fcbd73281fbd27e34b8393ec34a073c792642cd8e529288182"},
|
||||
{file = "sphinxcontrib_qthelp-1.0.7.tar.gz", hash = "sha256:053dedc38823a80a7209a80860b16b722e9e0209e32fea98c90e4e6624588ed6"},
|
||||
{file = "sphinxcontrib_qthelp-2.0.0-py3-none-any.whl", hash = "sha256:b18a828cdba941ccd6ee8445dbe72ffa3ef8cbe7505d8cd1fa0d42d3f2d5f3eb"},
|
||||
{file = "sphinxcontrib_qthelp-2.0.0.tar.gz", hash = "sha256:4fe7d0ac8fc171045be623aba3e2a8f613f8682731f9153bb2e40ece16b9bbab"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
lint = ["docutils-stubs", "flake8", "mypy"]
|
||||
lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
|
||||
standalone = ["Sphinx (>=5)"]
|
||||
test = ["pytest"]
|
||||
test = ["defusedxml (>=0.7.1)", "pytest"]
|
||||
|
||||
[[package]]
|
||||
name = "sphinxcontrib-serializinghtml"
|
||||
version = "1.1.10"
|
||||
version = "2.0.0"
|
||||
description = "sphinxcontrib-serializinghtml is a sphinx extension which outputs \"serialized\" HTML files (json and pickle)"
|
||||
optional = false
|
||||
python-versions = ">=3.9"
|
||||
files = [
|
||||
{file = "sphinxcontrib_serializinghtml-1.1.10-py3-none-any.whl", hash = "sha256:326369b8df80a7d2d8d7f99aa5ac577f51ea51556ed974e7716cfd4fca3f6cb7"},
|
||||
{file = "sphinxcontrib_serializinghtml-1.1.10.tar.gz", hash = "sha256:93f3f5dc458b91b192fe10c397e324f262cf163d79f3282c158e8436a2c4511f"},
|
||||
{file = "sphinxcontrib_serializinghtml-2.0.0-py3-none-any.whl", hash = "sha256:6e2cb0eef194e10c27ec0023bfeb25badbbb5868244cf5bc5bdc04e4464bf331"},
|
||||
{file = "sphinxcontrib_serializinghtml-2.0.0.tar.gz", hash = "sha256:e9d912827f872c029017a53f0ef2180b327c3f7fd23c87229f7a8e8b70031d4d"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
lint = ["docutils-stubs", "flake8", "mypy"]
|
||||
lint = ["mypy", "ruff (==0.5.5)", "types-docutils"]
|
||||
standalone = ["Sphinx (>=5)"]
|
||||
test = ["pytest"]
|
||||
|
||||
@ -764,20 +802,20 @@ zstd = ["zstandard (>=0.18.0)"]
|
||||
|
||||
[[package]]
|
||||
name = "zipp"
|
||||
version = "3.19.1"
|
||||
version = "3.20.0"
|
||||
description = "Backport of pathlib-compatible object wrapper for zip files"
|
||||
optional = false
|
||||
python-versions = ">=3.8"
|
||||
files = [
|
||||
{file = "zipp-3.19.1-py3-none-any.whl", hash = "sha256:2828e64edb5386ea6a52e7ba7cdb17bb30a73a858f5eb6eb93d8d36f5ea26091"},
|
||||
{file = "zipp-3.19.1.tar.gz", hash = "sha256:35427f6d5594f4acf82d25541438348c26736fa9b3afa2754bcd63cdb99d8e8f"},
|
||||
{file = "zipp-3.20.0-py3-none-any.whl", hash = "sha256:58da6168be89f0be59beb194da1250516fdaa062ccebd30127ac65d30045e10d"},
|
||||
{file = "zipp-3.20.0.tar.gz", hash = "sha256:0145e43d89664cfe1a2e533adc75adafed82fe2da404b4bbb6b026c0157bdb31"},
|
||||
]
|
||||
|
||||
[package.extras]
|
||||
doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"]
|
||||
test = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
|
||||
test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"]
|
||||
|
||||
[metadata]
|
||||
lock-version = "2.0"
|
||||
python-versions = ">=3.9,<4"
|
||||
content-hash = "46ea46aa07ec956a146cb89e39ee7b860ce217e94b104f6b132c2069b1a7c113"
|
||||
content-hash = "966c9edc8f3aceefd1b976959150f334452381a60c937bf2cfc78c11833c3239"
|
||||
|
@ -27,13 +27,14 @@ classifiers = [
|
||||
|
||||
[tool.poetry.dependencies]
|
||||
python = ">=3.9,<4"
|
||||
PyGObject = "^3.38.0"
|
||||
PyGObject = "^3.50"
|
||||
pycairo = "^1.20.0"
|
||||
|
||||
[tool.poetry.dev-dependencies]
|
||||
[tool.poetry.group.dev.dependencies]
|
||||
pytest = "^8.3"
|
||||
pytest-cov = "^5.0"
|
||||
pytest-archon = "^0.0.6"
|
||||
pytest-asyncio = "^0.23.8"
|
||||
|
||||
[tool.poetry.group.docs]
|
||||
optional=true
|
||||
|
@ -7,6 +7,7 @@ gi.require_version("Gtk", "4.0")
|
||||
|
||||
|
||||
import pytest
|
||||
import pytest_asyncio
|
||||
from gi.repository import Gtk
|
||||
|
||||
from gaphas.canvas import Canvas
|
||||
@ -32,17 +33,18 @@ def connections(canvas):
|
||||
return canvas.connections
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def view(canvas):
|
||||
# view.update()
|
||||
return GtkView(canvas)
|
||||
@pytest_asyncio.fixture
|
||||
async def view(canvas):
|
||||
view = GtkView(canvas)
|
||||
await view.update()
|
||||
return view
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def scrolled_window(view):
|
||||
@pytest_asyncio.fixture
|
||||
async def scrolled_window(view):
|
||||
scrolled_window = Gtk.ScrolledWindow()
|
||||
scrolled_window.set_child(view)
|
||||
view.update()
|
||||
await view.update()
|
||||
return scrolled_window
|
||||
|
||||
|
||||
@ -54,10 +56,11 @@ def window(view):
|
||||
window.destroy()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def box(canvas, connections):
|
||||
@pytest_asyncio.fixture
|
||||
async def box(canvas, connections, view):
|
||||
box = Box(connections)
|
||||
canvas.add(box)
|
||||
await view.update()
|
||||
return box
|
||||
|
||||
|
||||
|
@ -1,177 +0,0 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import functools
|
||||
import time
|
||||
|
||||
import pytest
|
||||
from gi.repository import GLib
|
||||
|
||||
from gaphas.decorators import g_async
|
||||
|
||||
|
||||
@g_async()
|
||||
def async_function(self, token):
|
||||
self.append(token)
|
||||
|
||||
|
||||
@g_async(single=True)
|
||||
def single_function(list, token):
|
||||
list.append(token)
|
||||
|
||||
|
||||
@g_async(timeout=10)
|
||||
def timeout_function(list, token):
|
||||
list.append(token)
|
||||
|
||||
|
||||
@g_async()
|
||||
def generator_function(list, tokens):
|
||||
for token in tokens:
|
||||
list.append(token)
|
||||
yield
|
||||
|
||||
|
||||
class Obj(list):
|
||||
@g_async(single=True)
|
||||
def single_method(self, token):
|
||||
self.append(token)
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def obj():
|
||||
return Obj()
|
||||
|
||||
|
||||
def iteration():
|
||||
ctx = GLib.main_context_default()
|
||||
while ctx.pending():
|
||||
ctx.iteration(False)
|
||||
|
||||
|
||||
def in_main_context(func):
|
||||
@functools.wraps(func)
|
||||
def run_async():
|
||||
GLib.idle_add(func)
|
||||
iteration()
|
||||
|
||||
return run_async
|
||||
|
||||
|
||||
@in_main_context
|
||||
def test_in_main_context():
|
||||
assert GLib.main_depth() == 1
|
||||
|
||||
|
||||
def test_function_is_called_when_not_in_main_loop():
|
||||
called: list[str] = []
|
||||
|
||||
async_function(called, "called")
|
||||
|
||||
assert "called" in called
|
||||
|
||||
|
||||
def test_generator_is_called_when_not_in_main_loop():
|
||||
called: list[str] = []
|
||||
|
||||
for _ in generator_function(called, ["one", "two"]):
|
||||
pass
|
||||
|
||||
assert called == ["one", "two"]
|
||||
|
||||
|
||||
@in_main_context
|
||||
def test_function_is_not_called_directly_in_main_loop():
|
||||
called: list[str] = []
|
||||
|
||||
async_function(called, "called")
|
||||
|
||||
assert "called" not in called
|
||||
|
||||
|
||||
def test_function_is_called_from_main_loop():
|
||||
called: list[str] = []
|
||||
|
||||
@in_main_context
|
||||
def fn():
|
||||
async_function(called, "called")
|
||||
assert "called" not in called
|
||||
|
||||
fn()
|
||||
|
||||
assert "called" in called
|
||||
|
||||
|
||||
def test_single_function_is_called_once():
|
||||
called: list[str] = []
|
||||
|
||||
@in_main_context
|
||||
def fn():
|
||||
single_function(called, "first")
|
||||
single_function(called, "second")
|
||||
single_function(called, "third")
|
||||
|
||||
fn()
|
||||
|
||||
assert "first" in called
|
||||
assert "second" not in called
|
||||
assert "third" not in called
|
||||
|
||||
|
||||
def test_single_method_is_called_once_per_instance():
|
||||
first = Obj()
|
||||
second = Obj()
|
||||
|
||||
@in_main_context
|
||||
def fn():
|
||||
first.single_method("first")
|
||||
second.single_method("second")
|
||||
|
||||
fn()
|
||||
|
||||
assert "first" in first
|
||||
assert "second" in second
|
||||
assert "first" not in second
|
||||
assert "second" not in first
|
||||
|
||||
|
||||
def test_timeout_function():
|
||||
called: list[str] = []
|
||||
|
||||
@in_main_context
|
||||
def fn():
|
||||
timeout_function(called, "first")
|
||||
async_function(called, "second")
|
||||
|
||||
fn()
|
||||
|
||||
# wait a bit for timeout resource to trigger
|
||||
time.sleep(0.01)
|
||||
iteration()
|
||||
|
||||
assert called == ["second", "first"]
|
||||
|
||||
|
||||
def test_run_generator_to_completion():
|
||||
called: list[str] = []
|
||||
|
||||
@in_main_context
|
||||
def fn():
|
||||
for _ in generator_function(called, ["one", "two", "three"]):
|
||||
pass
|
||||
|
||||
fn()
|
||||
|
||||
assert called == ["one", "two", "three"]
|
||||
|
||||
|
||||
def test_run_first_generator_to_completion():
|
||||
called: list[str] = []
|
||||
|
||||
@in_main_context
|
||||
def fn():
|
||||
generator_function(called, ["one", "two", "three"])
|
||||
generator_function(called, ["four", "five"])
|
||||
|
||||
fn()
|
||||
|
||||
assert called == ["one", "two", "three"]
|
@ -23,7 +23,8 @@ def test_box_handle_order(box):
|
||||
|
||||
|
||||
@pytest.mark.parametrize("count", [1, 2, 10, 99])
|
||||
def test_resize_by_dragging_se_handle(canvas, box, count):
|
||||
@pytest.mark.asyncio
|
||||
async def test_resize_by_dragging_se_handle(canvas, box, count):
|
||||
h_nw, h_ne, h_se, h_sw = box.handles()
|
||||
|
||||
for _ in range(count):
|
||||
|
@ -75,7 +75,8 @@ def test_line_guide_horizontal(line, canvas):
|
||||
assert 30.0 == guides[2]
|
||||
|
||||
|
||||
def test_guide_item_in_motion(connections, canvas, view, window):
|
||||
@pytest.mark.asyncio
|
||||
async def test_guide_item_in_motion(connections, canvas, view, window):
|
||||
e1 = Element(connections)
|
||||
e2 = Element(connections)
|
||||
e3 = Element(connections)
|
||||
@ -88,6 +89,8 @@ def test_guide_item_in_motion(connections, canvas, view, window):
|
||||
|
||||
e2.matrix.translate(40, 40)
|
||||
canvas.request_update(e2)
|
||||
await view.update()
|
||||
|
||||
assert 40 == e2.matrix[4]
|
||||
assert 40 == e2.matrix[5]
|
||||
|
||||
@ -108,7 +111,8 @@ def test_guide_item_in_motion(connections, canvas, view, window):
|
||||
assert 20 == e3.matrix[5]
|
||||
|
||||
|
||||
def test_guide_item_in_motion_2(connections, canvas, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_guide_item_in_motion_2(connections, canvas, view):
|
||||
e1 = Element(connections)
|
||||
e2 = Element(connections)
|
||||
e3 = Element(connections)
|
||||
@ -121,6 +125,8 @@ def test_guide_item_in_motion_2(connections, canvas, view):
|
||||
|
||||
e2.matrix.translate(40, 40)
|
||||
canvas.request_update(e2)
|
||||
await view.update()
|
||||
|
||||
assert 40 == e2.matrix[4]
|
||||
assert 40 == e2.matrix[5]
|
||||
|
||||
|
@ -1,14 +1,18 @@
|
||||
import pytest
|
||||
|
||||
from gaphas.handlemove import ItemHandleMove
|
||||
|
||||
|
||||
def test_can_connect(line, box, connections, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_can_connect(line, box, connections, view):
|
||||
handle_move = ItemHandleMove(line, line.head, view)
|
||||
handle_move.connect((0, 0))
|
||||
|
||||
assert connections.get_connection(line.head)
|
||||
|
||||
|
||||
def test_handle_is_connected_and_constraint_removed_when_moved(
|
||||
@pytest.mark.asyncio
|
||||
async def test_handle_is_connected_and_constraint_removed_when_moved(
|
||||
line, box, connections, view
|
||||
):
|
||||
handle_move = ItemHandleMove(line, line.head, view)
|
||||
@ -21,7 +25,8 @@ def test_handle_is_connected_and_constraint_removed_when_moved(
|
||||
assert constraint not in connections.solver.constraints
|
||||
|
||||
|
||||
def test_connected_item_can_disconnect(line, box, connections, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_connected_item_can_disconnect(line, box, connections, view):
|
||||
handle_move = ItemHandleMove(line, line.head, view)
|
||||
handle_move.connect((0, 0))
|
||||
|
||||
@ -35,7 +40,8 @@ def test_connected_item_can_disconnect(line, box, connections, view):
|
||||
assert orig_constraint not in connections.solver.constraints
|
||||
|
||||
|
||||
def test_connected_item_can_reconnect(line, box, connections, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_connected_item_can_reconnect(line, box, connections, view):
|
||||
handle_move = ItemHandleMove(line, line.head, view)
|
||||
handle_move.connect((0, 0))
|
||||
|
||||
|
@ -11,7 +11,8 @@ def item(connections):
|
||||
return Element(connections)
|
||||
|
||||
|
||||
def test_selection_move(canvas, view, item):
|
||||
@pytest.mark.asyncio
|
||||
async def test_selection_move(canvas, view, item):
|
||||
"""Test the Selection role methods."""
|
||||
canvas.add(item)
|
||||
mover = Move(item, view)
|
||||
|
@ -123,7 +123,8 @@ def test_ports_after_split(canvas, line):
|
||||
assert old_ports[1] == line.ports()[2]
|
||||
|
||||
|
||||
def test_constraints_after_split(canvas, connections, line, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_constraints_after_split(canvas, connections, line, view):
|
||||
"""Test if constraints are recreated after line split."""
|
||||
# Connect line2 to self.line
|
||||
line2 = Line(connections)
|
||||
@ -189,7 +190,8 @@ def test_params_error_exc(canvas, connections):
|
||||
# Test Line Merging
|
||||
|
||||
|
||||
def test_merge_first_single(line, canvas, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_merge_first_single(line, canvas, view):
|
||||
"""Test single line merging starting from 1st segment."""
|
||||
line.handles()[1].pos = (20, 0)
|
||||
segment = Segment(line, canvas)
|
||||
@ -223,7 +225,8 @@ def test_merge_first_single(line, canvas, view):
|
||||
assert (20, 0) == port.end.pos
|
||||
|
||||
|
||||
def test_constraints_after_merge(canvas, connections, line, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_constraints_after_merge(canvas, connections, line, view):
|
||||
"""Test if constraints are recreated after line merge."""
|
||||
line2 = Line(connections)
|
||||
canvas.add(line2)
|
||||
@ -231,7 +234,7 @@ def test_constraints_after_merge(canvas, connections, line, view):
|
||||
|
||||
canvas.request_update(line)
|
||||
canvas.request_update(line2)
|
||||
view.update()
|
||||
await view.update()
|
||||
|
||||
HandleMove(line2, head, view).connect((25, 25))
|
||||
cinfo = connections.get_connection(head)
|
||||
|
@ -1,7 +1,10 @@
|
||||
import pytest
|
||||
|
||||
from gaphas.tool.hover import hover_tool, on_motion
|
||||
|
||||
|
||||
def test_hovers_item(view, box):
|
||||
@pytest.mark.asyncio
|
||||
async def test_hovers_item(view, box):
|
||||
tool = hover_tool()
|
||||
view.add_controller(tool)
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
import math
|
||||
|
||||
import pytest
|
||||
from gi.repository import Gtk
|
||||
|
||||
from gaphas.handlemove import order_items
|
||||
@ -47,7 +48,8 @@ def test_should_create_a_gesture():
|
||||
assert isinstance(tool, Gtk.Gesture)
|
||||
|
||||
|
||||
def test_select_item_on_click(view, box, window):
|
||||
@pytest.mark.asyncio
|
||||
async def test_select_item_on_click(view, box, window):
|
||||
tool = MockGesture(view)
|
||||
drag_state = DragState()
|
||||
selection = view.selection
|
||||
@ -58,7 +60,8 @@ def test_select_item_on_click(view, box, window):
|
||||
assert box in selection.selected_items
|
||||
|
||||
|
||||
def test_start_move_handle_on_click(view, box, window):
|
||||
@pytest.mark.asyncio
|
||||
async def test_start_move_handle_on_click(view, box, window):
|
||||
tool = MockGesture(view)
|
||||
drag_state = DragState()
|
||||
|
||||
@ -69,7 +72,8 @@ def test_start_move_handle_on_click(view, box, window):
|
||||
assert next(iter(drag_state.moving)).handle is box.handles()[0]
|
||||
|
||||
|
||||
def test_get_item_at_point(view, box):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_item_at_point(view, box):
|
||||
"""Hover tool only reacts on motion-notify events."""
|
||||
box.width = 50
|
||||
box.height = 50
|
||||
@ -79,7 +83,8 @@ def test_get_item_at_point(view, box):
|
||||
assert next(item_at_point(view, (60, 10)), None) is None # type: ignore[call-overload]
|
||||
|
||||
|
||||
def test_get_unselected_item_at_point(view, box):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_unselected_item_at_point(view, box):
|
||||
box.width = 50
|
||||
box.height = 50
|
||||
view.selection.select_items(box)
|
||||
@ -88,7 +93,8 @@ def test_get_unselected_item_at_point(view, box):
|
||||
assert next(item_at_point(view, (10, 10), exclude=(box,)), None) is None # type: ignore[call-overload]
|
||||
|
||||
|
||||
def test_get_item_at_point_overlayed_by_bigger_item(view, canvas, connections):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_item_at_point_overlayed_by_bigger_item(view, canvas, connections):
|
||||
"""Hover tool only reacts on motion-notify events."""
|
||||
below = Box(connections)
|
||||
canvas.add(below)
|
||||
@ -101,6 +107,7 @@ def test_get_item_at_point_overlayed_by_bigger_item(view, canvas, connections):
|
||||
above.width = 100
|
||||
above.height = 100
|
||||
view.request_update((below, above))
|
||||
await view.update()
|
||||
|
||||
assert next(item_at_point(view, (10, 10)), None) is below # type: ignore[call-overload]
|
||||
assert next(item_at_point(view, (-1, -1)), None) is above # type: ignore[call-overload]
|
||||
@ -112,26 +119,30 @@ def test_order_by_distance():
|
||||
assert [e[0] for e in order_items(m)] == [0, -1, -3, 4, 5, 10]
|
||||
|
||||
|
||||
def test_get_handle_at_point(view, canvas, connections):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_handle_at_point(view, canvas, connections):
|
||||
box = Box(connections)
|
||||
box.min_width = 20
|
||||
box.min_height = 30
|
||||
box.matrix.translate(20, 20)
|
||||
box.matrix.rotate(math.pi / 1.5)
|
||||
canvas.add(box)
|
||||
await view.update()
|
||||
|
||||
i, h = handle_at_point(view, (20, 20))
|
||||
assert i is box
|
||||
assert h is box.handles()[0]
|
||||
|
||||
|
||||
def test_get_handle_at_point_at_pi_div_2(view, canvas, connections):
|
||||
@pytest.mark.asyncio
|
||||
async def test_get_handle_at_point_at_pi_div_2(view, canvas, connections):
|
||||
box = Box(connections)
|
||||
box.min_width = 20
|
||||
box.min_height = 30
|
||||
box.matrix.translate(20, 20)
|
||||
box.matrix.rotate(math.pi / 2)
|
||||
canvas.add(box)
|
||||
await view.update()
|
||||
|
||||
i, h = handle_at_point(view, (20, 20))
|
||||
assert i is box
|
||||
|
@ -41,7 +41,8 @@ def test_begin_state(zoom_data, view):
|
||||
assert zoom_data.sy == 1
|
||||
|
||||
|
||||
def test_scaling(zoom_data, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_scaling(zoom_data, view):
|
||||
tool = zoom_tool()
|
||||
view.add_controller(tool)
|
||||
|
||||
@ -51,7 +52,8 @@ def test_scaling(zoom_data, view):
|
||||
assert view.matrix[3] == pytest.approx(1.2)
|
||||
|
||||
|
||||
def test_multiple_scaling_events(zoom_data, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_multiple_scaling_events(zoom_data, view):
|
||||
tool = zoom_tool()
|
||||
view.add_controller(tool)
|
||||
|
||||
@ -62,7 +64,8 @@ def test_multiple_scaling_events(zoom_data, view):
|
||||
assert view.matrix[3] == pytest.approx(1.2)
|
||||
|
||||
|
||||
def test_scaling_with_unequal_scaling_factor(zoom_data, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_scaling_with_unequal_scaling_factor(zoom_data, view):
|
||||
tool = zoom_tool()
|
||||
view.add_controller(tool)
|
||||
|
||||
@ -74,7 +77,8 @@ def test_scaling_with_unequal_scaling_factor(zoom_data, view):
|
||||
assert view.matrix[3] == pytest.approx(1.2)
|
||||
|
||||
|
||||
def test_zoom_should_center_around_mouse_cursor(zoom_data, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_zoom_should_center_around_mouse_cursor(zoom_data, view):
|
||||
tool = zoom_tool()
|
||||
view.add_controller(tool)
|
||||
zoom_data.x0 = 100
|
||||
@ -86,7 +90,8 @@ def test_zoom_should_center_around_mouse_cursor(zoom_data, view):
|
||||
assert view.matrix[5] == pytest.approx(-10.0)
|
||||
|
||||
|
||||
def test_zoom_out_should_be_limited_to_20_percent(zoom_data, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_zoom_out_should_be_limited_to_20_percent(zoom_data, view):
|
||||
tool = zoom_tool()
|
||||
view.add_controller(tool)
|
||||
|
||||
@ -96,7 +101,8 @@ def test_zoom_out_should_be_limited_to_20_percent(zoom_data, view):
|
||||
assert view.matrix[3] == pytest.approx(0.2)
|
||||
|
||||
|
||||
def test_zoom_in_should_be_limited_to_20_times(zoom_data, view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_zoom_in_should_be_limited_to_20_times(zoom_data, view):
|
||||
tool = zoom_tool()
|
||||
view.add_controller(tool)
|
||||
|
||||
|
@ -1,5 +1,6 @@
|
||||
"""Test cases for the View class."""
|
||||
|
||||
import pytest
|
||||
from gi.repository import Gtk
|
||||
|
||||
from gaphas.canvas import Canvas
|
||||
@ -27,17 +28,21 @@ def test_custom_selection_setter():
|
||||
assert view.selection is custom_selection
|
||||
|
||||
|
||||
def test_item_removal(view, canvas, box):
|
||||
@pytest.mark.asyncio
|
||||
async def test_item_removal(view, canvas, box):
|
||||
await view.update()
|
||||
assert len(list(canvas.get_all_items())) == len(view._qtree)
|
||||
|
||||
view.selection.focused_item = box
|
||||
canvas.remove(box)
|
||||
await view.update()
|
||||
|
||||
assert not list(canvas.get_all_items())
|
||||
assert len(view._qtree) == 0
|
||||
|
||||
|
||||
def test_view_registration():
|
||||
@pytest.mark.asyncio
|
||||
async def test_view_registration():
|
||||
canvas = Canvas()
|
||||
|
||||
# GTK view does register for updates though
|
||||
@ -55,7 +60,8 @@ def test_view_registration():
|
||||
assert len(canvas._registered_views) == 1
|
||||
|
||||
|
||||
def test_view_registration_2(view, canvas, window):
|
||||
@pytest.mark.asyncio
|
||||
async def test_view_registration_2(view, canvas, window):
|
||||
"""Test view registration and destroy when view is destroyed."""
|
||||
window.present()
|
||||
|
||||
@ -67,7 +73,8 @@ def test_view_registration_2(view, canvas, window):
|
||||
assert len(canvas._registered_views) == 0
|
||||
|
||||
|
||||
def test_scroll_adjustments_signal(view, scrolled_window):
|
||||
@pytest.mark.asyncio
|
||||
async def test_scroll_adjustments_signal(view, scrolled_window):
|
||||
assert view.hadjustment
|
||||
assert view.vadjustment
|
||||
assert view.hadjustment.get_value() == 0.0
|
||||
@ -84,12 +91,14 @@ def test_scroll_adjustments_signal(view, scrolled_window):
|
||||
assert view.vadjustment.get_page_size() == 0.0
|
||||
|
||||
|
||||
def test_scroll_adjustments(view, scrolled_window):
|
||||
@pytest.mark.asyncio
|
||||
async def test_scroll_adjustments(view, scrolled_window):
|
||||
assert scrolled_window.get_hadjustment() is view.hadjustment
|
||||
assert scrolled_window.get_vadjustment() is view.vadjustment
|
||||
|
||||
|
||||
def test_will_not_remove_lone_controller(view):
|
||||
@pytest.mark.asyncio
|
||||
async def test_will_not_remove_lone_controller(view):
|
||||
ctrl = Gtk.EventControllerMotion.new()
|
||||
|
||||
removed = view.remove_controller(ctrl)
|
||||
|
Loading…
Reference in New Issue
Block a user