Python: Fix support for named exports

This commit is contained in:
Simon Hausmann 2024-08-13 10:56:12 +02:00 committed by Simon Hausmann
parent 2d5d53fba8
commit 636de6fc7c
7 changed files with 73 additions and 4 deletions

View file

@ -179,6 +179,11 @@ impl CompilationResult {
.into_iter()
.collect::<HashMap<String, PyObject>>()
}
#[getter]
fn named_exports(&self) -> Vec<(String, String)> {
self.result.named_exports(i_slint_core::InternalToken {}).cloned().collect::<Vec<_>>()
}
}
#[pyclass(unsendable)]

View file

@ -242,9 +242,15 @@ def load_file(path, quiet=False, style=None, include_paths=None, library_paths=N
setattr(module, comp_name, wrapper_class)
for name, struct_or_enum_prototype in result.structs_and_enums.items():
name = _normalize_prop(name)
struct_wrapper = _build_struct(name, struct_or_enum_prototype)
setattr(module, name, struct_wrapper)
for orig_name, new_name in result.named_exports:
orig_name = _normalize_prop(orig_name)
new_name = _normalize_prop(new_name)
setattr(module, new_name, getattr(module, orig_name))
return module

View file

@ -12,13 +12,16 @@ def test_load_file(caplog):
assert "The property 'color' has been deprecated. Please use 'background' instead" in caplog.text
assert len(list(module.__dict__.keys())) == 3
assert len(list(module.__dict__.keys())) == 6
assert "App" in module.__dict__
assert "Diag" in module.__dict__
assert "MyDiag" in module.__dict__
assert "MyData" in module.__dict__
assert "Secret_Struct" in module.__dict__
assert "Public_Struct" in module.__dict__
instance = module.App()
del instance
instance = module.Diag()
instance = module.MyDiag()
del instance
struct_instance = module.MyData()
@ -28,6 +31,9 @@ def test_load_file(caplog):
struct_instance = module.MyData(name="testing")
assert struct_instance.name == "testing"
assert module.Public_Struct is module.Secret_Struct
assert module.MyDiag is module.Diag
def test_load_file_fail():
with pytest.raises(CompileError, match="Could not compile non-existent.slint"):

View file

@ -15,9 +15,15 @@ export global SecondGlobal {
export struct MyData {
name: string,
age: int
age: int,
}
struct Secret-Struct {
balance: int,
}
export { Secret-Struct as Public-Struct }
export component App inherits Window {
in-out property <string> hello: "World";
callback say-hello(string) -> string;
@ -47,4 +53,6 @@ export component App inherits Window {
}
}
export component Diag inherits Window { }
component Diag inherits Window { }
export { Diag as MyDiag }

View file

@ -133,6 +133,7 @@ thiserror = "1"
document-features = { version = "0.2.0", optional = true }
spin_on = { workspace = true, optional = true }
raw-window-handle-06 = { workspace = true, optional = true }
itertools = { workspace = true }
[target.'cfg(target_arch = "wasm32")'.dependencies]
i-slint-backend-winit = { workspace = true }

View file

@ -816,6 +816,8 @@ impl Compiler {
diagnostics: diagnostics.into_iter().collect(),
#[cfg(feature = "internal")]
structs_and_enums: Vec::new(),
#[cfg(feature = "internal")]
named_exports: Vec::new(),
};
}
};
@ -852,6 +854,9 @@ pub struct CompilationResult {
pub(crate) diagnostics: Vec<Diagnostic>,
#[cfg(feature = "internal")]
pub(crate) structs_and_enums: Vec<LangType>,
/// For `export { Foo as Bar }` this vec contains tuples of (`Foo`, `Bar`)
#[cfg(feature = "internal")]
pub(crate) named_exports: Vec<(String, String)>,
}
impl core::fmt::Debug for CompilationResult {
@ -912,6 +917,17 @@ impl CompilationResult {
) -> impl Iterator<Item = &LangType> {
self.structs_and_enums.iter()
}
/// This is an internal function without API stability guarantees.
/// Returns the list of named export aliases as tuples (`export { Foo as Bar}` is (`Foo`, `Bar` tuple)).
#[doc(hidden)]
#[cfg(feature = "internal")]
pub fn named_exports(
&self,
_: i_slint_core::InternalToken,
) -> impl Iterator<Item = &(String, String)> {
self.named_exports.iter()
}
}
/// ComponentDefinition is a representation of a compiled component from .slint markup.

View file

@ -34,6 +34,8 @@ use i_slint_core::rtti::{self, AnimatedBindingKind, FieldOffset, PropertyInfo};
use i_slint_core::slice::Slice;
use i_slint_core::window::{WindowAdapterRc, WindowInner};
use i_slint_core::{Brush, Color, Property, SharedString, SharedVector};
#[cfg(feature = "internal")]
use itertools::Either;
use once_cell::unsync::OnceCell;
use std::collections::BTreeMap;
use std::collections::HashMap;
@ -846,6 +848,8 @@ pub async fn load(
diagnostics: diag.into_iter().collect(),
#[cfg(feature = "internal")]
structs_and_enums: Vec::new(),
#[cfg(feature = "internal")]
named_exports: Vec::new(),
};
}
@ -878,11 +882,34 @@ pub async fn load(
#[cfg(feature = "internal")]
let structs_and_enums = doc.used_types.borrow().structs_and_enums.clone();
#[cfg(feature = "internal")]
let named_exports = doc
.exports
.iter()
.filter_map(|export| match &export.1 {
Either::Left(component) if !component.is_global() => {
Some((&export.0.name, &component.id))
}
Either::Right(ty) => match &ty {
Type::Struct { name: Some(name), node: Some(_), .. } => {
Some((&export.0.name, name))
}
Type::Enumeration(en) => Some((&export.0.name, &en.name)),
_ => None,
},
_ => None,
})
.filter(|(export_name, type_name)| *export_name != *type_name)
.map(|(export_name, type_name)| (type_name.clone(), export_name.clone()))
.collect::<Vec<_>>();
CompilationResult {
diagnostics: diag.into_iter().collect(),
components,
#[cfg(feature = "internal")]
structs_and_enums,
#[cfg(feature = "internal")]
named_exports,
}
}