Upgrade to PyO3 0.24

The main change is that Rust paths are mapped to pathlib.Path, which changes our API (stricter).
This commit is contained in:
Simon Hausmann 2025-04-03 12:16:10 +02:00 committed by Simon Hausmann
parent 0c51f69b0a
commit 826ad7a865
10 changed files with 51 additions and 51 deletions

View file

@ -55,7 +55,7 @@ slint-interpreter = { workspace = true, features = [
"internal",
] }
i-slint-compiler = { workspace = true }
pyo3 = { version = "0.23", features = [
pyo3 = { version = "0.24", features = [
"extension-module",
"indexmap",
"chrono",

View file

@ -16,6 +16,7 @@ from typing import Any
import pathlib
from .models import ListModel, Model
from .slint import Image, Color, Brush, Timer, TimerMode
from pathlib import Path
Struct = native.PyStruct
@ -248,11 +249,9 @@ def load_file(
path: str | os.PathLike[Any] | pathlib.Path,
quiet: bool = False,
style: typing.Optional[str] = None,
include_paths: typing.Optional[
typing.List[str | os.PathLike[Any] | pathlib.Path]
] = None,
include_paths: typing.Optional[typing.List[os.PathLike[Any] | pathlib.Path]] = None,
library_paths: typing.Optional[
typing.Dict[str, str | os.PathLike[Any] | pathlib.Path]
typing.Dict[str, os.PathLike[Any] | pathlib.Path]
] = None,
translation_domain: typing.Optional[str] = None,
) -> types.SimpleNamespace:
@ -280,7 +279,7 @@ def load_file(
if translation_domain is not None:
compiler.translation_domain = translation_domain
result = compiler.build_from_path(path)
result = compiler.build_from_path(Path(path))
diagnostics = result.diagnostics
if diagnostics:
@ -289,13 +288,11 @@ def load_file(
if diag.level == native.DiagnosticLevel.Warning:
logging.warning(diag)
errors = [
diag
for diag in diagnostics
if diag.level == native.DiagnosticLevel.Error
]
if errors:
raise CompileError(f"Could not compile {path}", diagnostics)
errors = [
diag for diag in diagnostics if diag.level == native.DiagnosticLevel.Error
]
if errors:
raise CompileError(f"Could not compile {path}", diagnostics)
module = types.SimpleNamespace()
for comp_name in result.component_names:
@ -317,27 +314,27 @@ def load_file(
class SlintAutoLoader:
def __init__(self, base_dir: str | None = None):
self.local_dirs: typing.List[str] | None = None
def __init__(self, base_dir: Path | None = None):
self.local_dirs: typing.List[Path] | None = None
if base_dir:
self.local_dirs = [base_dir]
def __getattr__(self, name: str) -> Any:
for path in self.local_dirs or sys.path:
dir_candidate = os.path.join(path, name)
dir_candidate = Path(path) / name
if os.path.isdir(dir_candidate):
loader = SlintAutoLoader(dir_candidate)
setattr(self, name, loader)
return loader
file_candidate = dir_candidate + ".slint"
file_candidate = dir_candidate.with_suffix(".slint")
if os.path.isfile(file_candidate):
type_namespace = load_file(file_candidate)
setattr(self, name, type_namespace)
return type_namespace
dir_candidate = os.path.join(path, name.replace("_", "-"))
file_candidate = dir_candidate + ".slint"
dir_candidate = Path(path) / name.replace("_", "-")
file_candidate = dir_candidate.with_suffix(".slint")
if os.path.isfile(file_candidate):
type_namespace = load_file(file_candidate)
setattr(self, name, type_namespace)

View file

@ -63,7 +63,7 @@ class Image:
size: tuple[int, int]
width: int
height: int
path: typing.Optional[str]
path: typing.Optional[pathlib.Path]
def __new__(
cls,
) -> "Image": ...
@ -175,13 +175,13 @@ class CompilationResult:
def component(self, name: str) -> ComponentDefinition: ...
class Compiler:
include_paths: list[str | os.PathLike[Any] | pathlib.Path]
library_paths: dict[str, str | os.PathLike[Any] | pathlib.Path]
include_paths: list[os.PathLike[Any] | pathlib.Path]
library_paths: dict[str, os.PathLike[Any] | pathlib.Path]
translation_domain: str
style: str
def build_from_path(
self, path: str | os.PathLike[Any] | pathlib.Path
self, path: os.PathLike[Any] | pathlib.Path
) -> CompilationResult: ...
def build_from_source(
self, source: str, path: str | os.PathLike[Any] | pathlib.Path
self, source: str, path: os.PathLike[Any] | pathlib.Path
) -> CompilationResult: ...

View file

@ -3,20 +3,20 @@
from slint import load_file
import slint
import os
import pytest
from pathlib import Path
def base_dir() -> str:
def base_dir() -> Path:
origin = __spec__.origin
assert origin is not None
base_dir = os.path.dirname(origin)
base_dir = Path(origin).parent
assert base_dir is not None
return base_dir
def test_callback_decorators(caplog: pytest.LogCaptureFixture) -> None:
module = load_file(os.path.join(base_dir(), "test-load-file.slint"), quiet=False)
module = load_file(base_dir() / "test-load-file.slint", quiet=False)
class SubClass(module.App): # type: ignore
@slint.callback()

View file

@ -3,16 +3,17 @@
from slint import slint as native
from slint.slint import ValueType
from pathlib import Path
def test_basic_compiler() -> None:
compiler = native.Compiler()
assert compiler.include_paths == []
compiler.include_paths = ["testing"]
assert compiler.include_paths == ["testing"]
compiler.include_paths = [Path("testing")]
assert compiler.include_paths == [Path("testing")]
assert len(compiler.build_from_source("Garbage", "").component_names) == 0
assert len(compiler.build_from_source("Garbage", Path("")).component_names) == 0
result = compiler.build_from_source(
"""
@ -36,7 +37,7 @@ def test_basic_compiler() -> None:
public function ff() {}
}
""",
"",
Path(""),
)
assert result.component_names == ["Test"]
compdef = result.component("Test")
@ -80,7 +81,7 @@ def test_basic_compiler() -> None:
def test_compiler_build_from_path() -> None:
compiler = native.Compiler()
result = compiler.build_from_path("Nonexistent.slint")
result = compiler.build_from_path(Path("Nonexistent.slint"))
assert len(result.component_names) == 0
diags = result.diagnostics

View file

@ -5,6 +5,7 @@ from slint import slint as native
import weakref
import gc
import typing
from pathlib import Path
def test_callback_gc() -> None:
@ -17,7 +18,7 @@ def test_callback_gc() -> None:
callback test-callback(string) -> string;
}
""",
"",
Path(""),
).component("Test")
assert compdef is not None

View file

@ -5,6 +5,7 @@ import pytest
from slint import slint as native
from slint.slint import Image, Color, Brush
import os
from pathlib import Path
def test_property_access() -> None:
@ -42,7 +43,7 @@ def test_property_access() -> None:
callback test-callback();
}
""",
os.path.join(os.path.dirname(__file__), "main.slint"),
Path(__file__).parent / "main.slint",
).component("Test")
assert compdef is not None
@ -92,7 +93,7 @@ def test_property_access() -> None:
imageval = instance.get_property("imageprop")
assert imageval.width == 320
assert imageval.height == 480
assert "cat.jpg" in imageval.path
assert "cat.jpg" in imageval.path.name
with pytest.raises(RuntimeError, match="The image cannot be loaded"):
Image.load_from_path("non-existent.png")
@ -108,7 +109,7 @@ def test_property_access() -> None:
)
imageval = instance.get_property("imageprop")
assert imageval.size == (36, 36)
assert "humidity.png" in imageval.path
assert "humidity.png" in str(imageval.path)
with pytest.raises(
TypeError, match="'int' object cannot be converted to 'PyString'"
@ -157,7 +158,7 @@ def test_callbacks() -> None:
callback void-callback();
}
""",
"",
Path(""),
).component("Test")
assert compdef is not None
@ -192,7 +193,7 @@ def test_callbacks() -> None:
if __name__ == "__main__":
import slint
module = slint.load_file("../../demos/printerdemo/ui/printerdemo.slint")
module = slint.load_file(Path("../../demos/printerdemo/ui/printerdemo.slint"))
instance = module.MainWindow()
instance.PrinterQueue.start_job = lambda title: print(f"new print job {title}")
instance.run()

View file

@ -3,19 +3,19 @@
import pytest
from slint import load_file, CompileError
import os
from pathlib import Path
def base_dir() -> str:
def base_dir() -> Path:
origin = __spec__.origin
assert origin is not None
base_dir = os.path.dirname(origin)
base_dir = Path(origin).parent
assert base_dir is not None
return base_dir
def test_load_file(caplog: pytest.LogCaptureFixture) -> None:
module = load_file(os.path.join(base_dir(), "test-load-file.slint"), quiet=False)
module = load_file(base_dir() / "test-load-file.slint", quiet=False)
assert (
"The property 'color' has been deprecated. Please use 'background' instead"
@ -51,7 +51,7 @@ def test_load_file_fail() -> None:
def test_load_file_wrapper() -> None:
module = load_file(os.path.join(base_dir(), "test-load-file.slint"), quiet=False)
module = load_file(base_dir() / "test-load-file.slint", quiet=False)
instance = module.App()
@ -74,7 +74,7 @@ def test_load_file_wrapper() -> None:
def test_constructor_kwargs() -> None:
module = load_file(os.path.join(base_dir(), "test-load-file.slint"), quiet=False)
module = load_file(base_dir() / "test-load-file.slint", quiet=False)
def early_say_hello(arg: str) -> str:
return "early:" + arg

View file

@ -4,6 +4,7 @@
from slint import slint as native
from slint import models as models
import typing
from pathlib import Path
def test_model_notify() -> None:
@ -31,7 +32,7 @@ def test_model_notify() -> None:
}
""",
"",
Path(""),
).component("App")
assert compdef is not None
@ -62,7 +63,7 @@ def test_model_from_list() -> None:
in-out property<[int]> data: [1, 2, 3, 4];
}
""",
"",
Path(""),
).component("App")
assert compdef is not None
@ -110,7 +111,7 @@ def test_rust_model_sequence() -> None:
in-out property<[int]> data: [1, 2, 3, 4, 5];
}
""",
"",
Path(""),
).component("App")
assert compdef is not None
@ -141,7 +142,7 @@ def test_model_writeback() -> None:
}
""",
"",
Path(""),
).component("App")
assert compdef is not None

View file

@ -9,10 +9,9 @@ use pyo3_stub_gen::{
/// The TimerMode specifies what should happen after the timer fired.
///
/// Used by the `Timer.start()` function.
#[derive(Copy, Clone)]
#[derive(Copy, Clone, PartialEq)]
#[gen_stub_pyclass_enum]
#[pyclass(name = "TimerMode", eq, eq_int)]
#[derive(PartialEq)]
pub enum PyTimerMode {
/// A SingleShot timer is fired only once.
SingleShot,