Make PyStructSequence a derive macro

This commit is contained in:
Noah committed 2020-08-30 15:46:04 -05:00
1 parent 79c0efc491
commit 619f1a1de9
20 files changed
+252 -205

No files matched your search

+4 -5
View File
@@ -52,11 +52,10 @@ pub fn pymodule(attr: TokenStream, item: TokenStream) -> TokenStream {
result_to_tokens(pymodule::impl_pymodule(attr, item))
}
#[proc_macro_attribute]
pub fn pystruct_sequence(attr: TokenStream, item: TokenStream) -> TokenStream {
let attr = parse_macro_input!(attr as AttributeArgs);
let item = parse_macro_input!(item as Item);
result_to_tokens(pyclass::impl_pystruct_sequence(attr, item))
#[proc_macro_derive(PyStructSequence)]
pub fn pystruct_sequence(input: TokenStream) -> TokenStream {
let input = parse_macro_input!(input as DeriveInput);
result_to_tokens(pyclass::impl_pystruct_sequence(input))
}
#[proc_macro]
+119 -137
View File
@@ -7,8 +7,8 @@ use proc_macro2::TokenStream;
use quote::{quote, quote_spanned, ToTokens};
use std::collections::HashMap;
use syn::{
parse_quote, spanned::Spanned, Attribute, AttributeArgs, Ident, Index, Item, Meta, NestedMeta,
Result,
parse_quote, spanned::Spanned, Attribute, AttributeArgs, DeriveInput, Ident, Index, Item, Meta,
NestedMeta, Result,
};
use syn_ext::ext::*;
@@ -17,6 +17,7 @@ struct ImplContext {
impl_extend_items: ItemNursery,
getset_items: GetSetNursery,
extend_slots_items: ItemNursery,
class_extensions: Vec<TokenStream>,
errors: Vec<syn::Error>,
}
@@ -49,6 +50,7 @@ fn raw_extend_methods<T: syn::parse::Parse>(context: &ImplContext) -> impl Itera
let getset_impl = &context.getset_items;
let extend_impl = &context.impl_extend_items;
let slots_impl = &context.extend_slots_items;
let class_extensions = &context.class_extensions;
macro_rules! iter_chain {
($($it:expr),*$(,)?) => {
std::iter::empty()
@@ -63,6 +65,7 @@ fn raw_extend_methods<T: syn::parse::Parse>(context: &ImplContext) -> impl Itera
) {
#getset_impl
#extend_impl
#(#class_extensions)*
}
},
parse_quote! {
@@ -86,36 +89,32 @@ pub(crate) fn impl_pyimpl(
with_impl,
flags,
with_slots,
structseq_impl,
} = extract_impl_attrs(attr)?;
let ty = &imp.self_ty;
if structseq_impl {
imp.items.extend(raw_extend_methods(&context));
imp.into_token_stream()
} else {
let getset_impl = &context.getset_items;
let extend_impl = &context.impl_extend_items;
let slots_impl = &context.extend_slots_items;
quote! {
#imp
impl ::rustpython_vm::pyobject::PyClassImpl for #ty {
const TP_FLAGS: ::rustpython_vm::slots::PyTpFlags = ::rustpython_vm::slots::PyTpFlags::from_bits_truncate(#flags);
let getset_impl = &context.getset_items;
let extend_impl = &context.impl_extend_items;
let slots_impl = &context.extend_slots_items;
let class_extensions = &context.class_extensions;
quote! {
#imp
impl ::rustpython_vm::pyobject::PyClassImpl for #ty {
const TP_FLAGS: ::rustpython_vm::slots::PyTpFlags = ::rustpython_vm::slots::PyTpFlags::from_bits_truncate(#flags);
fn impl_extend_class(
ctx: &::rustpython_vm::pyobject::PyContext,
class: &::rustpython_vm::obj::objtype::PyClassRef,
) {
#getset_impl
#extend_impl
#with_impl
}
fn impl_extend_class(
ctx: &::rustpython_vm::pyobject::PyContext,
class: &::rustpython_vm::obj::objtype::PyClassRef,
) {
#getset_impl
#extend_impl
#with_impl
#(#class_extensions)*
}
fn extend_slots(slots: &mut ::rustpython_vm::slots::PyClassSlots) {
#with_slots
#slots_impl
}
fn extend_slots(slots: &mut ::rustpython_vm::slots::PyClassSlots) {
#with_slots
#slots_impl
}
}
}
@@ -160,6 +159,29 @@ fn generate_class_def(
Some(v) => quote!(Some(#v) ),
None => quote!(None),
};
let mut is_pystruct = false;
'pystruct_check: for attr in attrs {
if path_eq(&attr.path, "derive") {
if let Ok(Meta::List(l)) = attr.parse_meta() {
for nested in l.nested {
if nested
.get_ident()
.map_or(false, |p| p == "PyStructSequence")
{
is_pystruct = true;
break 'pystruct_check;
}
}
}
}
}
let base_class = if is_pystruct {
let baseclassdef = quote!(::rustpython_vm::pyobject::BaseClassDef);
quote!(const BASE: #baseclassdef = #baseclassdef::tuple();)
} else {
quote!()
};
let tokens = quote! {
impl ::rustpython_vm::pyobject::PyClassDef for #ident {
@@ -167,6 +189,7 @@ fn generate_class_def(
const MODULE_NAME: Option<&'static str> = #module_name;
const TP_NAME: &'static str = #module_class_name;
const DOC: Option<&'static str> = #doc;
#base_class
}
};
Ok(tokens)
@@ -190,127 +213,59 @@ pub(crate) fn impl_pyclass(
Ok(ret)
}
struct StructSeqItemMeta(ItemMetaInner);
impl ItemMeta for StructSeqItemMeta {
const ALLOWED_NAMES: &'static [&'static str] = &["module", "name", "with_pyimpl"];
fn from_inner(inner: ItemMetaInner) -> Self {
Self(inner)
}
fn inner(&self) -> &ItemMetaInner {
&self.0
}
}
pub(crate) fn impl_pystruct_sequence(
attr: AttributeArgs,
item: Item,
input: DeriveInput,
) -> std::result::Result<TokenStream, Diagnostic> {
let struc = if let Item::Struct(struc) = item {
struc
let fields = if let syn::Data::Struct(ref struc) = input.data {
&struc.fields
} else {
bail_span!(
item,
input,
"#[pystruct_sequence] can only be on a struct declaration"
)
};
let fake_ident = Ident::new("pystruct_sequence", struc.span());
let meta = StructSeqItemMeta::from_nested(struc.ident.clone(), fake_ident, attr.into_iter())?;
let with_pyimpl = meta.inner()._bool("with_pyimpl")?;
let class_meta = ClassItemMeta(meta.0);
let class_name = class_meta.class_name()?;
let module_name = class_meta.mandatory_module()?;
let class_def =
generate_class_def(&struc.ident, &class_name, Some(&module_name), &struc.attrs)?;
let mut properties = Vec::new();
let mut field_names = Vec::new();
for (i, field) in struc.fields.iter().enumerate() {
let idx = Index::from(i);
if let Some(ref field_name) = field.ident {
let field_name_str = field_name.to_string();
// TODO add doc to the generated property
let property = quote! {
class.set_str_attr(
#field_name_str,
ctx.new_readonly_getset(
match fields {
syn::Fields::Named(fields) => {
for (i, field) in fields.named.iter().enumerate() {
let idx = Index::from(i);
let field_name = field.ident.as_ref().unwrap();
let field_name_str = field_name.to_string();
// TODO add doc to the generated property
let property = quote! {
class.set_str_attr(
#field_name_str,
|zelf: &::rustpython_vm::obj::objtuple::PyTuple,
_vm: &::rustpython_vm::VirtualMachine| {
zelf.fast_getitem(#idx)
}
),
);
};
properties.push(property);
field_names.push(quote!(#field_name));
} else {
field_names.push(quote!(#idx));
ctx.new_readonly_getset(
#field_name_str,
|zelf: &::rustpython_vm::obj::objtuple::PyTuple,
_vm: &::rustpython_vm::VirtualMachine| {
zelf.fast_getitem(#idx)
}
),
);
};
properties.push(property);
field_names.push(quote!(#field_name));
}
}
_ => bail_span!(
input,
"#[pystruct_sequence] can only be on a struct with named fields"
),
}
let (with_extend, with_slots) = if with_pyimpl {
(
quote! {
Self::__extend_py_class(ctx, class);
},
quote! {
Self::__extend_slots(slots);
},
)
} else {
(quote! {}, quote! {})
};
let ty = &struc.ident;
let ty = &input.ident;
let ret = quote! {
#struc
#class_def
impl #ty {
pub fn into_struct_sequence(&self,
vm: &::rustpython_vm::VirtualMachine,
cls: ::rustpython_vm::obj::objtype::PyClassRef,
) -> ::rustpython_vm::pyobject::PyResult<::rustpython_vm::obj::objtuple::PyTupleRef> {
let tuple = ::rustpython_vm::obj::objtuple::PyTuple::from(
vec![#(::rustpython_vm::pyobject::IntoPyObject::into_pyobject(
::std::clone::Clone::clone(&self.#field_names),
vm,
)),*],
);
::rustpython_vm::pyobject::PyValue::into_ref_with_type(tuple, vm, cls)
}
}
impl ::rustpython_vm::pyobject::PyStructSequenceImpl for #ty {
impl ::rustpython_vm::pyobject::PyStructSequence for #ty {
const FIELD_NAMES: &'static [&'static str] = &[#(stringify!(#field_names)),*];
}
impl ::rustpython_vm::pyobject::PyClassImpl for #ty {
#[cfg(debug_assertions)]
const TP_FLAGS: ::rustpython_vm::slots::PyTpFlags = ::rustpython_vm::slots::PyTpFlags::_CREATED_WITH_FLAGS;
fn impl_extend_class(
ctx: &::rustpython_vm::pyobject::PyContext,
class: &::rustpython_vm::obj::objtype::PyClassRef,
) {
use ::rustpython_vm::pyobject::PyStructSequenceImpl;
#(#properties)*
class.set_str_attr("__repr__", ctx.new_method(Self::repr));
#with_extend
}
fn make_class(
ctx: &::rustpython_vm::pyobject::PyContext,
) -> ::rustpython_vm::obj::objtype::PyClassRef {
use crate::pyobject::PyClassDef;
Self::make_class_with_base(ctx, Self::NAME, &ctx.types.tuple_type)
}
fn extend_slots(slots: &mut ::rustpython_vm::slots::PyClassSlots) {
#with_slots
fn to_tuple(&self, vm: &::rustpython_vm::VirtualMachine,) -> ::rustpython_vm::obj::objtuple::PyTuple {
let items = vec![#(::rustpython_vm::pyobject::IntoPyObject::into_pyobject(
::std::clone::Clone::clone(&self.#field_names),
vm,
)),*];
items.into()
}
}
};
@@ -333,6 +288,11 @@ struct SlotItem {
inner: ContentItemInner,
}
/// #[extend_class]
struct ExtendClassItem {
inner: ContentItemInner,
}
impl ContentItem for MethodItem {
fn inner(&self) -> &ContentItemInner {
&self.inner
@@ -348,6 +308,11 @@ impl ContentItem for SlotItem {
&self.inner
}
}
impl ContentItem for ExtendClassItem {
fn inner(&self) -> &ContentItemInner {
&self.inner
}
}
struct ImplItemArgs<'a, Item: ItemLike> {
item: &'a Item,
@@ -469,6 +434,26 @@ where
Ok(())
}
}
impl<Item> ImplItem<Item> for ExtendClassItem
where
Item: ItemLike + ToTokens + GetIdent,
{
fn gen_impl_item(&self, args: ImplItemArgs<'_, Item>) -> Result<()> {
args.attrs.remove(self.index());
let ident = if args.item.is_function_or_method() {
Ok(args.item.get_ident().unwrap())
} else {
Err(self.new_syn_error(args.item.span(), "can only be on a method"))
}?;
args.context.class_extensions.push(quote! {
Self::#ident(ctx, class);
});
Ok(())
}
}
#[derive(Default)]
#[allow(clippy::type_complexity)]
@@ -705,14 +690,12 @@ struct ExtractedImplAttrs {
with_impl: TokenStream,
with_slots: TokenStream,
flags: TokenStream,
structseq_impl: bool,
}
fn extract_impl_attrs(attr: AttributeArgs) -> std::result::Result<ExtractedImplAttrs, Diagnostic> {
let mut withs = Vec::new();
let mut with_slots = Vec::new();
let mut flags = vec![quote! { ::rustpython_vm::slots::PyTpFlags::DEFAULT.bits() }];
let mut structseq_impl = false;
#[cfg(debug_assertions)]
{
flags.push(quote! {
@@ -772,9 +755,6 @@ fn extract_impl_attrs(attr: AttributeArgs) -> std::result::Result<ExtractedImplA
bail_span!(path, "Unknown pyimpl attribute")
}
}
NestedMeta::Meta(Meta::Path(path)) if path_eq(&path, "structseq_impl") => {
structseq_impl = true
}
attr => bail_span!(attr, "Unknown pyimpl attribute"),
}
}
@@ -789,7 +769,6 @@ fn extract_impl_attrs(attr: AttributeArgs) -> std::result::Result<ExtractedImplA
with_slots: quote! {
#(#with_slots)*
},
structseq_impl,
})
}
@@ -812,6 +791,9 @@ where
"pyslot" => Box::new(SlotItem {
inner: ContentItemInner { index, attr_name },
}),
"extend_class" => Box::new(ExtendClassItem {
inner: ContentItemInner { index, attr_name },
}),
other => unreachable!("#[pyimpl] doesn't accept #[{}]", other),
}
}
+3 -3
View File
@@ -105,7 +105,7 @@ fn new_module_item(
"pyattr" => Box::new(AttributeItem {
inner: ContentItemInner { index, attr_name },
}),
"pystruct_sequence" | "pyclass" => Box::new(ClassItem {
"pyclass" => Box::new(ClassItem {
inner: ContentItemInner { index, attr_name },
pyattrs: pyattrs.unwrap_or_else(Vec::new),
}),
@@ -175,7 +175,7 @@ where
if pyattrs.is_empty() {
result.push(new_item(i, attr_name, None));
} else {
if !["pyclass", "pystruct_sequence"].contains(&attr_name.as_str()) {
if attr_name != "pyclass" {
return Err(syn::Error::new_spanned(
attr,
"#[pyattr] #[pyclass] is the only supported composition",
@@ -199,7 +199,7 @@ struct FunctionItem {
inner: ContentItemInner,
}
/// #[pyclass] or #[pystruct_sequence]
/// #[pyclass]
struct ClassItem {
inner: ContentItemInner,
pyattrs: Vec<usize>,
+13 -12
View File
@@ -14,6 +14,7 @@ pub(crate) const ALL_ALLOWED_NAMES: &[&str] = &[
"pystruct_sequence",
"pyattr",
"pyslot",
"extend_class",
];
#[derive(Default)]
@@ -292,18 +293,18 @@ impl ClassItemMeta {
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 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 {
+1 -1
View File
@@ -463,7 +463,7 @@ pub struct ExceptionZoo {
impl ExceptionZoo {
pub fn new(type_type: &PyClassRef, object_type: &PyClassRef) -> Self {
let create_exception_type = |name: &str, base: &PyClassRef| {
create_type_with_slots(name, type_type, base, PyBaseException::make_slots())
create_type_with_slots(name, type_type, base.clone(), PyBaseException::make_slots())
};
// Sorted By Hierarchy then alphabetized.
let base_exception_type = create_exception_type(PyBaseExceptionRef::NAME, &object_type);
+1 -1
View File
@@ -41,7 +41,7 @@ macro_rules! py_class {
#[allow(unused_mut)]
let mut slots: $crate::slots::PyClassSlots = ($crate::slots::PyTpFlags::DEFAULT | $flags).into();
$($crate::py_class!(@extract_slots($ctx, &mut slots, $name, $value));)*
let py_class = $ctx.new_class($class_name, $class_base, slots);
let py_class = $ctx.new_class($class_name, $class_base.clone(), slots);
$($crate::py_class!(@extract_attrs($ctx, &py_class, $name, $value));)*
$ctx.add_tp_new_wrapper(&py_class);
py_class
+50 -8
View File
@@ -130,13 +130,16 @@ impl PyContext {
PyRef::new_ref(payload, cls.clone(), None)
}
let none_type = PyNone::create_bare_type(&types.type_type, &types.object_type);
let none_type = PyNone::create_bare_type(&types.type_type, types.object_type.clone());
let none = create_object(PyNone, &none_type);
let ellipsis = create_object(PyEllipsis, &types.ellipsis_type);
let not_implemented_type =
create_type("NotImplementedType", &types.type_type, &types.object_type);
let not_implemented_type = create_type(
"NotImplementedType",
&types.type_type,
types.object_type.clone(),
);
let not_implemented = create_object(PyNotImplemented, &not_implemented_type);
let int_cache_pool = (Self::INT_CACHE_POOL_MIN..=Self::INT_CACHE_POOL_MAX)
@@ -276,7 +279,7 @@ impl PyContext {
.unwrap()
}
pub fn new_class(&self, name: &str, base: &PyClassRef, slots: PyClassSlots) -> PyClassRef {
pub fn new_class(&self, name: &str, base: PyClassRef, slots: PyClassSlots) -> PyClassRef {
create_type_with_slots(name, &self.types.type_type, base, slots)
}
@@ -1257,11 +1260,29 @@ where
}
}
// can be extended in the future to use some sort of pyclass() attr instead of make_class_with_base
pub struct BaseClassDef {
is_tuple: bool,
}
impl BaseClassDef {
pub const fn tuple() -> Self {
BaseClassDef { is_tuple: true }
}
pub fn get_class(&self, ctx: &PyContext) -> PyClassRef {
if self.is_tuple {
ctx.types.tuple_type.clone()
} else {
ctx.types.object_type.clone()
}
}
}
pub trait PyClassDef {
const NAME: &'static str;
const MODULE_NAME: Option<&'static str>;
const TP_NAME: &'static str;
const DOC: Option<&'static str> = None;
const BASE: BaseClassDef = BaseClassDef { is_tuple: false };
}
impl<T> PyClassDef for PyRef<T>
@@ -1305,16 +1326,16 @@ pub trait PyClassImpl: PyClassDef {
}
fn make_class(ctx: &PyContext) -> PyClassRef {
Self::make_class_with_base(ctx, Self::NAME, &ctx.types.object_type)
Self::make_class_with_base(ctx, Self::NAME, Self::BASE.get_class(ctx))
}
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::make_slots());
Self::extend_class(ctx, &py_class);
py_class
}
fn create_bare_type(type_type: &PyClassRef, base: &PyClassRef) -> PyClassRef {
fn create_bare_type(type_type: &PyClassRef, base: PyClassRef) -> PyClassRef {
create_type_with_slots(Self::NAME, type_type, base, Self::make_slots())
}
@@ -1329,9 +1350,17 @@ pub trait PyClassImpl: PyClassDef {
}
}
pub trait PyStructSequenceImpl: PyClassImpl {
#[pyimpl]
pub trait PyStructSequence: PyClassImpl + 'static {
const FIELD_NAMES: &'static [&'static str];
fn to_tuple(&self, vm: &VirtualMachine) -> PyTuple;
fn into_struct_sequence(&self, vm: &VirtualMachine, cls: PyClassRef) -> PyResult<PyTupleRef> {
self.to_tuple(vm).into_ref_with_type(vm, cls)
}
#[pymethod(magic)]
fn repr(zelf: PyRef<PyTuple>, vm: &VirtualMachine) -> PyResult<String> {
let format_field = |(value, name)| {
let s = vm.to_repr(value)?;
@@ -1357,6 +1386,19 @@ pub trait PyStructSequenceImpl: PyClassImpl {
};
Ok(format!("{}({}{})", Self::TP_NAME, body, suffix))
}
#[extend_class]
fn extend_pyclass(ctx: &PyContext, class: &PyClassRef) {
for (i, &name) in Self::FIELD_NAMES.iter().enumerate() {
// cast i to a u8 so there's less to store in the getter closure.
// Hopefully there's not struct sequences with >=256 elements :P
let i = i as u8;
class.set_str_attr(
name,
ctx.new_readonly_getset(name, move |zelf: &PyTuple| zelf.fast_getitem(i.into())),
);
}
}
}
// TODO: find a better place to put this impl
+1 -1
View File
@@ -202,7 +202,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let error = create_type(
"Error",
&ctx.types.type_type,
&ctx.exceptions.exception_type,
ctx.exceptions.exception_type.clone(),
);
py_module!(vm, "_csv", {
+1 -1
View File
@@ -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)
}
}
+12 -7
View File
@@ -23,8 +23,8 @@ use crate::obj::objstr::{PyString, PyStringRef};
use crate::obj::objtuple::PyTupleRef;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{
BorrowValue, Either, ItemProtocol, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue,
TryFromObject, TypeProtocol,
BorrowValue, Either, ItemProtocol, PyClassImpl, PyObjectRef, PyRef, PyResult, PyStructSequence,
PyValue, TryFromObject, TypeProtocol,
};
use crate::vm::VirtualMachine;
@@ -637,8 +637,8 @@ mod _os {
}
#[pyattr]
#[pystruct_sequence(module = "os", name = "stat_result")]
#[derive(Debug)]
#[pyclass(module = "os", name = "stat_result")]
#[derive(Debug, PyStructSequence)]
pub(super) struct StatResult {
pub st_mode: u32,
pub st_ino: u64,
@@ -652,6 +652,7 @@ mod _os {
pub st_ctime: f64,
}
#[pyimpl(with(PyStructSequence))]
impl StatResult {
pub(super) fn into_obj(self, vm: &VirtualMachine) -> PyObjectRef {
self.into_struct_sequence(vm, vm.class(super::MODULE_NAME, "stat_result"))
@@ -847,12 +848,15 @@ mod _os {
}
#[pyattr]
#[pystruct_sequence(module = "os", name = "terminal_size")]
#[pyclass(module = "os", name = "terminal_size")]
#[derive(PyStructSequence)]
#[allow(dead_code)]
pub(super) struct PyTerminalSize {
pub columns: usize,
pub lines: usize,
}
#[pyimpl(with(PyStructSequence))]
impl PyTerminalSize {}
pub(super) fn support_funcs(vm: &VirtualMachine) -> Vec<SupportFunc> {
let mut supports = super::platform::support_funcs(vm);
@@ -1757,8 +1761,8 @@ mod posix {
}
#[pyattr]
#[pystruct_sequence(module = "os", name = "uname_result")]
#[derive(Debug)]
#[pyclass(module = "os", name = "uname_result")]
#[derive(Debug, PyStructSequence)]
struct UnameResult {
sysname: String,
nodename: String,
@@ -1767,6 +1771,7 @@ mod posix {
machine: String,
}
#[pyimpl(with(PyStructSequence))]
impl UnameResult {
fn into_obj(self, vm: &VirtualMachine) -> PyObjectRef {
self.into_struct_sequence(vm, vm.class(super::MODULE_NAME, "uname_result"))
+5 -2
View File
@@ -1,14 +1,15 @@
use crate::exceptions::IntoPyException;
use crate::obj::objint::PyIntRef;
use crate::obj::objstr::PyStringRef;
use crate::pyobject::{BorrowValue, PyClassImpl, PyObjectRef, PyResult};
use crate::pyobject::{BorrowValue, PyClassImpl, PyObjectRef, PyResult, PyStructSequence};
use crate::vm::VirtualMachine;
use std::convert::TryFrom;
use std::ptr::NonNull;
use nix::unistd::{self, User};
#[pystruct_sequence(module = "pwd", name = "struct_passwd")]
#[pyclass(module = "pwd", name = "struct_passwd")]
#[derive(PyStructSequence)]
struct Passwd {
pw_name: String,
pw_passwd: String,
@@ -18,6 +19,8 @@ struct Passwd {
pw_dir: String,
pw_shell: String,
}
#[pyimpl(with(PyStructSequence))]
impl Passwd {}
impl From<User> for Passwd {
fn from(user: User) -> Self {
+1 -1
View File
@@ -972,7 +972,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let struct_error = ctx.new_class(
"struct.error",
&ctx.exceptions.exception_type,
ctx.exceptions.exception_type.clone(),
Default::default(),
);
+2 -2
View File
@@ -671,12 +671,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,
vm.ctx.exceptions.os_error.clone(),
Default::default(),
);
let socket_gaierror = ctx.new_class(
"socket.gaierror",
&vm.ctx.exceptions.os_error,
vm.ctx.exceptions.os_error.clone(),
Default::default(),
);
+1 -1
View File
@@ -757,7 +757,7 @@ pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let ssl_error = create_type(
"SSLError",
&vm.ctx.types.type_type,
&vm.ctx.exceptions.os_error,
vm.ctx.exceptions.os_error.clone(),
);
let module = py_module!(vm, "_ssl", {
"_SSLContext" => PySslContext::make_class(ctx),
+6 -3
View File
@@ -11,7 +11,9 @@ use crate::function::OptionalArg;
use crate::obj::objstr::PyStringRef;
use crate::obj::objtuple::PyTupleRef;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{BorrowValue, Either, PyClassImpl, PyObjectRef, PyResult, TryFromObject};
use crate::pyobject::{
BorrowValue, Either, PyClassImpl, PyObjectRef, PyResult, PyStructSequence, TryFromObject,
};
use crate::vm::VirtualMachine;
#[cfg(unix)]
@@ -170,7 +172,8 @@ fn time_strptime(
Ok(PyStructTime::new(vm, instant, -1).into_obj(vm))
}
#[pystruct_sequence(with_pyimpl, module = "time", name = "struct_time")]
#[pyclass(module = "time", name = "struct_time")]
#[derive(PyStructSequence)]
#[allow(dead_code)]
struct PyStructTime {
tm_year: PyObjectRef,
@@ -190,7 +193,7 @@ impl fmt::Debug for PyStructTime {
}
}
#[pyimpl(structseq_impl)]
#[pyimpl(with(PyStructSequence))]
impl PyStructTime {
fn new(vm: &VirtualMachine, tm: NaiveDateTime, isdst: i32) -> Self {
PyStructTime {
+1 -1
View File
@@ -44,7 +44,7 @@ mod decl {
create_type(
"error",
&vm.ctx.types.type_type,
&vm.ctx.exceptions.exception_type,
vm.ctx.exceptions.exception_type.clone(),
)
}
+20 -9
View File
@@ -5,7 +5,9 @@ use crate::frame::FrameRef;
use crate::function::{Args, OptionalArg, PyFuncArgs};
use crate::obj::objstr::PyStringRef;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{IntoPyObject, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyResult};
use crate::pyobject::{
IntoPyObject, ItemProtocol, PyClassImpl, PyContext, PyObjectRef, PyResult, PyStructSequence,
};
use crate::vm::{PySettings, VirtualMachine};
use crate::{builtins, exceptions, py_io, version};
use rustpython_common::hash::{PyHash, PyUHash};
@@ -69,8 +71,8 @@ fn getframe(offset: OptionalArg<usize>, vm: &VirtualMachine) -> PyResult<FrameRe
/// sys.flags
///
/// Flags provided through command line arguments or environment vars.
#[pystruct_sequence(with_pyimpl, name = "flags", module = "sys")]
#[derive(Default, Debug)]
#[pyclass(name = "flags", module = "sys")]
#[derive(Default, Debug, PyStructSequence)]
struct SysFlags {
/// -d
debug: u8,
@@ -104,7 +106,7 @@ struct SysFlags {
utf8_mode: u8,
}
#[pyimpl(structseq_impl)]
#[pyimpl(with(PyStructSequence))]
impl SysFlags {
fn from_settings(settings: &PySettings) -> Self {
// Start with sensible defaults:
@@ -249,8 +251,8 @@ fn sys_displayhook(obj: PyObjectRef, vm: &VirtualMachine) -> PyResult<()> {
Ok(())
}
#[pystruct_sequence(module = "sys", name = "getwindowsversion")]
#[derive(Default, Debug)]
#[pyclass(module = "sys", name = "getwindowsversion")]
#[derive(Default, Debug, PyStructSequence)]
#[cfg(windows)]
struct WindowsVersion {
major: u32,
@@ -264,6 +266,9 @@ struct WindowsVersion {
product_type: u8,
platform_version: (u32, u32, u32),
}
#[cfg(windows)]
#[pyimpl(with(PyStructSequence))]
impl WindowsVersion {}
#[cfg(windows)]
fn sys_getwindowsversion(vm: &VirtualMachine) -> PyResult<crate::obj::objtuple::PyTupleRef> {
@@ -364,7 +369,8 @@ pub fn sysconfigdata_name() -> String {
format!("_sysconfigdata_{}_{}_{}", ABIFLAGS, PLATFORM, MULTIARCH)
}
#[pystruct_sequence(module = "sys", name = "hash_info")]
#[pyclass(module = "sys", name = "hash_info")]
#[derive(PyStructSequence)]
struct PyHashInfo {
width: usize,
modulus: PyUHash,
@@ -376,6 +382,7 @@ struct PyHashInfo {
seed_bits: usize,
cutoff: usize,
}
#[pyimpl(with(PyStructSequence))]
impl PyHashInfo {
const INFO: Self = {
use rustpython_common::hash::*;
@@ -393,7 +400,8 @@ impl PyHashInfo {
};
}
#[pystruct_sequence(module = "sys", name = "float_info")]
#[pyclass(module = "sys", name = "float_info")]
#[derive(PyStructSequence)]
struct PyFloatInfo {
max: f64,
max_exp: i32,
@@ -407,6 +415,7 @@ struct PyFloatInfo {
radix: u32,
rounds: i32,
}
#[pyimpl(with(PyStructSequence))]
impl PyFloatInfo {
const INFO: Self = PyFloatInfo {
max: f64::MAX,
@@ -423,11 +432,13 @@ impl PyFloatInfo {
};
}
#[pystruct_sequence(module = "sys", name = "int_info")]
#[pyclass(module = "sys", name = "int_info")]
#[derive(PyStructSequence)]
struct PyIntInfo {
bits_per_digit: usize,
sizeof_digit: usize,
}
#[pyimpl(with(PyStructSequence))]
impl PyIntInfo {
const INFO: Self = PyIntInfo {
bits_per_digit: 30, //?
+6 -6
View File
@@ -125,10 +125,10 @@ impl TypeZoo {
macro_rules! create_type {
($class:ty) => {
<$class>::create_bare_type(&type_type, &object_type)
<$class>::create_bare_type(&type_type, object_type.clone())
};
($class:ty, $base:expr) => {
<$class>::create_bare_type(&type_type, $base)
<$class>::create_bare_type(&type_type, $base.clone())
};
}
@@ -138,7 +138,7 @@ impl TypeZoo {
async_generator_asend: create_type!(objasyncgenerator::PyAsyncGenASend),
async_generator_athrow: create_type!(objasyncgenerator::PyAsyncGenAThrow),
async_generator_wrapped_value: create_type!(objasyncgenerator::PyAsyncGenWrappedValue),
bool_type: create_type!(objbool::PyBool, &int_type),
bool_type: create_type!(objbool::PyBool, int_type),
bound_method_type: create_type!(objfunction::PyBoundMethod),
builtin_function_or_method_type: create_type!(objbuiltinfunc::PyBuiltinFunction),
bytearray_type: create_type!(objbytearray::PyByteArray),
@@ -201,14 +201,14 @@ impl TypeZoo {
}
}
pub fn create_type(name: &str, type_type: &PyClassRef, base: &PyClassRef) -> PyClassRef {
pub fn create_type(name: &str, type_type: &PyClassRef, base: PyClassRef) -> PyClassRef {
create_type_with_slots(name, type_type, base, Default::default())
}
pub fn create_type_with_slots(
name: &str,
type_type: &PyClassRef,
base: &PyClassRef,
base: PyClassRef,
slots: PyClassSlots,
) -> PyClassRef {
let dict = PyAttributes::new();
@@ -216,7 +216,7 @@ pub fn create_type_with_slots(
type_type.clone(),
name,
base.clone(),
vec![base.clone()],
vec![base],
dict,
slots,
)
+4 -3
View File
@@ -1,6 +1,7 @@
/* Several function to retrieve version information.
*/
use crate::pyobject::PyStructSequence;
use chrono::prelude::DateTime;
use chrono::Local;
use std::time::{Duration, UNIX_EPOCH};
@@ -15,8 +16,8 @@ const SERIAL: usize = 0;
pub const VERSION_HEX: usize =
(MAJOR << 24) | (MINOR << 16) | (MICRO << 8) | (RELEASELEVEL_N << 4) | SERIAL;
#[pystruct_sequence(with_pyimpl, module = "sys", name = "version_info")]
#[derive(Default, Debug)]
#[pyclass(module = "sys", name = "version_info")]
#[derive(Default, Debug, PyStructSequence)]
pub struct VersionInfo {
major: usize,
minor: usize,
@@ -34,7 +35,7 @@ pub fn get_version() -> String {
)
}
#[pyimpl(structseq_impl)]
#[pyimpl(with(PyStructSequence))]
impl VersionInfo {
pub const VERSION: VersionInfo = VersionInfo {
major: MAJOR,
+1 -1
View File
@@ -255,7 +255,7 @@ fn new_js_error(vm: &VirtualMachine, err: JsValue) -> PyBaseExceptionRef {
pub fn make_module(vm: &VirtualMachine) -> PyObjectRef {
let ctx = &vm.ctx;
py_module!(vm, "_js", {
"JsError" => create_type("JsError", &ctx.types.type_type, &ctx.exceptions.exception_type),
"JsError" => create_type("JsError", &ctx.types.type_type, ctx.exceptions.exception_type.clone()),
"JsValue" => PyJsValue::make_class(ctx),
})
}