mirror of
https://github.com/RustPython/RustPython.git
synced 2026-10-28 18:59:04 +08:00
70 files changed
+1638
-1273
No files matched your search
Generated
+10
@@ -1340,6 +1340,7 @@ dependencies = [
|
||||
"rustpython-bytecode",
|
||||
"rustpython-compiler",
|
||||
"syn",
|
||||
"syn-ext",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1688,6 +1689,15 @@ dependencies = [
|
||||
"unicode-xid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn-ext"
|
||||
version = "0.2.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "da910e9ec6f88d3f591893025a3040fe2659b7f7ea4eacce5469b7ebe5287339"
|
||||
dependencies = [
|
||||
"syn",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "term"
|
||||
version = "0.5.2"
|
||||
|
||||
@@ -12,6 +12,7 @@ proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
syn = { version = "1.0", features = ["full"] }
|
||||
syn-ext = { version = "0.2.1", features = ["full"] }
|
||||
quote = "1.0"
|
||||
proc-macro2 = "1.0"
|
||||
rustpython-compiler = { path = "../compiler", version = "0.1.1" }
|
||||
|
||||
+12
-12
@@ -43,19 +43,19 @@ macro_rules! bail_span {
|
||||
)
|
||||
}
|
||||
|
||||
macro_rules! push_err_span {
|
||||
($diagnostics:expr, $($t:tt)*) => {
|
||||
$diagnostics.push(err_span!($($t)*))
|
||||
};
|
||||
}
|
||||
// macro_rules! push_err_span {
|
||||
// ($diagnostics:expr, $($t:tt)*) => {
|
||||
// $diagnostics.push(err_span!($($t)*))
|
||||
// };
|
||||
// }
|
||||
|
||||
macro_rules! push_diag_result {
|
||||
($diags:expr, $x:expr $(,)?) => {
|
||||
if let Err(e) = $x {
|
||||
$diags.push(e);
|
||||
}
|
||||
};
|
||||
}
|
||||
// macro_rules! push_diag_result {
|
||||
// ($diags:expr, $x:expr $(,)?) => {
|
||||
// if let Err(e) = $x {
|
||||
// $diags.push(e);
|
||||
// }
|
||||
// };
|
||||
// }
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct Diagnostic {
|
||||
|
||||
+619
-427
File diff suppressed because it is too large.
Load diff
+373
-420
@@ -1,443 +1,72 @@
|
||||
use super::Diagnostic;
|
||||
use crate::error::Diagnostic;
|
||||
use crate::util::{
|
||||
def_to_name, meta_into_nesteds, optional_attribute_arg, ItemIdent, ItemMeta, ItemType,
|
||||
pyclass_ident_and_attrs, AttributeExt, ClassItemMeta, ContentItem, ContentItemInner, ErrorVec,
|
||||
ItemMeta, ItemNursery, SimpleItemMeta, ALL_ALLOWED_NAMES,
|
||||
};
|
||||
use proc_macro2::{Span, TokenStream as TokenStream2};
|
||||
use proc_macro2::TokenStream;
|
||||
use quote::{quote, quote_spanned, ToTokens};
|
||||
use std::collections::HashMap;
|
||||
use syn::{parse_quote, spanned::Spanned, AttributeArgs, Ident, Item, Meta, NestedMeta, UseTree};
|
||||
use syn::{parse_quote, spanned::Spanned, Attribute, AttributeArgs, Ident, Item, Result, UseTree};
|
||||
use syn_ext::ext::*;
|
||||
|
||||
struct Module {
|
||||
#[derive(Default)]
|
||||
struct ModuleContext {
|
||||
name: String,
|
||||
items: HashMap<(String, Vec<Meta>), ModuleItem>,
|
||||
module_extend_items: ItemNursery,
|
||||
errors: Vec<syn::Error>,
|
||||
}
|
||||
|
||||
#[derive(PartialEq, Eq, Hash)]
|
||||
enum ModuleItem {
|
||||
Function {
|
||||
item_ident: Ident,
|
||||
py_name: String,
|
||||
},
|
||||
EvaluatedAttr {
|
||||
item_ident: Ident,
|
||||
py_name: String,
|
||||
},
|
||||
ConstAttr {
|
||||
item_ident: Ident,
|
||||
py_name: String,
|
||||
},
|
||||
ClassAttr {
|
||||
item_ident: Ident,
|
||||
py_name: Option<String>,
|
||||
},
|
||||
Class {
|
||||
item_ident: Ident,
|
||||
py_name: String,
|
||||
},
|
||||
}
|
||||
|
||||
impl ModuleItem {
|
||||
fn name(&self) -> String {
|
||||
use ModuleItem::*;
|
||||
match self {
|
||||
Function { py_name, .. } => py_name.clone(),
|
||||
EvaluatedAttr { py_name, .. } => py_name.clone(),
|
||||
ConstAttr { py_name, .. } => py_name.clone(),
|
||||
ClassAttr { py_name, .. } => py_name.clone().unwrap_or_else(String::new),
|
||||
Class { py_name, .. } => py_name.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Module {
|
||||
fn add_item(
|
||||
&mut self,
|
||||
item: ModuleItem,
|
||||
cfgs: Vec<Meta>,
|
||||
span: Span,
|
||||
) -> Result<(), Diagnostic> {
|
||||
if let Some(existing) = self.items.insert((item.name(), cfgs), item) {
|
||||
Err(Diagnostic::span_error(
|
||||
span,
|
||||
format!(
|
||||
"Duplicate #[py*] attribute on pymodule: {}",
|
||||
existing.name()
|
||||
),
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_function(ident: &Ident, nesteds: Vec<NestedMeta>) -> Result<ModuleItem, Diagnostic> {
|
||||
let item_meta =
|
||||
ItemMeta::from_nested_meta("pyfunction", &ident, &nesteds, ItemMeta::SIMPLE_NAMES)?;
|
||||
Ok(ModuleItem::Function {
|
||||
item_ident: ident.clone(),
|
||||
py_name: item_meta.simple_name()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_class(ident: &Ident, nesteds: Vec<NestedMeta>) -> Result<ModuleItem, Diagnostic> {
|
||||
let item_meta =
|
||||
ItemMeta::from_nested_meta("pyclass", &ident, &nesteds, ItemMeta::SIMPLE_NAMES)?;
|
||||
Ok(ModuleItem::Class {
|
||||
item_ident: ident.clone(),
|
||||
py_name: item_meta.simple_name()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_struct_sequence(
|
||||
ident: &Ident,
|
||||
nesteds: Vec<NestedMeta>,
|
||||
) -> Result<ModuleItem, Diagnostic> {
|
||||
let item_meta = ItemMeta::from_nested_meta(
|
||||
"pystruct_sequence",
|
||||
&ident,
|
||||
&nesteds,
|
||||
ItemMeta::STRUCT_SEQUENCE_NAMES,
|
||||
)?;
|
||||
Ok(ModuleItem::Class {
|
||||
item_ident: ident.clone(),
|
||||
py_name: item_meta.simple_name()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_evaluated_attr(
|
||||
ident: &Ident,
|
||||
nesteds: Vec<NestedMeta>,
|
||||
) -> Result<ModuleItem, Diagnostic> {
|
||||
let item_meta =
|
||||
ItemMeta::from_nested_meta("pyattr", &ident, &nesteds, ItemMeta::SIMPLE_NAMES)?;
|
||||
Ok(ModuleItem::EvaluatedAttr {
|
||||
item_ident: ident.clone(),
|
||||
py_name: item_meta.simple_name()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_const_attr(
|
||||
ident: &Ident,
|
||||
nesteds: Vec<NestedMeta>,
|
||||
) -> Result<ModuleItem, Diagnostic> {
|
||||
let item_meta =
|
||||
ItemMeta::from_nested_meta("pyattr", &ident, &nesteds, ItemMeta::SIMPLE_NAMES)?;
|
||||
Ok(ModuleItem::ConstAttr {
|
||||
item_ident: ident.clone(),
|
||||
py_name: item_meta.simple_name()?,
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_class_attr(
|
||||
ident: &Ident,
|
||||
nesteds: Vec<NestedMeta>,
|
||||
) -> Result<ModuleItem, Diagnostic> {
|
||||
let item_meta =
|
||||
ItemMeta::from_nested_meta("pyattr", &ident, &nesteds, ItemMeta::SIMPLE_NAMES)?;
|
||||
Ok(ModuleItem::ClassAttr {
|
||||
item_ident: ident.clone(),
|
||||
py_name: item_meta.optional_name(),
|
||||
})
|
||||
}
|
||||
|
||||
fn extract_item_from_syn(&mut self, item: &mut ItemIdent) -> Result<(), Diagnostic> {
|
||||
let mut attr_idxs = Vec::new();
|
||||
let mut items = Vec::new();
|
||||
let mut cfgs = Vec::new();
|
||||
let mut has_class = false;
|
||||
for (i, attr) in item.attrs.iter_mut().enumerate() {
|
||||
let meta = attr.parse_meta()?;
|
||||
let meta_span = meta.span();
|
||||
let name = match meta.path().get_ident() {
|
||||
Some(name) => name.clone(),
|
||||
None => continue,
|
||||
};
|
||||
|
||||
let into_nested = || {
|
||||
meta_into_nesteds(meta.clone()).map_err(|meta| {
|
||||
err_span!(
|
||||
meta,
|
||||
"#[{name} = \"...\"] cannot be a name/value, you probably meant \
|
||||
#[{name}(name = \"...\")]",
|
||||
name = name.to_string(),
|
||||
)
|
||||
})
|
||||
};
|
||||
match name.to_string().as_str() {
|
||||
"pyfunction" => {
|
||||
assert!(item.typ == ItemType::Fn);
|
||||
attr_idxs.push(i);
|
||||
items.push((
|
||||
Self::extract_function(item.ident, into_nested()?)?,
|
||||
meta_span,
|
||||
));
|
||||
}
|
||||
"pyattr" => {
|
||||
attr_idxs.push(i);
|
||||
let item = match item.typ {
|
||||
ItemType::Fn => Self::extract_evaluated_attr(item.ident, into_nested()?)?,
|
||||
ItemType::Const => Self::extract_const_attr(item.ident, into_nested()?)?,
|
||||
ItemType::Struct | ItemType::Enum => {
|
||||
if has_class {
|
||||
return Err(err_span!(
|
||||
meta,
|
||||
"#[pyattr] must be placed on top of #[pyclass] or #[pystruct_sequence]",
|
||||
));
|
||||
}
|
||||
Self::extract_class_attr(item.ident, into_nested()?)?
|
||||
}
|
||||
ItemType::Use => Self::extract_const_attr(item.ident, into_nested()?)?,
|
||||
ItemType::Method => unreachable!(),
|
||||
};
|
||||
items.push((item, meta_span));
|
||||
}
|
||||
attr_name @ "pyclass" | attr_name @ "pystruct_sequence" => {
|
||||
assert!(item.typ == ItemType::Struct);
|
||||
|
||||
let nested_or = into_nested();
|
||||
let mut metalist = match &meta {
|
||||
Meta::Path(path) => parse_quote!(#path()),
|
||||
Meta::List(metalist) => metalist.clone(),
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if let Ok(nested) = &nested_or {
|
||||
if optional_attribute_arg("py..", "module", &nested)?.is_none() {
|
||||
let module_name = &self.name;
|
||||
metalist.nested.push(parse_quote! {module = #module_name});
|
||||
*attr = parse_quote!(#[#metalist]);
|
||||
}
|
||||
}
|
||||
|
||||
if has_class {
|
||||
Err(err_span!(
|
||||
meta,
|
||||
"#[{}] in module cannot be duplicated",
|
||||
attr_name,
|
||||
))
|
||||
} else if !items
|
||||
.iter()
|
||||
.all(|(item, _span)| matches!(item, ModuleItem::ClassAttr{..}))
|
||||
{
|
||||
Err(err_span!(
|
||||
meta,
|
||||
"#[{}] is allowed to have only #[pyattr] as siblings",
|
||||
attr_name,
|
||||
))
|
||||
} else {
|
||||
has_class = true;
|
||||
Ok(())
|
||||
}?;
|
||||
|
||||
let class = match attr_name {
|
||||
"pyclass" => Self::extract_class(item.ident, nested_or?)?,
|
||||
"pystruct_sequence" => {
|
||||
// TODO: validate pystruct_sequence doesn't have module
|
||||
Self::extract_struct_sequence(item.ident, nested_or?)?
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
|
||||
if items.is_empty() {
|
||||
items.push((class, meta_span));
|
||||
} else {
|
||||
for (attr, _) in items.iter_mut() {
|
||||
match attr {
|
||||
ModuleItem::ClassAttr { py_name, .. } => {
|
||||
if py_name.is_none() {
|
||||
*py_name = Some(class.name());
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
"cfg" => {
|
||||
cfgs.push(meta);
|
||||
continue;
|
||||
}
|
||||
_ => {
|
||||
continue;
|
||||
}
|
||||
};
|
||||
}
|
||||
for (item, meta) in items {
|
||||
self.add_item(item, cfgs.clone(), meta)?;
|
||||
}
|
||||
let mut i = 0;
|
||||
let mut attr_idxs = &*attr_idxs;
|
||||
item.attrs.retain(|_| {
|
||||
let drop = attr_idxs.first().copied() == Some(i);
|
||||
if drop {
|
||||
attr_idxs = &attr_idxs[1..];
|
||||
}
|
||||
i += 1;
|
||||
!drop
|
||||
});
|
||||
for (i, idx) in attr_idxs.iter().enumerate() {
|
||||
item.attrs.remove(idx - i);
|
||||
}
|
||||
// TODO: Add module to pystruct_sequence
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn extract_module_items(
|
||||
mut items: Vec<ItemIdent>,
|
||||
module_name: &str,
|
||||
) -> Result<TokenStream2, Diagnostic> {
|
||||
let mut diagnostics: Vec<Diagnostic> = Vec::new();
|
||||
|
||||
let mut module = Module {
|
||||
name: module_name.to_owned(),
|
||||
items: Default::default(),
|
||||
};
|
||||
|
||||
for item in items.iter_mut() {
|
||||
push_diag_result!(diagnostics, module.extract_item_from_syn(item),);
|
||||
}
|
||||
|
||||
let items = module
|
||||
.items
|
||||
.into_iter()
|
||||
.map(|((_name, cfgs), item)| match item {
|
||||
ModuleItem::Function {
|
||||
item_ident,
|
||||
py_name,
|
||||
} => {
|
||||
let new_func = quote_spanned!(
|
||||
item_ident.span() =>
|
||||
vm.ctx.new_function_named(#item_ident, #module_name.to_owned(), #py_name.to_owned()));
|
||||
quote! {
|
||||
#( #[ #cfgs ])*
|
||||
vm.__module_set_attr(&module, #py_name, #new_func).unwrap();
|
||||
}
|
||||
}
|
||||
ModuleItem::EvaluatedAttr {
|
||||
item_ident,
|
||||
py_name,
|
||||
} => {
|
||||
let new_attr = quote_spanned!(
|
||||
item_ident.span() =>
|
||||
vm.new_pyobj(#item_ident(vm)));
|
||||
quote! {
|
||||
#( #[ #cfgs ])*
|
||||
vm.__module_set_attr(&module, #py_name, #new_attr).unwrap();
|
||||
}
|
||||
}
|
||||
ModuleItem::ConstAttr {
|
||||
item_ident,
|
||||
py_name,
|
||||
} => {
|
||||
let new_attr = quote_spanned!(
|
||||
item_ident.span() =>
|
||||
vm.new_pyobj(#item_ident));
|
||||
quote! {
|
||||
#( #[ #cfgs ])*
|
||||
vm.__module_set_attr(&module, #py_name, #new_attr).unwrap();
|
||||
}
|
||||
}
|
||||
class => {
|
||||
let (item_ident, py_name) = match class {
|
||||
ModuleItem::ClassAttr {
|
||||
item_ident,
|
||||
py_name: Some(py_name),
|
||||
} => (item_ident, py_name),
|
||||
ModuleItem::Class {
|
||||
item_ident,
|
||||
py_name,
|
||||
} => (item_ident, py_name),
|
||||
_ => unreachable!()
|
||||
};
|
||||
let new_class = quote_spanned!(
|
||||
item_ident.span() =>
|
||||
#item_ident::make_class(&vm.ctx));
|
||||
quote! {
|
||||
#( #[ #cfgs ])*
|
||||
vm.__module_set_attr(&module, #py_name, #new_class).unwrap();
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
Diagnostic::from_vec(diagnostics)?;
|
||||
|
||||
Ok(quote! {
|
||||
#(#items)*
|
||||
})
|
||||
}
|
||||
|
||||
pub fn impl_pymodule(attr: AttributeArgs, item: Item) -> Result<TokenStream2, Diagnostic> {
|
||||
let mut module = match item {
|
||||
pub fn impl_pymodule(
|
||||
attr: AttributeArgs,
|
||||
module_item: Item,
|
||||
) -> std::result::Result<TokenStream, Diagnostic> {
|
||||
let mut module_item = match module_item {
|
||||
Item::Mod(m) => m,
|
||||
other => bail_span!(other, "#[pymodule] can only be on a module declaration"),
|
||||
other => bail_span!(other, "#[pymodule] can only be on a full module"),
|
||||
};
|
||||
let module_name = def_to_name("pymodule", &module.ident, &attr)?;
|
||||
let fake_ident = Ident::new("pymodule", module_item.span());
|
||||
let module_meta =
|
||||
SimpleItemMeta::from_nested(module_item.ident.clone(), fake_ident, attr.into_iter())?;
|
||||
|
||||
let (_, content) = match module.content.as_mut() {
|
||||
Some(c) => c,
|
||||
None => bail_span!(
|
||||
module,
|
||||
"#[pymodule] can only be on a module declaration with body"
|
||||
),
|
||||
// generation resources
|
||||
let mut context = ModuleContext {
|
||||
name: module_meta.simple_name()?,
|
||||
..Default::default()
|
||||
};
|
||||
let items = module_item.items_mut().ok_or_else(|| {
|
||||
module_meta.new_meta_error("requires actual module, not a module declaration")
|
||||
})?;
|
||||
|
||||
let items = content
|
||||
.iter_mut()
|
||||
.filter_map(|item| {
|
||||
let item = match item {
|
||||
Item::Fn(syn::ItemFn { attrs, sig, .. }) => ItemIdent {
|
||||
typ: ItemType::Fn,
|
||||
// collect to context
|
||||
for item in items.iter_mut() {
|
||||
let r = item.try_split_attr_mut(|attrs, item| {
|
||||
let (pyitems, cfgs) = attrs_to_module_items(&attrs, new_module_item)?;
|
||||
for pyitem in pyitems.iter().rev() {
|
||||
let r = pyitem.gen_module_item(ModuleItemArgs {
|
||||
item,
|
||||
attrs,
|
||||
ident: &sig.ident,
|
||||
},
|
||||
Item::Struct(syn::ItemStruct { attrs, ident, .. }) => ItemIdent {
|
||||
typ: ItemType::Struct,
|
||||
attrs,
|
||||
ident,
|
||||
},
|
||||
Item::Enum(syn::ItemEnum { attrs, ident, .. }) => ItemIdent {
|
||||
typ: ItemType::Enum,
|
||||
attrs,
|
||||
ident,
|
||||
},
|
||||
Item::Const(syn::ItemConst { attrs, ident, .. }) => ItemIdent {
|
||||
typ: ItemType::Const,
|
||||
attrs,
|
||||
ident,
|
||||
},
|
||||
Item::Use(syn::ItemUse { attrs, tree, .. }) => {
|
||||
let ident = match tree {
|
||||
UseTree::Path(path) => match &*path.tree {
|
||||
UseTree::Name(name) => &name.ident,
|
||||
UseTree::Rename(rename) => &rename.rename,
|
||||
_ => return None,
|
||||
},
|
||||
_ => return None,
|
||||
};
|
||||
ItemIdent {
|
||||
typ: ItemType::Use,
|
||||
attrs,
|
||||
ident,
|
||||
}
|
||||
}
|
||||
_ => return None,
|
||||
};
|
||||
Some(item)
|
||||
})
|
||||
.collect();
|
||||
context: &mut context,
|
||||
cfgs: cfgs.as_slice(),
|
||||
});
|
||||
context.errors.ok_or_push(r);
|
||||
}
|
||||
Ok(())
|
||||
});
|
||||
context.errors.ok_or_push(r);
|
||||
}
|
||||
|
||||
let extend_mod = extract_module_items(items, &module_name)?;
|
||||
content.extend(vec![
|
||||
// append additional items
|
||||
let module_name = context.name.as_str();
|
||||
let module_extend_items = context.module_extend_items;
|
||||
items.extend(vec![
|
||||
parse_quote! {
|
||||
pub(crate) const MODULE_NAME: &str = #module_name;
|
||||
pub(crate) const MODULE_NAME: &'static str = #module_name;
|
||||
},
|
||||
parse_quote! {
|
||||
pub(crate) fn extend_module(
|
||||
vm: &::rustpython_vm::vm::VirtualMachine,
|
||||
module: &::rustpython_vm::pyobject::PyObjectRef,
|
||||
) {
|
||||
#extend_mod
|
||||
#module_extend_items
|
||||
}
|
||||
},
|
||||
parse_quote! {
|
||||
@@ -452,5 +81,329 @@ pub fn impl_pymodule(attr: AttributeArgs, item: Item) -> Result<TokenStream2, Di
|
||||
},
|
||||
]);
|
||||
|
||||
Ok(module.into_token_stream())
|
||||
Ok(if let Some(error) = context.errors.into_error() {
|
||||
let error = Diagnostic::from(error);
|
||||
quote! {
|
||||
#module_item
|
||||
#error
|
||||
}
|
||||
} else {
|
||||
module_item.into_token_stream()
|
||||
})
|
||||
}
|
||||
|
||||
fn new_module_item(
|
||||
index: usize,
|
||||
attr_name: String,
|
||||
pyattrs: Option<Vec<usize>>,
|
||||
) -> Box<dyn ModuleItem> {
|
||||
assert!(ALL_ALLOWED_NAMES.contains(&attr_name.as_str()));
|
||||
match attr_name.as_str() {
|
||||
"pyfunction" => Box::new(FunctionItem {
|
||||
inner: ContentItemInner { index, attr_name },
|
||||
}),
|
||||
"pyattr" => Box::new(AttributeItem {
|
||||
inner: ContentItemInner { index, attr_name },
|
||||
}),
|
||||
"pystruct_sequence" | "pyclass" => Box::new(ClassItem {
|
||||
inner: ContentItemInner { index, attr_name },
|
||||
pyattrs: pyattrs.unwrap_or_else(Vec::new),
|
||||
}),
|
||||
other => unreachable!("#[pymodule] doesn't accept #[{}]", other),
|
||||
}
|
||||
}
|
||||
|
||||
fn attrs_to_module_items<F, R>(attrs: &[Attribute], new_item: F) -> Result<(Vec<R>, Vec<Attribute>)>
|
||||
where
|
||||
F: Fn(usize, String, Option<Vec<usize>>) -> R,
|
||||
{
|
||||
let mut cfgs: Vec<Attribute> = Vec::new();
|
||||
let mut result = Vec::new();
|
||||
|
||||
let mut iter = attrs.iter().enumerate().peekable();
|
||||
while let Some((_, attr)) = iter.peek() {
|
||||
// take all cfgs but no py items
|
||||
let attr = *attr;
|
||||
let attr_name = if let Some(ident) = attr.get_ident() {
|
||||
ident.to_string()
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
if attr_name == "cfg" {
|
||||
cfgs.push(attr.clone());
|
||||
} else if ALL_ALLOWED_NAMES.contains(&attr_name.as_str()) {
|
||||
break;
|
||||
}
|
||||
iter.next();
|
||||
}
|
||||
|
||||
let mut closed = false;
|
||||
let mut pyattrs = Vec::new();
|
||||
for (i, attr) in iter {
|
||||
// take py items but no cfgs
|
||||
let attr_name = if let Some(ident) = attr.get_ident() {
|
||||
ident.to_string()
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
if attr_name == "cfg" {
|
||||
return Err(syn::Error::new_spanned(
|
||||
attr,
|
||||
"#[py*] items must be placed under `cfgs`",
|
||||
));
|
||||
}
|
||||
if !ALL_ALLOWED_NAMES.contains(&attr_name.as_str()) {
|
||||
continue;
|
||||
} else if closed {
|
||||
return Err(syn::Error::new_spanned(
|
||||
attr,
|
||||
"Only one #[pyattr] annotated #[py*] item can exist",
|
||||
));
|
||||
}
|
||||
|
||||
if attr_name == "pyattr" {
|
||||
if !result.is_empty() {
|
||||
return Err(syn::Error::new_spanned(
|
||||
attr,
|
||||
"#[pyattr] must be placed on top of other #[py*] items",
|
||||
));
|
||||
}
|
||||
pyattrs.push((i, attr_name));
|
||||
continue;
|
||||
}
|
||||
|
||||
if pyattrs.is_empty() {
|
||||
result.push(new_item(i, attr_name, None));
|
||||
} else {
|
||||
if !["pyclass", "pystruct_sequence"].contains(&attr_name.as_str()) {
|
||||
return Err(syn::Error::new_spanned(
|
||||
attr,
|
||||
"#[pyattr] #[pyclass] is the only supported composition",
|
||||
));
|
||||
}
|
||||
let pyattr_indexes = pyattrs.iter().map(|(i, _)| i).copied().collect();
|
||||
result.push(new_item(i, attr_name, Some(pyattr_indexes)));
|
||||
pyattrs = Vec::new();
|
||||
closed = true;
|
||||
}
|
||||
}
|
||||
for (index, attr_name) in pyattrs {
|
||||
assert!(!closed);
|
||||
result.push(new_item(index, attr_name, None));
|
||||
}
|
||||
Ok((result, cfgs))
|
||||
}
|
||||
|
||||
/// #[pyfunction]
|
||||
struct FunctionItem {
|
||||
inner: ContentItemInner,
|
||||
}
|
||||
|
||||
/// #[pyclass] or #[pystruct_sequence]
|
||||
struct ClassItem {
|
||||
inner: ContentItemInner,
|
||||
pyattrs: Vec<usize>,
|
||||
}
|
||||
|
||||
/// #[pyattr]
|
||||
struct AttributeItem {
|
||||
inner: ContentItemInner,
|
||||
}
|
||||
|
||||
impl ContentItem for FunctionItem {
|
||||
fn inner(&self) -> &ContentItemInner {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl ContentItem for ClassItem {
|
||||
fn inner(&self) -> &ContentItemInner {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
impl ContentItem for AttributeItem {
|
||||
fn inner(&self) -> &ContentItemInner {
|
||||
&self.inner
|
||||
}
|
||||
}
|
||||
|
||||
struct ModuleItemArgs<'a> {
|
||||
item: &'a Item,
|
||||
attrs: &'a mut Vec<Attribute>,
|
||||
context: &'a mut ModuleContext,
|
||||
cfgs: &'a [Attribute],
|
||||
}
|
||||
|
||||
impl<'a> ModuleItemArgs<'a> {
|
||||
fn module_name(&'a self) -> &'a str {
|
||||
self.context.name.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
trait ModuleItem: ContentItem {
|
||||
fn gen_module_item(&self, args: ModuleItemArgs<'_>) -> Result<()>;
|
||||
}
|
||||
|
||||
impl ModuleItem for FunctionItem {
|
||||
fn gen_module_item(&self, args: ModuleItemArgs<'_>) -> Result<()> {
|
||||
let ident = match args.item {
|
||||
Item::Fn(syn::ItemFn { sig, .. }) => sig.ident.clone(),
|
||||
other => return Err(self.new_syn_error(other.span(), "can only be on a function")),
|
||||
};
|
||||
|
||||
let item_attr = args.attrs.remove(self.index());
|
||||
let item_meta = SimpleItemMeta::from_nested(
|
||||
ident.clone(),
|
||||
item_attr.get_ident().unwrap().clone(),
|
||||
item_attr.promoted_nested()?.into_iter(),
|
||||
)?;
|
||||
|
||||
let py_name = item_meta.simple_name()?;
|
||||
let item = {
|
||||
let module = args.module_name();
|
||||
let new_func = quote_spanned!(
|
||||
ident.span() => vm.ctx.new_function_named(#ident, #module.to_owned(), #py_name.to_owned())
|
||||
);
|
||||
quote! {
|
||||
vm.__module_set_attr(&module, #py_name, #new_func).unwrap();
|
||||
}
|
||||
};
|
||||
|
||||
args.context
|
||||
.module_extend_items
|
||||
.add_item(py_name, args.cfgs.to_vec(), item)?;
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleItem for ClassItem {
|
||||
fn gen_module_item(&self, args: ModuleItemArgs<'_>) -> Result<()> {
|
||||
let (ident, _) = pyclass_ident_and_attrs(&args.item)?;
|
||||
let (module_name, class_name) = {
|
||||
let class_attr = &mut args.attrs[self.inner.index];
|
||||
if self.pyattrs.is_empty() {
|
||||
// check noattr before ClassItemMeta::from_nested
|
||||
let noattr = class_attr.try_remove_name("noattr")?;
|
||||
if noattr.is_none() {
|
||||
return Err(syn::Error::new_spanned(
|
||||
class_attr,
|
||||
format!(
|
||||
"#[{name}] requires #[pyattr] to be a module attribute. \
|
||||
To keep it free type, try #[{name}(noattr)]",
|
||||
name = self.attr_name()
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
|
||||
let class_meta = ClassItemMeta::from_nested(
|
||||
ident.clone(),
|
||||
class_attr.get_ident().unwrap().clone(),
|
||||
class_attr.promoted_nested()?.into_iter(),
|
||||
)?;
|
||||
let module_name = args.context.name.clone();
|
||||
class_attr.fill_nested_meta("module", || {
|
||||
parse_quote! {module = #module_name}
|
||||
})?;
|
||||
let class_name = class_meta.class_name()?;
|
||||
(module_name, class_name)
|
||||
};
|
||||
for attr_index in self.pyattrs.iter().rev() {
|
||||
let mut loop_unit = || {
|
||||
let attr_attr = args.attrs.remove(*attr_index);
|
||||
let (meta_ident, nested) = attr_attr.ident_and_promoted_nested()?;
|
||||
let item_meta = SimpleItemMeta::from_nested(
|
||||
ident.clone(),
|
||||
meta_ident.clone(),
|
||||
nested.into_iter(),
|
||||
)?;
|
||||
|
||||
let py_name = item_meta
|
||||
.optional_name()
|
||||
.unwrap_or_else(|| class_name.clone());
|
||||
let new_class = quote_spanned!(ident.span() =>
|
||||
#ident::make_class(&vm.ctx);
|
||||
);
|
||||
let item = quote! {
|
||||
let new_class = #new_class;
|
||||
new_class.set_str_attr("__module__", vm.ctx.new_str(#module_name));
|
||||
vm.__module_set_attr(&module, #py_name, new_class).unwrap();
|
||||
};
|
||||
|
||||
args.context
|
||||
.module_extend_items
|
||||
.add_item(py_name, args.cfgs.to_vec(), item)?;
|
||||
Ok(())
|
||||
};
|
||||
let r = loop_unit();
|
||||
args.context.errors.ok_or_push(r);
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
impl ModuleItem for AttributeItem {
|
||||
fn gen_module_item(&self, args: ModuleItemArgs<'_>) -> Result<()> {
|
||||
let get_py_name = |attrs: &mut Vec<Attribute>, ident: &Ident| -> Result<_> {
|
||||
let (meta_ident, nested) = attrs[self.inner.index].ident_and_promoted_nested()?;
|
||||
let item_meta =
|
||||
SimpleItemMeta::from_nested(ident.clone(), meta_ident.clone(), nested.into_iter())?;
|
||||
let py_name = item_meta.simple_name()?;
|
||||
Ok(py_name)
|
||||
};
|
||||
let (py_name, tokens) = match args.item {
|
||||
Item::Fn(syn::ItemFn { sig, .. }) => {
|
||||
let ident = &sig.ident;
|
||||
let py_name = get_py_name(args.attrs, &ident)?;
|
||||
(
|
||||
py_name.clone(),
|
||||
quote! {
|
||||
vm.__module_set_attr(&module, #py_name, vm.new_pyobj(#ident(vm))).unwrap();
|
||||
},
|
||||
)
|
||||
}
|
||||
Item::Const(syn::ItemConst { ident, .. }) => {
|
||||
let py_name = get_py_name(args.attrs, &ident)?;
|
||||
(
|
||||
py_name.clone(),
|
||||
quote! {
|
||||
vm.__module_set_attr(&module, #py_name, vm.new_pyobj(#ident)).unwrap();
|
||||
},
|
||||
)
|
||||
}
|
||||
Item::Use(syn::ItemUse {
|
||||
tree: UseTree::Path(path),
|
||||
..
|
||||
}) => {
|
||||
let ident = match &*path.tree {
|
||||
UseTree::Name(name) => &name.ident,
|
||||
UseTree::Rename(rename) => &rename.rename,
|
||||
other => {
|
||||
return Err(self.new_syn_error(other.span(), "can only be a simple use"));
|
||||
}
|
||||
};
|
||||
|
||||
let py_name = get_py_name(args.attrs, &ident)?;
|
||||
(
|
||||
py_name.clone(),
|
||||
quote! {
|
||||
vm.__module_set_attr(&module, #py_name, vm.new_pyobj(#ident)).unwrap();
|
||||
},
|
||||
)
|
||||
}
|
||||
other => {
|
||||
return Err(
|
||||
self.new_syn_error(other.span(), "can only be on a function, const and use")
|
||||
)
|
||||
}
|
||||
};
|
||||
args.attrs.remove(self.index());
|
||||
|
||||
args.context
|
||||
.module_extend_items
|
||||
.add_item(py_name, args.cfgs.to_vec(), tokens)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
+425
-249
@@ -1,269 +1,445 @@
|
||||
use super::Diagnostic;
|
||||
use proc_macro2::{Span, TokenStream};
|
||||
use quote::{quote, ToTokens};
|
||||
use std::collections::HashMap;
|
||||
use syn::{Attribute, Ident, Lit, Meta, NestedMeta, Path};
|
||||
use syn::{spanned::Spanned, Attribute, Ident, Meta, MetaList, NestedMeta, Path, Result};
|
||||
use syn_ext::ext::{AttributeExt as SynAttributeExt, *};
|
||||
use syn_ext::types::PunctuatedNestedMeta;
|
||||
|
||||
pub(crate) const ALL_ALLOWED_NAMES: &[&str] = &[
|
||||
"pymethod",
|
||||
"pyclassmethod",
|
||||
"pyproperty",
|
||||
"pyfunction",
|
||||
"pyclass",
|
||||
"pystruct_sequence",
|
||||
"pyattr",
|
||||
"pyslot",
|
||||
];
|
||||
|
||||
#[derive(Default)]
|
||||
pub(crate) struct ItemNursery(HashMap<(String, Vec<Attribute>), TokenStream>);
|
||||
|
||||
impl ItemNursery {
|
||||
pub fn add_item(
|
||||
&mut self,
|
||||
name: String,
|
||||
cfgs: Vec<Attribute>,
|
||||
tokens: TokenStream,
|
||||
) -> Result<()> {
|
||||
if let Some(existing) = self.0.insert((name, cfgs), tokens) {
|
||||
Err(syn::Error::new_spanned(
|
||||
existing,
|
||||
"Duplicated #[py*] attribute found",
|
||||
))
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl ToTokens for ItemNursery {
|
||||
fn to_tokens(&self, tokens: &mut TokenStream) {
|
||||
tokens.extend(self.0.iter().map(|((_, cfgs), item)| {
|
||||
quote! {
|
||||
#( #cfgs )*
|
||||
{
|
||||
#item
|
||||
}
|
||||
}
|
||||
}))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct ContentItemInner {
|
||||
pub index: usize,
|
||||
pub attr_name: String,
|
||||
}
|
||||
|
||||
pub(crate) trait ContentItem {
|
||||
fn inner(&self) -> &ContentItemInner;
|
||||
fn index(&self) -> usize {
|
||||
self.inner().index
|
||||
}
|
||||
fn attr_name(&self) -> &str {
|
||||
self.inner().attr_name.as_str()
|
||||
}
|
||||
fn new_syn_error(&self, span: Span, message: &str) -> syn::Error {
|
||||
syn::Error::new(span, format!("#[{}] {}", self.attr_name(), message))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ItemMetaInner {
|
||||
pub item_ident: Ident,
|
||||
pub meta_ident: Ident,
|
||||
pub meta_map: HashMap<String, (usize, Meta)>,
|
||||
}
|
||||
|
||||
impl ItemMetaInner {
|
||||
pub fn from_nested<I>(
|
||||
item_ident: Ident,
|
||||
meta_ident: Ident,
|
||||
nested: I,
|
||||
allowed_names: &[&'static str],
|
||||
) -> Result<Self>
|
||||
where
|
||||
I: std::iter::Iterator<Item = NestedMeta>,
|
||||
{
|
||||
let (meta_map, lits) = nested.into_unique_map_and_lits(|path| {
|
||||
if let Some(ident) = path.get_ident() {
|
||||
let name = ident.to_string();
|
||||
if allowed_names.contains(&name.as_str()) {
|
||||
Ok(Some(name))
|
||||
} else {
|
||||
Err(syn::Error::new_spanned(
|
||||
ident,
|
||||
format!(
|
||||
"#[{}({})] is not one of allowed attributes {}",
|
||||
meta_ident.to_string(),
|
||||
name,
|
||||
allowed_names.join(", ")
|
||||
),
|
||||
))
|
||||
}
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
})?;
|
||||
if !lits.is_empty() {
|
||||
return Err(syn::Error::new_spanned(
|
||||
&meta_ident,
|
||||
format!("#[{}(..)] cannot contain literal", meta_ident.to_string()),
|
||||
));
|
||||
}
|
||||
|
||||
Ok(Self {
|
||||
item_ident,
|
||||
meta_ident,
|
||||
meta_map,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn item_name(&self) -> String {
|
||||
self.item_ident.to_string()
|
||||
}
|
||||
|
||||
pub fn meta_name(&self) -> String {
|
||||
self.meta_ident.to_string()
|
||||
}
|
||||
|
||||
pub fn _optional_str(&self, key: &str) -> Result<Option<String>> {
|
||||
let value = if let Some((_, meta)) = self.meta_map.get(key) {
|
||||
match meta {
|
||||
Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(lit),
|
||||
..
|
||||
}) => Some(lit.value()),
|
||||
other => {
|
||||
return Err(syn::Error::new_spanned(
|
||||
other,
|
||||
format!(
|
||||
"#[{}({} = ...)] must exist as a string",
|
||||
self.meta_name(),
|
||||
key
|
||||
),
|
||||
));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
None
|
||||
};
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn _bool(&self, key: &str) -> Result<bool> {
|
||||
let value = if let Some((_, meta)) = self.meta_map.get(key) {
|
||||
match meta {
|
||||
Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Bool(lit),
|
||||
..
|
||||
}) => lit.value,
|
||||
Meta::Path(_) => true,
|
||||
other => {
|
||||
return Err(syn::Error::new_spanned(
|
||||
other,
|
||||
format!("#[{}({})] is expected", self.meta_name(), key),
|
||||
))
|
||||
}
|
||||
}
|
||||
} else {
|
||||
false
|
||||
};
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait ItemMeta: Sized {
|
||||
const ALLOWED_NAMES: &'static [&'static str];
|
||||
|
||||
fn from_nested<I>(item_ident: Ident, meta_ident: Ident, nested: I) -> Result<Self>
|
||||
where
|
||||
I: std::iter::Iterator<Item = NestedMeta>,
|
||||
{
|
||||
Ok(Self::from_inner(ItemMetaInner::from_nested(
|
||||
item_ident,
|
||||
meta_ident,
|
||||
nested,
|
||||
Self::ALLOWED_NAMES,
|
||||
)?))
|
||||
}
|
||||
|
||||
fn from_inner(inner: ItemMetaInner) -> Self;
|
||||
fn inner(&self) -> &ItemMetaInner;
|
||||
|
||||
fn simple_name(&self) -> Result<String> {
|
||||
let inner = self.inner();
|
||||
Ok(inner
|
||||
._optional_str("name")?
|
||||
.unwrap_or_else(|| inner.item_name()))
|
||||
}
|
||||
|
||||
fn optional_name(&self) -> Option<String> {
|
||||
self.inner()._optional_str("name").ok().flatten()
|
||||
}
|
||||
|
||||
fn new_meta_error(&self, msg: &str) -> syn::Error {
|
||||
let inner = self.inner();
|
||||
syn::Error::new_spanned(
|
||||
&inner.meta_ident,
|
||||
format!("#[{}] {}", inner.meta_name(), msg),
|
||||
)
|
||||
}
|
||||
}
|
||||
pub(crate) struct SimpleItemMeta(pub ItemMetaInner);
|
||||
|
||||
impl ItemMeta for SimpleItemMeta {
|
||||
const ALLOWED_NAMES: &'static [&'static str] = &["name"];
|
||||
|
||||
fn from_inner(inner: ItemMetaInner) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
fn inner(&self) -> &ItemMetaInner {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct ClassItemMeta(ItemMetaInner);
|
||||
|
||||
impl ItemMeta for ClassItemMeta {
|
||||
const ALLOWED_NAMES: &'static [&'static str] = &["module", "name"];
|
||||
|
||||
fn from_inner(inner: ItemMetaInner) -> Self {
|
||||
Self(inner)
|
||||
}
|
||||
fn inner(&self) -> &ItemMetaInner {
|
||||
&self.0
|
||||
}
|
||||
}
|
||||
|
||||
impl ClassItemMeta {
|
||||
pub fn class_name(&self) -> Result<String> {
|
||||
const KEY: &str = "name";
|
||||
let inner = self.inner();
|
||||
let value = if let Some((_, meta)) = inner.meta_map.get(KEY) {
|
||||
match meta {
|
||||
Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(lit),
|
||||
..
|
||||
}) => Some(lit.value()),
|
||||
Meta::Path(_) => Some(inner.item_name()),
|
||||
_ => None,
|
||||
}
|
||||
} else {
|
||||
None
|
||||
}.ok_or_else(|| syn::Error::new_spanned(
|
||||
&inner.meta_ident,
|
||||
format!(
|
||||
"#[{attr_name}(name = ...)] must exist as a string. Try #[{attr_name}(name)] to use rust type name.",
|
||||
attr_name=inner.meta_name()
|
||||
),
|
||||
))?;
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn module(&self) -> Result<Option<String>> {
|
||||
const KEY: &str = "module";
|
||||
let inner = self.inner();
|
||||
let value = if let Some((_, meta)) = inner.meta_map.get(KEY) {
|
||||
match meta {
|
||||
Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Str(lit),
|
||||
..
|
||||
}) => Ok(Some(lit.value())),
|
||||
Meta::NameValue(syn::MetaNameValue {
|
||||
lit: syn::Lit::Bool(lit),
|
||||
..
|
||||
}) => if lit.value {
|
||||
Err(lit.span())
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
other => Err(other.span()),
|
||||
}
|
||||
} else {
|
||||
Err(inner.item_ident.span())
|
||||
}.map_err(|span| syn::Error::new(
|
||||
span,
|
||||
format!(
|
||||
"#[{attr_name}(module = ...)] must exist as a string or false. Try #[{attr_name}(module=false)] for built-in types.",
|
||||
attr_name=inner.meta_name()
|
||||
),
|
||||
))?;
|
||||
Ok(value)
|
||||
}
|
||||
|
||||
pub fn mandatory_module(&self) -> Result<String> {
|
||||
let inner = self.inner();
|
||||
let value = self.module().ok().flatten().
|
||||
ok_or_else(|| syn::Error::new_spanned(
|
||||
&inner.meta_ident,
|
||||
format!(
|
||||
"#[{attr_name}(module = ...)] must exist as a string. Built-in module is not allowed here.",
|
||||
attr_name=inner.meta_name()
|
||||
),
|
||||
))?;
|
||||
Ok(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn path_eq(path: &Path, s: &str) -> bool {
|
||||
path.get_ident().map_or(false, |id| id == s)
|
||||
}
|
||||
|
||||
pub(crate) fn def_to_name(
|
||||
attr_name: &'static str,
|
||||
ident: &Ident,
|
||||
attrs: &[NestedMeta],
|
||||
) -> Result<String, Diagnostic> {
|
||||
optional_attribute_arg(attr_name, "name", attrs)
|
||||
.transpose()
|
||||
.unwrap_or_else(|| Ok(ident.to_string()))
|
||||
pub(crate) trait AttributeExt: SynAttributeExt {
|
||||
fn promoted_nested(&self) -> Result<PunctuatedNestedMeta>;
|
||||
fn ident_and_promoted_nested(&self) -> Result<(&Ident, PunctuatedNestedMeta)>;
|
||||
fn try_remove_name(&mut self, name: &str) -> Result<Option<syn::NestedMeta>>;
|
||||
fn fill_nested_meta<F>(&mut self, name: &str, new_item: F) -> Result<()>
|
||||
where
|
||||
F: Fn() -> NestedMeta;
|
||||
}
|
||||
|
||||
pub(crate) fn attribute_arg(
|
||||
attr_name: &'static str,
|
||||
arg_name: &'static str,
|
||||
attrs: &[NestedMeta],
|
||||
) -> Result<String, Diagnostic> {
|
||||
if let Some(r) = optional_attribute_arg(attr_name, arg_name, attrs).transpose() {
|
||||
r
|
||||
} else {
|
||||
bail_span!(
|
||||
attrs[0],
|
||||
"#[{}({} = ...)] must exist but not found",
|
||||
attr_name,
|
||||
arg_name
|
||||
)
|
||||
impl AttributeExt for Attribute {
|
||||
fn promoted_nested(&self) -> Result<PunctuatedNestedMeta> {
|
||||
let list = self.promoted_list().map_err(|mut e| {
|
||||
let name = self.get_ident().unwrap().to_string();
|
||||
e.combine(syn::Error::new_spanned(
|
||||
self,
|
||||
format!(
|
||||
"#[{name} = \"...\"] cannot be a name/value, you probably meant \
|
||||
#[{name}(name = \"...\")]",
|
||||
name = name,
|
||||
),
|
||||
));
|
||||
e
|
||||
})?;
|
||||
Ok(list.nested)
|
||||
}
|
||||
fn ident_and_promoted_nested(&self) -> Result<(&Ident, PunctuatedNestedMeta)> {
|
||||
Ok((self.get_ident().unwrap(), self.promoted_nested()?))
|
||||
}
|
||||
|
||||
fn try_remove_name(&mut self, item_name: &str) -> Result<Option<syn::NestedMeta>> {
|
||||
self.try_meta_mut(|meta| {
|
||||
let nested = match meta {
|
||||
Meta::List(MetaList { ref mut nested, .. }) => Ok(nested),
|
||||
other => Err(syn::Error::new(
|
||||
other.span(),
|
||||
format!(
|
||||
"#[{name}(...)] doesn't contain '{item}' to remove",
|
||||
name = other.get_ident().unwrap().to_string(),
|
||||
item = item_name
|
||||
),
|
||||
)),
|
||||
}?;
|
||||
|
||||
let mut found = None;
|
||||
for (i, item) in nested.iter().enumerate() {
|
||||
let ident = if let Some(ident) = item.get_ident() {
|
||||
ident
|
||||
} else {
|
||||
continue;
|
||||
};
|
||||
if *ident != item_name {
|
||||
continue;
|
||||
}
|
||||
if found.is_some() {
|
||||
return Err(syn::Error::new(
|
||||
item.span(),
|
||||
format!(
|
||||
"#[py..({}...)] must be unique but found multiple times",
|
||||
item_name,
|
||||
),
|
||||
));
|
||||
}
|
||||
found = Some(i);
|
||||
}
|
||||
|
||||
Ok(found.map(|idx| nested.remove(idx).into_value()))
|
||||
})
|
||||
}
|
||||
|
||||
fn fill_nested_meta<F>(&mut self, name: &str, new_item: F) -> Result<()>
|
||||
where
|
||||
F: Fn() -> NestedMeta,
|
||||
{
|
||||
self.try_meta_mut(|meta| {
|
||||
let list = meta.promote_to_list(Default::default())?;
|
||||
let has_name = list
|
||||
.nested
|
||||
.iter()
|
||||
.any(|nmeta| nmeta.get_path().map_or(false, |p| path_eq(p, name)));
|
||||
if !has_name {
|
||||
list.nested.push(new_item())
|
||||
}
|
||||
Ok(())
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn optional_attribute_arg(
|
||||
attr_name: &'static str,
|
||||
arg_name: &'static str,
|
||||
attrs: &[NestedMeta],
|
||||
) -> Result<Option<String>, Diagnostic> {
|
||||
let mut arg_value = None;
|
||||
for attr in attrs {
|
||||
match attr {
|
||||
NestedMeta::Meta(Meta::NameValue(name_value))
|
||||
if path_eq(&name_value.path, arg_name) =>
|
||||
{
|
||||
if let Lit::Str(lit) = &name_value.lit {
|
||||
if arg_value.is_some() {
|
||||
bail_span!(
|
||||
name_value.lit,
|
||||
"#[{}({} = ...)] must be unique but found multiple times",
|
||||
attr_name,
|
||||
arg_name
|
||||
);
|
||||
}
|
||||
arg_value = Some(lit.value());
|
||||
} else {
|
||||
bail_span!(
|
||||
name_value.lit,
|
||||
"#[{}({} = ...)] must be a string",
|
||||
attr_name,
|
||||
arg_name
|
||||
);
|
||||
}
|
||||
}
|
||||
_ => continue,
|
||||
pub(crate) fn pyclass_ident_and_attrs(item: &syn::Item) -> Result<(&Ident, &[Attribute])> {
|
||||
use syn::Item::*;
|
||||
match item {
|
||||
Struct(syn::ItemStruct { ident, attrs, .. }) => Ok((ident, attrs)),
|
||||
Enum(syn::ItemEnum { ident, attrs, .. }) => Ok((ident, attrs)),
|
||||
other => Err(syn::Error::new_spanned(
|
||||
other,
|
||||
"#[pyclass] can only be on a struct or enum declaration",
|
||||
)),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) trait ErrorVec: Sized {
|
||||
fn into_error(self) -> Option<syn::Error>;
|
||||
fn into_result(self) -> Result<()> {
|
||||
if let Some(error) = self.into_error() {
|
||||
Err(error)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Ok(arg_value)
|
||||
fn ok_or_push<T>(&mut self, r: Result<T>) -> Option<T>;
|
||||
}
|
||||
|
||||
pub(crate) fn meta_into_nesteds(meta: Meta) -> Result<Vec<NestedMeta>, Meta> {
|
||||
match meta {
|
||||
Meta::Path(_) => Ok(Vec::new()),
|
||||
Meta::List(list) => Ok(list.nested.into_iter().collect()),
|
||||
Meta::NameValue(_) => Err(meta),
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(PartialEq)]
|
||||
pub(crate) enum ItemType {
|
||||
Fn,
|
||||
Method,
|
||||
Struct,
|
||||
Enum,
|
||||
Const,
|
||||
Use,
|
||||
}
|
||||
|
||||
pub(crate) struct ItemIdent<'a> {
|
||||
pub typ: ItemType,
|
||||
pub attrs: &'a mut Vec<Attribute>,
|
||||
pub ident: &'a Ident,
|
||||
}
|
||||
|
||||
pub(crate) struct ItemMeta<'a> {
|
||||
ident: &'a Ident,
|
||||
parent_type: &'static str,
|
||||
meta: HashMap<String, Option<Lit>>,
|
||||
}
|
||||
|
||||
impl<'a> ItemMeta<'a> {
|
||||
pub const SIMPLE_NAMES: &'static [&'static str] = &["name"];
|
||||
pub const STRUCT_SEQUENCE_NAMES: &'static [&'static str] = &["module", "name"];
|
||||
pub const ATTRIBUTE_NAMES: &'static [&'static str] = &["name", "magic"];
|
||||
pub const PROPERTY_NAMES: &'static [&'static str] = &["name", "magic", "setter"];
|
||||
|
||||
pub fn from_nested_meta(
|
||||
parent_type: &'static str,
|
||||
ident: &'a Ident,
|
||||
nested_meta: &[NestedMeta],
|
||||
names: &[&'static str],
|
||||
) -> Result<Self, Diagnostic> {
|
||||
let mut extracted = Self {
|
||||
ident,
|
||||
parent_type,
|
||||
meta: HashMap::new(),
|
||||
};
|
||||
|
||||
let validate_name = |name: &str, extracted: &Self| -> Result<(), Diagnostic> {
|
||||
if names.contains(&name) {
|
||||
if extracted.meta.contains_key(name) {
|
||||
bail_span!(ident, "#[{}] must have only one '{}'", parent_type, name);
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
} else {
|
||||
bail_span!(
|
||||
ident,
|
||||
"#[{}({})] is not one of allowed attributes {}",
|
||||
parent_type,
|
||||
name,
|
||||
names.join(", ")
|
||||
);
|
||||
impl ErrorVec for Vec<syn::Error> {
|
||||
fn into_error(self) -> Option<syn::Error> {
|
||||
let mut iter = self.into_iter();
|
||||
if let Some(mut first) = iter.next() {
|
||||
for err in iter {
|
||||
first.combine(err);
|
||||
}
|
||||
};
|
||||
|
||||
for meta in nested_meta {
|
||||
let meta = match meta {
|
||||
NestedMeta::Meta(meta) => meta,
|
||||
NestedMeta::Lit(_) => continue,
|
||||
};
|
||||
|
||||
match meta {
|
||||
Meta::NameValue(name_value) => {
|
||||
if let Some(ident) = name_value.path.get_ident() {
|
||||
let name = ident.to_string();
|
||||
validate_name(&name, &extracted)?;
|
||||
extracted.meta.insert(name, Some(name_value.lit.clone()));
|
||||
}
|
||||
}
|
||||
Meta::Path(path) => {
|
||||
if let Some(ident) = path.get_ident() {
|
||||
let name = ident.to_string();
|
||||
validate_name(&name, &extracted)?;
|
||||
extracted.meta.insert(name, None);
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
_ => (),
|
||||
Some(first)
|
||||
} else {
|
||||
None
|
||||
}
|
||||
}
|
||||
fn ok_or_push<T>(&mut self, r: Result<T>) -> Option<T> {
|
||||
match r {
|
||||
Ok(v) => Some(v),
|
||||
Err(e) => {
|
||||
self.push(e);
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
Ok(extracted)
|
||||
}
|
||||
|
||||
fn _str(&self, key: &str) -> Result<Option<String>, Diagnostic> {
|
||||
Ok(match self.meta.get(key) {
|
||||
Some(Some(lit)) => {
|
||||
if let Lit::Str(s) = lit {
|
||||
Some(s.value())
|
||||
} else {
|
||||
bail_span!(
|
||||
&self.ident,
|
||||
"#[{}({} = ...)] must be a string",
|
||||
self.parent_type,
|
||||
key
|
||||
);
|
||||
}
|
||||
}
|
||||
Some(None) => {
|
||||
bail_span!(
|
||||
&self.ident,
|
||||
"#[{}({} = ...)] is expected",
|
||||
self.parent_type,
|
||||
key,
|
||||
);
|
||||
}
|
||||
None => None,
|
||||
})
|
||||
}
|
||||
|
||||
fn _bool(&self, key: &str) -> Result<bool, Diagnostic> {
|
||||
Ok(match self.meta.get(key) {
|
||||
Some(Some(_)) => {
|
||||
bail_span!(&self.ident, "#[{}({})] is expected", self.parent_type, key,);
|
||||
}
|
||||
Some(None) => true,
|
||||
None => false,
|
||||
})
|
||||
}
|
||||
|
||||
pub fn simple_name(&self) -> Result<String, Diagnostic> {
|
||||
Ok(self._str("name")?.unwrap_or_else(|| self.ident.to_string()))
|
||||
}
|
||||
|
||||
pub fn optional_name(&self) -> Option<String> {
|
||||
self.simple_name().ok()
|
||||
}
|
||||
|
||||
pub fn method_name(&self) -> Result<String, Diagnostic> {
|
||||
let name = self._str("name")?;
|
||||
let magic = self._bool("magic")?;
|
||||
Ok(if let Some(name) = name {
|
||||
name
|
||||
} else {
|
||||
let name = self.ident.to_string();
|
||||
if magic {
|
||||
format!("__{}__", name)
|
||||
} else {
|
||||
name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn property_name(&self) -> Result<String, Diagnostic> {
|
||||
let magic = self._bool("magic")?;
|
||||
let setter = self._bool("setter")?;
|
||||
let name = self._str("name")?;
|
||||
|
||||
Ok(if let Some(name) = name {
|
||||
name
|
||||
} else {
|
||||
let sig_name = self.ident.to_string();
|
||||
let name = if setter {
|
||||
if let Some(name) = sig_name.strip_prefix("set_") {
|
||||
if name.is_empty() {
|
||||
bail_span!(
|
||||
&self.ident,
|
||||
"A #[{}(setter)] fn with a set_* name must \
|
||||
have something after \"set_\"",
|
||||
self.parent_type
|
||||
)
|
||||
}
|
||||
name.to_string()
|
||||
} else {
|
||||
bail_span!(
|
||||
&self.ident,
|
||||
"A #[{}(setter)] fn must either have a `name` \
|
||||
parameter or a fn name along the lines of \"set_*\"",
|
||||
self.parent_type
|
||||
)
|
||||
}
|
||||
} else {
|
||||
sig_name
|
||||
};
|
||||
if magic {
|
||||
format!("__{}__", name)
|
||||
} else {
|
||||
name
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
pub fn setter(&self) -> Result<bool, Diagnostic> {
|
||||
self._bool("setter")
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,7 @@ use std::io::{self, BufRead, BufReader};
|
||||
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
#[pyclass(name = "BaseException")]
|
||||
#[pyclass(module = false, name = "BaseException")]
|
||||
pub struct PyBaseException {
|
||||
traceback: PyRwLock<Option<PyTracebackRef>>,
|
||||
cause: PyRwLock<Option<PyBaseExceptionRef>>,
|
||||
|
||||
+1
-1
@@ -87,7 +87,7 @@ struct FrameState {
|
||||
blocks: Vec<Block>,
|
||||
}
|
||||
|
||||
#[pyclass(name = "frame")]
|
||||
#[pyclass(module = false, name = "frame")]
|
||||
pub struct Frame {
|
||||
pub code: PyCodeRef,
|
||||
pub scope: Scope,
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::vm::VirtualMachine;
|
||||
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
#[pyclass(name = "async_generator")]
|
||||
#[pyclass(name = "async_generator", module = false)]
|
||||
#[derive(Debug)]
|
||||
pub struct PyAsyncGen {
|
||||
inner: Coro,
|
||||
@@ -114,7 +114,7 @@ impl PyAsyncGen {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "async_generator_wrapped_value")]
|
||||
#[pyclass(module = false, name = "async_generator_wrapped_value")]
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct PyAsyncGenWrappedValue(pub PyObjectRef);
|
||||
impl PyValue for PyAsyncGenWrappedValue {
|
||||
@@ -158,7 +158,7 @@ enum AwaitableState {
|
||||
Closed,
|
||||
}
|
||||
|
||||
#[pyclass(name = "async_generator_asend")]
|
||||
#[pyclass(module = false, name = "async_generator_asend")]
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct PyAsyncGenASend {
|
||||
ag: PyAsyncGenRef,
|
||||
@@ -253,7 +253,7 @@ impl PyAsyncGenASend {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "async_generator_athrow")]
|
||||
#[pyclass(module = false, name = "async_generator_athrow")]
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct PyAsyncGenAThrow {
|
||||
ag: PyAsyncGenRef,
|
||||
|
||||
@@ -81,7 +81,7 @@ pub fn boolval(vm: &VirtualMachine, obj: PyObjectRef) -> PyResult<bool> {
|
||||
/// Returns True when the argument x is true, False otherwise.
|
||||
/// The builtins True and False are the only two instances of the class bool.
|
||||
/// The class bool is a subclass of the class int, and cannot be subclassed.
|
||||
#[pyclass(name = "bool")]
|
||||
#[pyclass(name = "bool", module = false)]
|
||||
pub(crate) struct PyBool;
|
||||
|
||||
#[pyimpl]
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::pyobject::{
|
||||
use crate::slots::{SlotCall, SlotDescriptor};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "builtin_function_or_method")]
|
||||
#[pyclass(name = "builtin_function_or_method", module = false)]
|
||||
pub struct PyBuiltinFunction {
|
||||
value: PyNativeFunc,
|
||||
module: Option<PyStringRef>,
|
||||
@@ -70,7 +70,7 @@ impl PyBuiltinFunction {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "method_descriptor")]
|
||||
#[pyclass(module = false, name = "method_descriptor")]
|
||||
pub struct PyBuiltinMethod {
|
||||
function: PyBuiltinFunction,
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ use crate::vm::VirtualMachine;
|
||||
/// - a bytes or a buffer object\n \
|
||||
/// - any object implementing the buffer API.\n \
|
||||
/// - an integer";
|
||||
#[pyclass(name = "bytearray")]
|
||||
#[pyclass(module = false, name = "bytearray")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyByteArray {
|
||||
inner: PyRwLock<PyBytesInner>,
|
||||
@@ -606,7 +606,7 @@ impl PyByteArray {
|
||||
// obj.borrow_mut().kind = PyObjectPayload::Bytes { value };
|
||||
// }
|
||||
|
||||
#[pyclass(name = "bytearray_iterator")]
|
||||
#[pyclass(module = false, name = "bytearray_iterator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyByteArrayIterator {
|
||||
position: AtomicCell<usize>,
|
||||
|
||||
@@ -32,7 +32,7 @@ use rustpython_common::hash::PyHash;
|
||||
/// - a text string encoded using the specified encoding\n \
|
||||
/// - any object implementing the buffer API.\n \
|
||||
/// - an integer";
|
||||
#[pyclass(name = "bytes")]
|
||||
#[pyclass(module = false, name = "bytes")]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PyBytes {
|
||||
inner: PyBytesInner,
|
||||
@@ -488,7 +488,7 @@ impl PyBytes {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "bytes_iterator")]
|
||||
#[pyclass(module = false, name = "bytes_iterator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyBytesIterator {
|
||||
position: AtomicCell<usize>,
|
||||
|
||||
@@ -26,7 +26,7 @@ use crate::vm::VirtualMachine;
|
||||
///
|
||||
/// Class methods are different than C++ or Java static methods.
|
||||
/// If you want those, see the staticmethod builtin.
|
||||
#[pyclass(name = "classmethod")]
|
||||
#[pyclass(module = false, name = "classmethod")]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PyClassMethod {
|
||||
callable: PyObjectRef,
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::vm::VirtualMachine;
|
||||
|
||||
pub type PyCodeRef = PyRef<PyCode>;
|
||||
|
||||
#[pyclass(name = "code")]
|
||||
#[pyclass(module = false, name = "code")]
|
||||
pub struct PyCode {
|
||||
pub code: bytecode::CodeObject,
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ use rustpython_common::{float_ops, hash};
|
||||
/// Create a complex number from a real part and an optional imaginary part.
|
||||
///
|
||||
/// This is equivalent to (real + imag*1j) where imag defaults to 0.
|
||||
#[pyclass(name = "complex")]
|
||||
#[pyclass(module = false, name = "complex")]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct PyComplex {
|
||||
value: Complex64,
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::vm::VirtualMachine;
|
||||
|
||||
pub type PyCoroutineRef = PyRef<PyCoroutine>;
|
||||
|
||||
#[pyclass(name = "coroutine")]
|
||||
#[pyclass(module = false, name = "coroutine")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyCoroutine {
|
||||
inner: Coro,
|
||||
@@ -95,7 +95,7 @@ impl PyCoroutine {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "coroutine_wrapper")]
|
||||
#[pyclass(module = false, name = "coroutine_wrapper")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyCoroutineWrapper {
|
||||
coro: PyCoroutineRef,
|
||||
|
||||
@@ -18,7 +18,7 @@ use std::mem::size_of;
|
||||
|
||||
pub type DictContentType = dictdatatype::Dict;
|
||||
|
||||
#[pyclass(name = "dict")]
|
||||
#[pyclass(module = false, name = "dict")]
|
||||
#[derive(Default)]
|
||||
pub struct PyDict {
|
||||
entries: DictContentType,
|
||||
@@ -553,7 +553,7 @@ impl Iterator for DictIter {
|
||||
|
||||
macro_rules! dict_iterator {
|
||||
( $name: ident, $iter_name: ident, $class: ident, $iter_class: ident, $class_name: literal, $iter_class_name: literal, $result_fn: expr) => {
|
||||
#[pyclass(name = $class_name)]
|
||||
#[pyclass(module=false,name = $class_name)]
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct $name {
|
||||
pub dict: PyDictRef,
|
||||
@@ -598,7 +598,7 @@ macro_rules! dict_iterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = $iter_class_name)]
|
||||
#[pyclass(module=false,name = $iter_class_name)]
|
||||
#[derive(Debug)]
|
||||
pub(crate) struct $iter_name {
|
||||
pub dict: PyDictRef,
|
||||
|
||||
@@ -6,7 +6,7 @@ pub(crate) fn init(context: &PyContext) {
|
||||
PyEllipsis::extend_class(context, &context.ellipsis_type());
|
||||
}
|
||||
|
||||
#[pyclass(name = "EllipsisType")]
|
||||
#[pyclass(module = false, name = "EllipsisType")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyEllipsis;
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@ use crate::function::OptionalArg;
|
||||
use crate::pyobject::{BorrowValue, PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "enumerate")]
|
||||
#[pyclass(module = false, name = "enumerate")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyEnumerate {
|
||||
counter: PyRwLock<BigInt>,
|
||||
|
||||
@@ -10,7 +10,7 @@ pub type PyFilterRef = PyRef<PyFilter>;
|
||||
///
|
||||
/// Return an iterator yielding those items of iterable for which function(item)
|
||||
/// is true. If function is None, return the items that are true.
|
||||
#[pyclass(name = "filter")]
|
||||
#[pyclass(module = false, name = "filter")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyFilter {
|
||||
predicate: PyObjectRef,
|
||||
|
||||
@@ -19,7 +19,7 @@ use crate::vm::VirtualMachine;
|
||||
use rustpython_common::{float_ops, hash};
|
||||
|
||||
/// Convert a string or number to a floating point number, if possible.
|
||||
#[pyclass(name = "float")]
|
||||
#[pyclass(module = false, name = "float")]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub struct PyFloat {
|
||||
value: f64,
|
||||
|
||||
@@ -20,7 +20,7 @@ use itertools::Itertools;
|
||||
|
||||
pub type PyFunctionRef = PyRef<PyFunction>;
|
||||
|
||||
#[pyclass(name = "function")]
|
||||
#[pyclass(module = false, name = "function")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyFunction {
|
||||
code: PyCodeRef,
|
||||
@@ -287,7 +287,7 @@ impl PyFunction {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "method")]
|
||||
#[pyclass(module = false, name = "method")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyBoundMethod {
|
||||
// TODO: these shouldn't be public
|
||||
|
||||
@@ -12,7 +12,7 @@ use crate::vm::VirtualMachine;
|
||||
|
||||
pub type PyGeneratorRef = PyRef<PyGenerator>;
|
||||
|
||||
#[pyclass(name = "generator")]
|
||||
#[pyclass(module = false, name = "generator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyGenerator {
|
||||
inner: Coro,
|
||||
|
||||
@@ -144,7 +144,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "getset_descriptor")]
|
||||
#[pyclass(module = false, name = "getset_descriptor")]
|
||||
pub struct PyGetSet {
|
||||
name: String,
|
||||
getter: Option<PyGetterFunc>,
|
||||
|
||||
@@ -40,7 +40,7 @@ use rustpython_common::hash;
|
||||
/// Base 0 means to interpret the base from the string as an integer literal.
|
||||
/// >>> int('0b100', base=0)
|
||||
/// 4
|
||||
#[pyclass(name = "int")]
|
||||
#[pyclass(module = false, name = "int")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyInt {
|
||||
value: BigInt,
|
||||
|
||||
@@ -149,7 +149,7 @@ pub fn length_hint(vm: &VirtualMachine, iter: PyObjectRef) -> PyResult<Option<us
|
||||
Ok(Some(hint))
|
||||
}
|
||||
|
||||
#[pyclass(name = "iter")]
|
||||
#[pyclass(module = false, name = "iter")]
|
||||
#[derive(Debug)]
|
||||
pub struct PySequenceIterator {
|
||||
pub position: AtomicCell<isize>,
|
||||
@@ -222,7 +222,7 @@ pub fn seq_iter_method(obj: PyObjectRef) -> PySequenceIterator {
|
||||
PySequenceIterator::new_forward(obj)
|
||||
}
|
||||
|
||||
#[pyclass(name = "callable_iterator")]
|
||||
#[pyclass(module = false, name = "callable_iterator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyCallableIterator {
|
||||
callable: PyCallable,
|
||||
|
||||
@@ -27,7 +27,7 @@ use crate::vm::{ReprGuard, VirtualMachine};
|
||||
///
|
||||
/// If no argument is given, the constructor creates a new empty list.
|
||||
/// The argument must be an iterable if specified.
|
||||
#[pyclass(name = "list")]
|
||||
#[pyclass(module = false, name = "list")]
|
||||
#[derive(Default)]
|
||||
pub struct PyList {
|
||||
elements: PyRwLock<Vec<PyObjectRef>>,
|
||||
@@ -825,7 +825,7 @@ fn do_sort(
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[pyclass(name = "list_iterator")]
|
||||
#[pyclass(module = false, name = "list_iterator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyListIterator {
|
||||
pub position: AtomicCell<usize>,
|
||||
@@ -864,7 +864,7 @@ impl PyListIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "list_reverseiterator")]
|
||||
#[pyclass(module = false, name = "list_reverseiterator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyListReverseIterator {
|
||||
pub position: AtomicCell<isize>,
|
||||
|
||||
@@ -8,7 +8,7 @@ use crate::vm::VirtualMachine;
|
||||
///
|
||||
/// Make an iterator that computes the function using arguments from
|
||||
/// each of the iterables. Stops when the shortest iterable is exhausted.
|
||||
#[pyclass(name = "map")]
|
||||
#[pyclass(module = false, name = "map")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyMap {
|
||||
mapper: PyObjectRef,
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::pyobject::{
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "mappingproxy")]
|
||||
#[pyclass(module = false, name = "mappingproxy")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyMappingProxy {
|
||||
mapping: MappingProxyInner,
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::pyobject::{
|
||||
use crate::stdlib::array::PyArray;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "memoryview")]
|
||||
#[pyclass(module = false, name = "memoryview")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyMemoryView {
|
||||
obj_ref: PyObjectRef,
|
||||
|
||||
@@ -7,7 +7,7 @@ use crate::pyobject::{
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "module")]
|
||||
#[pyclass(module = false, name = "module")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyModule {}
|
||||
pub type PyModuleRef = PyRef<PyModule>;
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::vm::VirtualMachine;
|
||||
/// A simple attribute-based namespace.
|
||||
///
|
||||
/// SimpleNamespace(**kwargs)
|
||||
#[pyclass(name = "SimpleNamespace")]
|
||||
#[pyclass(module = false, name = "SimpleNamespace")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyNamespace;
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::pyobject::{
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "NoneType")]
|
||||
#[pyclass(module = false, name = "NoneType")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyNone;
|
||||
pub type PyNoneRef = PyRef<PyNone>;
|
||||
|
||||
@@ -13,7 +13,7 @@ use crate::pyobject::{
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
/// The most base type
|
||||
#[pyclass(name = "object")]
|
||||
#[pyclass(module = false, name = "object")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyBaseObject;
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ use crate::vm::VirtualMachine;
|
||||
/// @x.deleter
|
||||
/// def x(self):
|
||||
/// del self._x
|
||||
#[pyclass(name = "property")]
|
||||
#[pyclass(module = false, name = "property")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyProperty {
|
||||
getter: Option<PyObjectRef>,
|
||||
|
||||
@@ -25,7 +25,7 @@ use rustpython_common::hash::PyHash;
|
||||
/// start defaults to 0, and stop is omitted! range(4) produces 0, 1, 2, 3.
|
||||
/// These are exactly the valid indices for a list of 4 elements.
|
||||
/// When step is given, it specifies the increment (or decrement).
|
||||
#[pyclass(name = "range")]
|
||||
#[pyclass(module = false, name = "range")]
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct PyRange {
|
||||
pub start: PyIntRef,
|
||||
@@ -400,7 +400,7 @@ impl PyRange {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "range_iterator")]
|
||||
#[pyclass(module = false, name = "range_iterator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyRangeIterator {
|
||||
position: AtomicCell<usize>,
|
||||
|
||||
@@ -21,7 +21,7 @@ pub type SetContentType = dictdatatype::Dict<()>;
|
||||
/// set(iterable) -> new set object
|
||||
///
|
||||
/// Build an unordered collection of unique elements.
|
||||
#[pyclass(name = "set")]
|
||||
#[pyclass(module = false, name = "set")]
|
||||
#[derive(Default)]
|
||||
pub struct PySet {
|
||||
inner: PySetInner,
|
||||
@@ -32,7 +32,7 @@ pub type PySetRef = PyRef<PySet>;
|
||||
/// frozenset(iterable) -> frozenset object
|
||||
///
|
||||
/// Build an immutable unordered collection of unique elements.
|
||||
#[pyclass(name = "frozenset")]
|
||||
#[pyclass(module = false, name = "frozenset")]
|
||||
#[derive(Default)]
|
||||
pub struct PyFrozenSet {
|
||||
inner: PySetInner,
|
||||
@@ -824,7 +824,7 @@ struct SetSizeInfo {
|
||||
position: usize,
|
||||
}
|
||||
|
||||
#[pyclass(name = "set_iterator")]
|
||||
#[pyclass(module = false, name = "set_iterator")]
|
||||
pub(crate) struct PySetIterator {
|
||||
dict: PyRc<SetContentType>,
|
||||
size_info: crossbeam_utils::atomic::AtomicCell<SetSizeInfo>,
|
||||
|
||||
@@ -9,7 +9,7 @@ use crate::vm::VirtualMachine;
|
||||
use num_bigint::{BigInt, ToBigInt};
|
||||
use num_traits::{One, Signed, Zero};
|
||||
|
||||
#[pyclass(name = "slice")]
|
||||
#[pyclass(module = false, name = "slice")]
|
||||
#[derive(Debug)]
|
||||
pub struct PySlice {
|
||||
pub start: Option<PyObjectRef>,
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyVa
|
||||
use crate::slots::SlotDescriptor;
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "staticmethod")]
|
||||
#[pyclass(module = false, name = "staticmethod")]
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct PyStaticMethod {
|
||||
pub callable: PyObjectRef,
|
||||
|
||||
@@ -41,7 +41,7 @@ use rustpython_common::hash;
|
||||
/// or repr(object).
|
||||
/// encoding defaults to sys.getdefaultencoding().
|
||||
/// errors defaults to 'strict'."
|
||||
#[pyclass(name = "str")]
|
||||
#[pyclass(module = false, name = "str")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyString {
|
||||
value: String,
|
||||
@@ -102,7 +102,7 @@ impl TryIntoRef<PyString> for &str {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "str_iterator")]
|
||||
#[pyclass(module = false, name = "str_iterator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyStringIterator {
|
||||
pub string: PyStringRef,
|
||||
@@ -135,7 +135,7 @@ impl PyStringIterator {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "str_reverseiterator")]
|
||||
#[pyclass(module = false, name = "str_reverseiterator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyStringReverseIterator {
|
||||
pub position: AtomicCell<isize>,
|
||||
|
||||
@@ -21,7 +21,7 @@ use itertools::Itertools;
|
||||
|
||||
pub type PySuperRef = PyRef<PySuper>;
|
||||
|
||||
#[pyclass(name = "super")]
|
||||
#[pyclass(module = false, name = "super")]
|
||||
#[derive(Debug)]
|
||||
pub struct PySuper {
|
||||
typ: PyClassRef,
|
||||
|
||||
@@ -3,7 +3,7 @@ use crate::obj::objtype::PyClassRef;
|
||||
use crate::pyobject::{PyClassImpl, PyContext, PyRef, PyValue};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "traceback")]
|
||||
#[pyclass(module = false, name = "traceback")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyTraceback {
|
||||
pub next: Option<PyTracebackRef>, // TODO: Make mutable
|
||||
|
||||
@@ -18,7 +18,7 @@ use rustpython_common::hash::PyHash;
|
||||
/// tuple(iterable) -> tuple initialized from iterable's items
|
||||
///
|
||||
/// If the argument is a tuple, the return value is the same object.
|
||||
#[pyclass(name = "tuple")]
|
||||
#[pyclass(module = false, name = "tuple")]
|
||||
pub struct PyTuple {
|
||||
elements: Vec<PyObjectRef>,
|
||||
}
|
||||
@@ -255,7 +255,7 @@ impl PyTuple {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "tuple_iterator")]
|
||||
#[pyclass(module = false, name = "tuple_iterator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyTupleIterator {
|
||||
position: AtomicCell<usize>,
|
||||
|
||||
@@ -24,7 +24,7 @@ use std::ops::Deref;
|
||||
/// type(object_or_name, bases, dict)
|
||||
/// type(object) -> the object's type
|
||||
/// type(name, bases, dict) -> a new type
|
||||
#[pyclass(name = "type")]
|
||||
#[pyclass(module = false, name = "type")]
|
||||
pub struct PyClass {
|
||||
pub name: String,
|
||||
pub base: Option<PyClassRef>,
|
||||
|
||||
@@ -4,7 +4,7 @@ use crate::function::OptionalArg;
|
||||
use crate::pyobject::{PyClassImpl, PyContext, PyObjectRef, PyRef, PyResult, PyValue};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "weakproxy")]
|
||||
#[pyclass(module = false, name = "weakproxy")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyWeakProxy {
|
||||
weak: PyWeak,
|
||||
|
||||
@@ -11,7 +11,7 @@ use rustpython_common::rc::{PyRc, PyWeak as Weak};
|
||||
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
#[pyclass(name = "ref")]
|
||||
#[pyclass(module = false, name = "ref")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyWeak {
|
||||
referent: Weak<PyObject<dyn PyObjectPayload>>,
|
||||
|
||||
@@ -6,7 +6,7 @@ use crate::vm::VirtualMachine;
|
||||
|
||||
pub type PyZipRef = PyRef<PyZip>;
|
||||
|
||||
#[pyclass(name = "zip")]
|
||||
#[pyclass(module = false, name = "zip")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyZip {
|
||||
iterators: Vec<PyObjectRef>,
|
||||
|
||||
+4
-4
@@ -464,8 +464,8 @@ impl PyContext {
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
pub fn new_class(&self, name: &str, base: PyClassRef, flags: PyTpFlags) -> PyClassRef {
|
||||
create_type_with_flags(name, &self.type_type(), &base, flags)
|
||||
pub fn new_class(&self, name: &str, base: &PyClassRef, flags: PyTpFlags) -> PyClassRef {
|
||||
create_type_with_flags(name, &self.type_type(), base, flags)
|
||||
}
|
||||
|
||||
pub fn new_namespace(&self) -> PyObjectRef {
|
||||
@@ -1481,10 +1481,10 @@ pub trait PyClassImpl: PyClassDef {
|
||||
}
|
||||
|
||||
fn make_class(ctx: &PyContext) -> PyClassRef {
|
||||
Self::make_class_with_base(ctx, Self::NAME, ctx.object())
|
||||
Self::make_class_with_base(ctx, Self::NAME, &ctx.object())
|
||||
}
|
||||
|
||||
fn make_class_with_base(ctx: &PyContext, name: &str, base: PyClassRef) -> PyClassRef {
|
||||
fn make_class_with_base(ctx: &PyContext, name: &str, base: &PyClassRef) -> PyClassRef {
|
||||
let py_class = ctx.new_class(name, base, Self::TP_FLAGS);
|
||||
Self::extend_class(ctx, &py_class);
|
||||
py_class
|
||||
|
||||
@@ -246,7 +246,7 @@ def_array_enum!(
|
||||
(Double, f64, 'd'),
|
||||
);
|
||||
|
||||
#[pyclass(name = "array")]
|
||||
#[pyclass(module = "array", name = "array")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyArray {
|
||||
array: PyRwLock<ArrayContentType>,
|
||||
@@ -530,7 +530,7 @@ impl PyArray {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "array_iterator")]
|
||||
#[pyclass(module = "array", name = "array_iterator")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyArrayIter {
|
||||
position: AtomicCell<usize>,
|
||||
|
||||
+64
-64
@@ -644,72 +644,72 @@ pub(crate) fn parse(vm: &VirtualMachine, source: &str, mode: Mode) -> PyResult {
|
||||
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
let ast_base = py_class!(ctx, "AST", ctx.object(), PyTpFlags::HAS_DICT, {});
|
||||
let ast_base = py_class!(ctx, "AST", &ctx.object(), PyTpFlags::HAS_DICT, {});
|
||||
py_module!(vm, MODULE_NAME, {
|
||||
// TODO: There's got to be a better way!
|
||||
"alias" => py_class!(ctx, "alias", ast_base.clone(), {}),
|
||||
"arg" => py_class!(ctx, "arg", ast_base.clone(), {}),
|
||||
"arguments" => py_class!(ctx, "arguments", ast_base.clone(), {}),
|
||||
"AnnAssign" => py_class!(ctx, "AnnAssign", ast_base.clone(), {}),
|
||||
"Assign" => py_class!(ctx, "Assign", ast_base.clone(), {}),
|
||||
"AugAssign" => py_class!(ctx, "AugAssign", ast_base.clone(), {}),
|
||||
"AsyncFor" => py_class!(ctx, "AsyncFor", ast_base.clone(), {}),
|
||||
"AsyncFunctionDef" => py_class!(ctx, "AsyncFunctionDef", ast_base.clone(), {}),
|
||||
"AsyncWith" => py_class!(ctx, "AsyncWith", ast_base.clone(), {}),
|
||||
"Assert" => py_class!(ctx, "Assert", ast_base.clone(), {}),
|
||||
"Attribute" => py_class!(ctx, "Attribute", ast_base.clone(), {}),
|
||||
"Await" => py_class!(ctx, "Await", ast_base.clone(), {}),
|
||||
"BinOp" => py_class!(ctx, "BinOp", ast_base.clone(), {}),
|
||||
"BoolOp" => py_class!(ctx, "BoolOp", ast_base.clone(), {}),
|
||||
"Break" => py_class!(ctx, "Break", ast_base.clone(), {}),
|
||||
"Bytes" => py_class!(ctx, "Bytes", ast_base.clone(), {}),
|
||||
"Call" => py_class!(ctx, "Call", ast_base.clone(), {}),
|
||||
"ClassDef" => py_class!(ctx, "ClassDef", ast_base.clone(), {}),
|
||||
"Compare" => py_class!(ctx, "Compare", ast_base.clone(), {}),
|
||||
"comprehension" => py_class!(ctx, "comprehension", ast_base.clone(), {}),
|
||||
"Continue" => py_class!(ctx, "Continue", ast_base.clone(), {}),
|
||||
"Delete" => py_class!(ctx, "Delete", ast_base.clone(), {}),
|
||||
"Dict" => py_class!(ctx, "Dict", ast_base.clone(), {}),
|
||||
"DictComp" => py_class!(ctx, "DictComp", ast_base.clone(), {}),
|
||||
"Ellipsis" => py_class!(ctx, "Ellipsis", ast_base.clone(), {}),
|
||||
"Expr" => py_class!(ctx, "Expr", ast_base.clone(), {}),
|
||||
"ExceptHandler" => py_class!(ctx, "ExceptHandler", ast_base.clone(), {}),
|
||||
"For" => py_class!(ctx, "For", ast_base.clone(), {}),
|
||||
"FormattedValue" => py_class!(ctx, "FormattedValue", ast_base.clone(), {}),
|
||||
"FunctionDef" => py_class!(ctx, "FunctionDef", ast_base.clone(), {}),
|
||||
"GeneratorExp" => py_class!(ctx, "GeneratorExp", ast_base.clone(), {}),
|
||||
"Global" => py_class!(ctx, "Global", ast_base.clone(), {}),
|
||||
"If" => py_class!(ctx, "If", ast_base.clone(), {}),
|
||||
"IfExp" => py_class!(ctx, "IfExp", ast_base.clone(), {}),
|
||||
"Import" => py_class!(ctx, "Import", ast_base.clone(), {}),
|
||||
"ImportFrom" => py_class!(ctx, "ImportFrom", ast_base.clone(), {}),
|
||||
"JoinedStr" => py_class!(ctx, "JoinedStr", ast_base.clone(), {}),
|
||||
"keyword" => py_class!(ctx, "keyword", ast_base.clone(), {}),
|
||||
"Lambda" => py_class!(ctx, "Lambda", ast_base.clone(), {}),
|
||||
"List" => py_class!(ctx, "List", ast_base.clone(), {}),
|
||||
"ListComp" => py_class!(ctx, "ListComp", ast_base.clone(), {}),
|
||||
"Module" => py_class!(ctx, "Module", ast_base.clone(), {}),
|
||||
"Name" => py_class!(ctx, "Name", ast_base.clone(), {}),
|
||||
"NameConstant" => py_class!(ctx, "NameConstant", ast_base.clone(), {}),
|
||||
"Nonlocal" => py_class!(ctx, "Nonlocal", ast_base.clone(), {}),
|
||||
"Num" => py_class!(ctx, "Num", ast_base.clone(), {}),
|
||||
"Pass" => py_class!(ctx, "Pass", ast_base.clone(), {}),
|
||||
"Raise" => py_class!(ctx, "Raise", ast_base.clone(), {}),
|
||||
"Return" => py_class!(ctx, "Return", ast_base.clone(), {}),
|
||||
"Set" => py_class!(ctx, "Set", ast_base.clone(), {}),
|
||||
"SetComp" => py_class!(ctx, "SetComp", ast_base.clone(), {}),
|
||||
"Starred" => py_class!(ctx, "Starred", ast_base.clone(), {}),
|
||||
"Starred" => py_class!(ctx, "Starred", ast_base.clone(), {}),
|
||||
"Str" => py_class!(ctx, "Str", ast_base.clone(), {}),
|
||||
"Subscript" => py_class!(ctx, "Subscript", ast_base.clone(), {}),
|
||||
"Try" => py_class!(ctx, "Try", ast_base.clone(), {}),
|
||||
"Tuple" => py_class!(ctx, "Tuple", ast_base.clone(), {}),
|
||||
"UnaryOp" => py_class!(ctx, "UnaryOp", ast_base.clone(), {}),
|
||||
"While" => py_class!(ctx, "While", ast_base.clone(), {}),
|
||||
"With" => py_class!(ctx, "With", ast_base.clone(), {}),
|
||||
"withitem" => py_class!(ctx, "withitem", ast_base.clone(), {}),
|
||||
"Yield" => py_class!(ctx, "Yield", ast_base.clone(), {}),
|
||||
"YieldFrom" => py_class!(ctx, "YieldFrom", ast_base.clone(), {}),
|
||||
"alias" => py_class!(ctx, "alias", &ast_base, {}),
|
||||
"arg" => py_class!(ctx, "arg", &ast_base, {}),
|
||||
"arguments" => py_class!(ctx, "arguments", &ast_base, {}),
|
||||
"AnnAssign" => py_class!(ctx, "AnnAssign", &ast_base, {}),
|
||||
"Assign" => py_class!(ctx, "Assign", &ast_base, {}),
|
||||
"AugAssign" => py_class!(ctx, "AugAssign", &ast_base, {}),
|
||||
"AsyncFor" => py_class!(ctx, "AsyncFor", &ast_base, {}),
|
||||
"AsyncFunctionDef" => py_class!(ctx, "AsyncFunctionDef", &ast_base, {}),
|
||||
"AsyncWith" => py_class!(ctx, "AsyncWith", &ast_base, {}),
|
||||
"Assert" => py_class!(ctx, "Assert", &ast_base, {}),
|
||||
"Attribute" => py_class!(ctx, "Attribute", &ast_base, {}),
|
||||
"Await" => py_class!(ctx, "Await", &ast_base, {}),
|
||||
"BinOp" => py_class!(ctx, "BinOp", &ast_base, {}),
|
||||
"BoolOp" => py_class!(ctx, "BoolOp", &ast_base, {}),
|
||||
"Break" => py_class!(ctx, "Break", &ast_base, {}),
|
||||
"Bytes" => py_class!(ctx, "Bytes", &ast_base, {}),
|
||||
"Call" => py_class!(ctx, "Call", &ast_base, {}),
|
||||
"ClassDef" => py_class!(ctx, "ClassDef", &ast_base, {}),
|
||||
"Compare" => py_class!(ctx, "Compare", &ast_base, {}),
|
||||
"comprehension" => py_class!(ctx, "comprehension", &ast_base, {}),
|
||||
"Continue" => py_class!(ctx, "Continue", &ast_base, {}),
|
||||
"Delete" => py_class!(ctx, "Delete", &ast_base, {}),
|
||||
"Dict" => py_class!(ctx, "Dict", &ast_base, {}),
|
||||
"DictComp" => py_class!(ctx, "DictComp", &ast_base, {}),
|
||||
"Ellipsis" => py_class!(ctx, "Ellipsis", &ast_base, {}),
|
||||
"Expr" => py_class!(ctx, "Expr", &ast_base, {}),
|
||||
"ExceptHandler" => py_class!(ctx, "ExceptHandler", &ast_base, {}),
|
||||
"For" => py_class!(ctx, "For", &ast_base, {}),
|
||||
"FormattedValue" => py_class!(ctx, "FormattedValue", &ast_base, {}),
|
||||
"FunctionDef" => py_class!(ctx, "FunctionDef", &ast_base, {}),
|
||||
"GeneratorExp" => py_class!(ctx, "GeneratorExp", &ast_base, {}),
|
||||
"Global" => py_class!(ctx, "Global", &ast_base, {}),
|
||||
"If" => py_class!(ctx, "If", &ast_base, {}),
|
||||
"IfExp" => py_class!(ctx, "IfExp", &ast_base, {}),
|
||||
"Import" => py_class!(ctx, "Import", &ast_base, {}),
|
||||
"ImportFrom" => py_class!(ctx, "ImportFrom", &ast_base, {}),
|
||||
"JoinedStr" => py_class!(ctx, "JoinedStr", &ast_base, {}),
|
||||
"keyword" => py_class!(ctx, "keyword", &ast_base, {}),
|
||||
"Lambda" => py_class!(ctx, "Lambda", &ast_base, {}),
|
||||
"List" => py_class!(ctx, "List", &ast_base, {}),
|
||||
"ListComp" => py_class!(ctx, "ListComp", &ast_base, {}),
|
||||
"Module" => py_class!(ctx, "Module", &ast_base, {}),
|
||||
"Name" => py_class!(ctx, "Name", &ast_base, {}),
|
||||
"NameConstant" => py_class!(ctx, "NameConstant", &ast_base, {}),
|
||||
"Nonlocal" => py_class!(ctx, "Nonlocal", &ast_base, {}),
|
||||
"Num" => py_class!(ctx, "Num", &ast_base, {}),
|
||||
"Pass" => py_class!(ctx, "Pass", &ast_base, {}),
|
||||
"Raise" => py_class!(ctx, "Raise", &ast_base, {}),
|
||||
"Return" => py_class!(ctx, "Return", &ast_base, {}),
|
||||
"Set" => py_class!(ctx, "Set", &ast_base, {}),
|
||||
"SetComp" => py_class!(ctx, "SetComp", &ast_base, {}),
|
||||
"Starred" => py_class!(ctx, "Starred", &ast_base, {}),
|
||||
"Starred" => py_class!(ctx, "Starred", &ast_base, {}),
|
||||
"Str" => py_class!(ctx, "Str", &ast_base, {}),
|
||||
"Subscript" => py_class!(ctx, "Subscript", &ast_base, {}),
|
||||
"Try" => py_class!(ctx, "Try", &ast_base, {}),
|
||||
"Tuple" => py_class!(ctx, "Tuple", &ast_base, {}),
|
||||
"UnaryOp" => py_class!(ctx, "UnaryOp", &ast_base, {}),
|
||||
"While" => py_class!(ctx, "While", &ast_base, {}),
|
||||
"With" => py_class!(ctx, "With", &ast_base, {}),
|
||||
"withitem" => py_class!(ctx, "withitem", &ast_base, {}),
|
||||
"Yield" => py_class!(ctx, "Yield", &ast_base, {}),
|
||||
"YieldFrom" => py_class!(ctx, "YieldFrom", &ast_base, {}),
|
||||
"AST" => ast_base,
|
||||
"PyCF_ONLY_AST" => ctx.new_int(PY_COMPILE_FLAG_AST_ONLY),
|
||||
})
|
||||
|
||||
@@ -17,6 +17,7 @@ mod _collections {
|
||||
|
||||
use crossbeam_utils::atomic::AtomicCell;
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "deque")]
|
||||
#[derive(Debug)]
|
||||
struct PyDeque {
|
||||
@@ -402,6 +403,7 @@ mod _collections {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "_deque_iterator")]
|
||||
#[derive(Debug)]
|
||||
struct PyDequeIterator {
|
||||
|
||||
@@ -124,7 +124,7 @@ impl ReadState {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "Reader")]
|
||||
#[pyclass(module = "csv", name = "Reader")]
|
||||
struct Reader {
|
||||
state: PyRwLock<ReadState>,
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ use sha1::Sha1;
|
||||
use sha2::{Sha224, Sha256, Sha384, Sha512};
|
||||
use sha3::{Sha3_224, Sha3_256, Sha3_384, Sha3_512}; // TODO: , Shake128, Shake256};
|
||||
|
||||
#[pyclass(name = "hasher")]
|
||||
#[pyclass(module = "hashlib", name = "hasher")]
|
||||
struct PyHasher {
|
||||
name: String,
|
||||
buffer: PyRwLock<HashWrapper>,
|
||||
|
||||
+11
-11
@@ -647,7 +647,7 @@ mod fileio {
|
||||
flag as u32
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[pyclass(module = "io", name)]
|
||||
#[derive(Debug)]
|
||||
struct FileIO {
|
||||
fd: AtomicCell<i64>,
|
||||
@@ -877,7 +877,7 @@ mod fileio {
|
||||
}
|
||||
|
||||
pub fn make_fileio(ctx: &crate::pyobject::PyContext, raw_io_base: PyClassRef) -> PyClassRef {
|
||||
FileIO::make_class_with_base(ctx, FileIO::NAME, raw_io_base)
|
||||
FileIO::make_class_with_base(ctx, FileIO::NAME, &raw_io_base)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1268,7 +1268,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
|
||||
// IOBase the abstract base class of the IO Module
|
||||
let io_base = py_class!(ctx, "_IOBase", ctx.object(), {
|
||||
let io_base = py_class!(ctx, "_IOBase", &ctx.object(), {
|
||||
"__enter__" => ctx.new_method(io_base_cm_enter),
|
||||
"__exit__" => ctx.new_method(io_base_cm_exit),
|
||||
"seekable" => ctx.new_method(io_base_seekable),
|
||||
@@ -1289,17 +1289,17 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
});
|
||||
|
||||
// IOBase Subclasses
|
||||
let raw_io_base = py_class!(ctx, "_RawIOBase", io_base.clone(), {
|
||||
let raw_io_base = py_class!(ctx, "_RawIOBase", &io_base, {
|
||||
"read" => ctx.new_method(raw_io_base_read),
|
||||
});
|
||||
|
||||
let buffered_io_base = py_class!(ctx, "_BufferedIOBase", io_base.clone(), {});
|
||||
let buffered_io_base = py_class!(ctx, "_BufferedIOBase", &io_base, {});
|
||||
|
||||
//TextIO Base has no public constructor
|
||||
let text_io_base = py_class!(ctx, "_TextIOBase", io_base.clone(), {});
|
||||
let text_io_base = py_class!(ctx, "_TextIOBase", &io_base, {});
|
||||
|
||||
// BufferedIOBase Subclasses
|
||||
let buffered_reader = py_class!(ctx, "BufferedReader", buffered_io_base.clone(), {
|
||||
let buffered_reader = py_class!(ctx, "BufferedReader", &buffered_io_base, {
|
||||
//workaround till the buffered classes can be fixed up to be more
|
||||
//consistent with the python model
|
||||
//For more info see: https://github.com/RustPython/RustPython/issues/547
|
||||
@@ -1314,7 +1314,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
"mode" => ctx.new_readonly_getset("mode", buffered_io_base_mode),
|
||||
});
|
||||
|
||||
let buffered_writer = py_class!(ctx, "BufferedWriter", buffered_io_base.clone(), {
|
||||
let buffered_writer = py_class!(ctx, "BufferedWriter", &buffered_io_base, {
|
||||
//workaround till the buffered classes can be fixed up to be more
|
||||
//consistent with the python model
|
||||
//For more info see: https://github.com/RustPython/RustPython/issues/547
|
||||
@@ -1330,7 +1330,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
});
|
||||
|
||||
//TextIOBase Subclass
|
||||
let text_io_wrapper = py_class!(ctx, "TextIOWrapper", text_io_base.clone(), {
|
||||
let text_io_wrapper = py_class!(ctx, "TextIOWrapper", &text_io_base, {
|
||||
"__init__" => ctx.new_method(text_io_wrapper_init),
|
||||
"seekable" => ctx.new_method(text_io_wrapper_seekable),
|
||||
"seek" => ctx.new_method(text_io_wrapper_seek),
|
||||
@@ -1344,7 +1344,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
});
|
||||
|
||||
//StringIO: in-memory text
|
||||
let string_io = py_class!(ctx, "StringIO", text_io_base.clone(), {
|
||||
let string_io = py_class!(ctx, "StringIO", &text_io_base, {
|
||||
"__module__" => ctx.new_str("_io"),
|
||||
(slot new) => string_io_new,
|
||||
"seek" => ctx.new_method(PyStringIORef::seek),
|
||||
@@ -1360,7 +1360,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
});
|
||||
|
||||
//BytesIO: in-memory bytes
|
||||
let bytes_io = py_class!(ctx, "BytesIO", buffered_io_base.clone(), {
|
||||
let bytes_io = py_class!(ctx, "BytesIO", &buffered_io_base, {
|
||||
(slot new) => bytes_io_new,
|
||||
"read" => ctx.new_method(PyBytesIORef::read),
|
||||
"read1" => ctx.new_method(PyBytesIORef::read),
|
||||
|
||||
@@ -22,6 +22,7 @@ mod decl {
|
||||
};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "chain")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsChain {
|
||||
@@ -107,6 +108,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "compress")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsCompress {
|
||||
@@ -158,6 +160,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "count")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsCount {
|
||||
@@ -210,6 +213,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "cycle")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsCycle {
|
||||
@@ -271,6 +275,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "repeat")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsRepeat {
|
||||
@@ -328,6 +333,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "starmap")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsStarmap {
|
||||
@@ -369,6 +375,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "takewhile")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsTakewhile {
|
||||
@@ -428,6 +435,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "dropwhile")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsDropwhile {
|
||||
@@ -512,6 +520,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "groupby")]
|
||||
struct PyItertoolsGroupBy {
|
||||
iterable: PyObjectRef,
|
||||
@@ -620,6 +629,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "_grouper")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsGrouper {
|
||||
@@ -671,6 +681,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "islice")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsIslice {
|
||||
@@ -797,6 +808,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "filterfalse")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsFilterFalse {
|
||||
@@ -853,6 +865,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "accumulate")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsAccumulate {
|
||||
@@ -937,6 +950,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "tee")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsTee {
|
||||
@@ -1015,6 +1029,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "product")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsProduct {
|
||||
@@ -1132,6 +1147,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "combinations")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsCombinations {
|
||||
@@ -1231,6 +1247,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "combinations_with_replacement")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsCombinationsWithReplacement {
|
||||
@@ -1325,6 +1342,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "permutations")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsPermutations {
|
||||
@@ -1455,6 +1473,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "zip_longest")]
|
||||
#[derive(Debug)]
|
||||
struct PyItertoolsZipLongest {
|
||||
|
||||
+8
-3
@@ -293,8 +293,8 @@ mod _os {
|
||||
rust_file(fileno);
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
#[cfg(any(unix, windows, target_os = "wasi"))]
|
||||
#[pyfunction]
|
||||
pub(crate) fn open(
|
||||
name: PyPathLike,
|
||||
flags: OpenFlags,
|
||||
@@ -350,8 +350,8 @@ mod _os {
|
||||
Ok(raw_file_number(handle))
|
||||
}
|
||||
|
||||
#[pyfunction]
|
||||
#[cfg(not(any(unix, windows, target_os = "wasi")))]
|
||||
#[pyfunction]
|
||||
pub(crate) fn open(vm: &VirtualMachine, args: PyFuncArgs) -> PyResult {
|
||||
Err(vm.new_os_error("os.open not implemented on this platform".to_owned()))
|
||||
}
|
||||
@@ -474,7 +474,8 @@ mod _os {
|
||||
mode.process_path(path, vm)
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[pyattr]
|
||||
#[pyclass(name)]
|
||||
#[derive(Debug)]
|
||||
struct DirEntry {
|
||||
entry: fs::DirEntry,
|
||||
@@ -557,6 +558,7 @@ mod _os {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "ScandirIter")]
|
||||
#[derive(Debug)]
|
||||
struct ScandirIterator {
|
||||
@@ -634,6 +636,7 @@ mod _os {
|
||||
.into_object())
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pystruct_sequence(module = "os", name = "stat_result")]
|
||||
#[derive(Debug)]
|
||||
pub(super) struct StatResult {
|
||||
@@ -830,6 +833,7 @@ mod _os {
|
||||
.into_owned()
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pystruct_sequence(module = "os", name = "terminal_size")]
|
||||
#[allow(dead_code)]
|
||||
pub(super) struct PyTerminalSize {
|
||||
@@ -1739,6 +1743,7 @@ mod posix {
|
||||
Ok(ret_mask)
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pystruct_sequence(module = "os", name = "uname_result")]
|
||||
#[derive(Debug)]
|
||||
struct UnameResult {
|
||||
|
||||
@@ -786,6 +786,7 @@ mod _struct {
|
||||
.with_ref(|buf| format_spec.unpack(&buf[offset..offset + size], vm))
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "unpack_iterator")]
|
||||
#[derive(Debug)]
|
||||
struct UnpackIterator {
|
||||
@@ -870,6 +871,7 @@ mod _struct {
|
||||
Ok(format_spec.size())
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "Struct")]
|
||||
#[derive(Debug)]
|
||||
struct PyStruct {
|
||||
@@ -970,7 +972,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
|
||||
let struct_error = ctx.new_class(
|
||||
"struct.error",
|
||||
ctx.exceptions.exception_type.clone(),
|
||||
&ctx.exceptions.exception_type,
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@ mod _random {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "Random")]
|
||||
#[derive(Debug)]
|
||||
struct PyRandom {
|
||||
|
||||
+2
-2
@@ -16,7 +16,7 @@ use crate::obj::objtype::PyClassRef;
|
||||
use crate::pyobject::{BorrowValue, PyClassImpl, PyObjectRef, PyResult, PyValue, TryFromObject};
|
||||
use crate::vm::VirtualMachine;
|
||||
|
||||
#[pyclass(name = "Pattern")]
|
||||
#[pyclass(module = "re", name = "Pattern")]
|
||||
#[derive(Debug)]
|
||||
struct PyPattern {
|
||||
regex: Regex,
|
||||
@@ -69,7 +69,7 @@ impl PyValue for PyPattern {
|
||||
}
|
||||
|
||||
/// Inner data for a match object.
|
||||
#[pyclass(name = "Match")]
|
||||
#[pyclass(module = "re", name = "Match")]
|
||||
struct PyMatch {
|
||||
haystack: PyStringRef,
|
||||
captures: Vec<Option<Range<usize>>>,
|
||||
|
||||
@@ -54,7 +54,7 @@ mod c {
|
||||
};
|
||||
}
|
||||
|
||||
#[pyclass(name = "socket")]
|
||||
#[pyclass(module = "socket", name = "socket")]
|
||||
#[derive(Debug)]
|
||||
pub struct PySocket {
|
||||
kind: AtomicCell<i32>,
|
||||
@@ -654,12 +654,12 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
let ctx = &vm.ctx;
|
||||
let socket_timeout = ctx.new_class(
|
||||
"socket.timeout",
|
||||
vm.ctx.exceptions.os_error.clone(),
|
||||
&vm.ctx.exceptions.os_error,
|
||||
Default::default(),
|
||||
);
|
||||
let socket_gaierror = ctx.new_class(
|
||||
"socket.gaierror",
|
||||
vm.ctx.exceptions.os_error.clone(),
|
||||
&vm.ctx.exceptions.os_error,
|
||||
Default::default(),
|
||||
);
|
||||
|
||||
|
||||
@@ -228,7 +228,7 @@ fn ssl_rand_pseudo_bytes(n: i32, vm: &VirtualMachine) -> PyResult<(Vec<u8>, bool
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass(name = "_SSLContext")]
|
||||
#[pyclass(module = "ssl", name = "_SSLContext")]
|
||||
struct PySslContext {
|
||||
ctx: PyRwLock<SslContextBuilder>,
|
||||
check_hostname: bool,
|
||||
@@ -504,7 +504,7 @@ struct LoadVerifyLocationsArgs {
|
||||
cadata: Option<Either<PyStringRef, PyBytesLike>>,
|
||||
}
|
||||
|
||||
#[pyclass(name = "_SSLSocket")]
|
||||
#[pyclass(module = "ssl", name = "_SSLSocket")]
|
||||
struct PySslSocket {
|
||||
ctx: PyRef<PySslContext>,
|
||||
stream: PyRwLock<Option<ssl::SslStreamBuilder<PySocketRef>>>,
|
||||
|
||||
@@ -60,6 +60,7 @@ mod decl {
|
||||
type PySymbolTableRef = PyRef<PySymbolTable>;
|
||||
type PySymbolRef = PyRef<PySymbol>;
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "SymbolTable")]
|
||||
struct PySymbolTable {
|
||||
symtable: symboltable::SymbolTable,
|
||||
@@ -176,6 +177,7 @@ mod decl {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "Symbol")]
|
||||
struct PySymbol {
|
||||
symbol: symboltable::Symbol,
|
||||
|
||||
@@ -92,7 +92,7 @@ macro_rules! repr_lock_impl {
|
||||
}};
|
||||
}
|
||||
|
||||
#[pyclass(name = "lock")]
|
||||
#[pyclass(module = "thread", name = "lock")]
|
||||
struct PyLock {
|
||||
mu: RawMutex,
|
||||
}
|
||||
@@ -146,7 +146,7 @@ impl PyLock {
|
||||
}
|
||||
|
||||
pub type RawRMutex = RawReentrantMutex<RawMutex, RawThreadId>;
|
||||
#[pyclass(name = "RLock")]
|
||||
#[pyclass(module = "thread", name = "RLock")]
|
||||
struct PyRLock {
|
||||
mu: RawRMutex,
|
||||
}
|
||||
@@ -277,7 +277,7 @@ fn thread_count(vm: &VirtualMachine) -> usize {
|
||||
vm.state.thread_count.load()
|
||||
}
|
||||
|
||||
#[pyclass(name = "_local")]
|
||||
#[pyclass(module = "thread", name = "_local")]
|
||||
#[derive(Debug)]
|
||||
struct PyLocal {
|
||||
data: ThreadLocal<PyDictRef>,
|
||||
|
||||
@@ -54,7 +54,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
|
||||
module
|
||||
}
|
||||
|
||||
#[pyclass(name = "UCD")]
|
||||
#[pyclass(module = "unicodedata", name = "UCD")]
|
||||
#[derive(Debug)]
|
||||
struct PyUCD {
|
||||
unic_version: UnicodeVersion,
|
||||
|
||||
@@ -14,7 +14,7 @@ use std::io;
|
||||
use winapi::shared::winerror;
|
||||
use winreg::{enums::RegType, RegKey, RegValue};
|
||||
|
||||
#[pyclass(name = "HKEYType")]
|
||||
#[pyclass(module = "winreg", name = "HKEYType")]
|
||||
#[derive(Debug)]
|
||||
struct PyHKEY {
|
||||
key: PyRwLock<RegKey>,
|
||||
|
||||
@@ -213,6 +213,7 @@ mod decl {
|
||||
unconsumed_tail: PyMutex::new(PyBytes::from(vec![]).into_ref(vm)),
|
||||
}
|
||||
}
|
||||
#[pyattr]
|
||||
#[pyclass(name = "Decompress")]
|
||||
#[derive(Debug)]
|
||||
struct PyDecompress {
|
||||
@@ -373,6 +374,7 @@ mod decl {
|
||||
unconsumed: Vec<u8>,
|
||||
}
|
||||
|
||||
#[pyattr]
|
||||
#[pyclass(name = "Compress")]
|
||||
#[derive(Debug)]
|
||||
struct PyCompress {
|
||||
|
||||
@@ -162,7 +162,7 @@ fn browser_cancel_animation_frame(id: i32, vm: &VirtualMachine) -> PyResult {
|
||||
Ok(vm.get_none())
|
||||
}
|
||||
|
||||
#[pyclass(name = "Promise")]
|
||||
#[pyclass(module = "browser", name = "Promise")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyPromise {
|
||||
value: Promise,
|
||||
@@ -248,7 +248,7 @@ impl PyPromise {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[pyclass(module = "browser", name)]
|
||||
#[derive(Debug)]
|
||||
struct Document {
|
||||
doc: web_sys::Document,
|
||||
@@ -276,7 +276,7 @@ impl Document {
|
||||
}
|
||||
}
|
||||
|
||||
#[pyclass]
|
||||
#[pyclass(module = "browser", name)]
|
||||
#[derive(Debug)]
|
||||
struct Element {
|
||||
elem: web_sys::Element,
|
||||
|
||||
@@ -30,7 +30,7 @@ extern "C" {
|
||||
fn instance_of(lhs: &JsValue, rhs: &JsValue) -> Result<bool, JsValue>;
|
||||
}
|
||||
|
||||
#[pyclass(name = "JsValue")]
|
||||
#[pyclass(module = "_js", name = "JsValue")]
|
||||
#[derive(Debug)]
|
||||
pub struct PyJsValue {
|
||||
value: JsValue,
|
||||
|
||||
@@ -32,7 +32,7 @@ pub fn make_stdout_object(
|
||||
let flush_method = ctx.new_method(|_self: PyObjectRef| {});
|
||||
// there's not really any point to storing this class so that there's a consistent type object,
|
||||
// we just want a half-decent repr() output
|
||||
let cls = py_class!(ctx, "JSStdout", vm.ctx.object(), {
|
||||
let cls = py_class!(ctx, "JSStdout", &vm.ctx.object(), {
|
||||
"write" => write_method,
|
||||
"flush" => flush_method,
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user