summaryrefslogtreecommitdiff
path: root/lib/sew_stack/stitch_layers
diff options
context:
space:
mode:
authorLex Neva <lexelby@users.noreply.github.com>2025-08-21 16:10:48 -0400
committerGitHub <noreply@github.com>2025-08-21 16:10:48 -0400
commite9bcdc910a2101c0da2fa379da36e1d1be2fe3f2 (patch)
tree0e47774b5648ff14cf3b67495ea4f361371031a5 /lib/sew_stack/stitch_layers
parenta71ec6e4599e28dfac45d2df3575976dffbb25d6 (diff)
fix type errors (#3928)
* fix type checking error in overriding path propery * fix type hints in sew stack * enable type checking for tartan * ignore type warnings for dynamic wx module attributes * fix tartan type errors * fix circular import * add type-check and test targets * use Optional instead
Diffstat (limited to 'lib/sew_stack/stitch_layers')
-rw-r--r--lib/sew_stack/stitch_layers/mixins/path.py7
-rw-r--r--lib/sew_stack/stitch_layers/mixins/protocol.py50
-rw-r--r--lib/sew_stack/stitch_layers/mixins/randomization.py13
3 files changed, 55 insertions, 15 deletions
diff --git a/lib/sew_stack/stitch_layers/mixins/path.py b/lib/sew_stack/stitch_layers/mixins/path.py
index 88e5419d..9739f381 100644
--- a/lib/sew_stack/stitch_layers/mixins/path.py
+++ b/lib/sew_stack/stitch_layers/mixins/path.py
@@ -1,6 +1,6 @@
+from .protocol import LayerProtocol
from ..stitch_layer_editor import Category, Property
from ....i18n import _
-from ....utils import DotDict, Point
class PathPropertiesMixin:
@@ -13,10 +13,7 @@ class PathPropertiesMixin:
class PathMixin:
- config: DotDict
- paths: 'list[list[Point]]'
-
- def get_paths(self):
+ def get_paths(self: LayerProtocol):
paths = self.paths
if self.config.reverse_path:
diff --git a/lib/sew_stack/stitch_layers/mixins/protocol.py b/lib/sew_stack/stitch_layers/mixins/protocol.py
new file mode 100644
index 00000000..1057bd7b
--- /dev/null
+++ b/lib/sew_stack/stitch_layers/mixins/protocol.py
@@ -0,0 +1,50 @@
+from typing import Protocol, TYPE_CHECKING
+
+from lib.utils import DotDict, Point
+
+
+if TYPE_CHECKING:
+ from lib.sew_stack import SewStack
+
+
+class LayerProtocol(Protocol):
+ paths: 'list[list[Point]]'
+ config: DotDict
+ element: 'SewStack'
+
+
+def with_protocol(protocol):
+ """Include a protocol in a Mixin only for type hinting.
+
+ Normally we'd use a protocol in a mixin to indicate that we
+ expect certain attributes to be available on self, as
+ described here:
+
+ https://mypy.readthedocs.io/en/stable/more_types.html#mixin-classes
+
+ However, for some reason type-checkers then _only_ allow use of
+ properties on self that are defined in the protocol. For example,
+ this doesn't work:
+
+ class MyMixin:
+ def foo(self):
+ return "hi"
+
+ def bar(self: LayerProtocol):
+ thing = self.foo()
+ if self.config.baz == thing:
+ ...
+
+ This fails because mypy says that "self.foo()" references unknown
+ attribute "foo"... even though it's defined right there in MyMixin.
+ This feels a little weird, but that's how it works.
+
+ Instead, we do it like this:
+
+ class MyMixin(with_protocol(LayerProtocol)):
+ ...
+ """
+ if TYPE_CHECKING:
+ return protocol
+ else:
+ return object
diff --git a/lib/sew_stack/stitch_layers/mixins/randomization.py b/lib/sew_stack/stitch_layers/mixins/randomization.py
index 5414731c..009b5042 100644
--- a/lib/sew_stack/stitch_layers/mixins/randomization.py
+++ b/lib/sew_stack/stitch_layers/mixins/randomization.py
@@ -1,17 +1,13 @@
import os
from secrets import randbelow
-from typing import TYPE_CHECKING
import wx.propgrid
+from .protocol import LayerProtocol, with_protocol
from ..stitch_layer_editor import Category, Property
from ....i18n import _
from ....svg import PIXELS_PER_MM
-from ....utils import DotDict, get_resource_dir, prng
-
-if TYPE_CHECKING:
- from ... import SewStack
-
+from ....utils import get_resource_dir, prng
editor_instance = None
@@ -70,10 +66,7 @@ class RandomizationPropertiesMixin:
)
-class RandomizationMixin:
- config: DotDict
- element: "SewStack"
-
+class RandomizationMixin(with_protocol(LayerProtocol)):
@classmethod
def randomization_defaults(cls):
return dict(