Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 33 additions & 11 deletions derive/src/pymodule.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::error::Diagnostic;
use crate::util::{
iter_use_idents, pyclass_ident_and_attrs, text_signature, AttributeExt, ClassItemMeta,
ContentItem, ContentItemInner, ErrorVec, ItemMeta, ItemNursery, SimpleItemMeta,
iter_use_idents, pyclass_ident_and_attrs, text_signature, AttrItemMeta, AttributeExt,
ClassItemMeta, ContentItem, ContentItemInner, ErrorVec, ItemMeta, ItemNursery, SimpleItemMeta,
ALL_ALLOWED_NAMES,
};
use proc_macro2::TokenStream;
Expand Down Expand Up @@ -241,7 +241,7 @@ impl ContentItem for AttributeItem {
}

struct ModuleItemArgs<'a> {
item: &'a Item,
item: &'a mut Item,
attrs: &'a mut Vec<Attribute>,
context: &'a mut ModuleContext,
cfgs: &'a [Attribute],
Expand Down Expand Up @@ -370,15 +370,36 @@ impl ModuleItem for AttributeItem {
fn gen_module_item(&self, args: ModuleItemArgs<'_>) -> Result<()> {
let cfgs = args.cfgs.to_vec();
let attr = args.attrs.remove(self.index());
let get_py_name = |attr: &Attribute, ident: &Ident| -> Result<_> {
let item_meta = SimpleItemMeta::from_attr(ident.clone(), attr)?;
let py_name = item_meta.simple_name()?;
Ok(py_name)
};
let (py_name, tokens) = match args.item {
Item::Fn(syn::ItemFn { sig, .. }) => {
Item::Fn(syn::ItemFn { sig, block, .. }) => {
let ident = &sig.ident;
let py_name = get_py_name(&attr, ident)?;
// If `once` keyword is in #[pyattr],
// wrapping it with static_cell for preventing it from using it as function
let attr_meta = AttrItemMeta::from_attr(ident.clone(), &attr)?;
if attr_meta.inner()._bool("once")? {
let stmts = &block.stmts;
let return_type = match &sig.output {
syn::ReturnType::Default => {
unreachable!("#[pyattr] attached function must have return type.")
}
syn::ReturnType::Type(_, ty) => ty,
};
let stmt: syn::Stmt = parse_quote! {
{
rustpython_common::static_cell! {
static ERROR: #return_type;
}
ERROR
.get_or_init(|| {
#(#stmts)*
})
.clone()
}
};
block.stmts = vec![stmt];
}

let py_name = attr_meta.simple_name()?;
(
py_name.clone(),
quote_spanned! { ident.span() =>
Expand All @@ -387,7 +408,8 @@ impl ModuleItem for AttributeItem {
)
}
Item::Const(syn::ItemConst { ident, .. }) => {
let py_name = get_py_name(&attr, ident)?;
let item_meta = SimpleItemMeta::from_attr(ident.clone(), &attr)?;
let py_name = item_meta.simple_name()?;
(
py_name.clone(),
quote_spanned! { ident.span() =>
Expand Down
13 changes: 13 additions & 0 deletions derive/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,19 @@ impl ItemMeta for SimpleItemMeta {
}
}

pub(crate) struct AttrItemMeta(pub ItemMetaInner);

impl ItemMeta for AttrItemMeta {
const ALLOWED_NAMES: &'static [&'static str] = &["name", "once"];

fn from_inner(inner: ItemMetaInner) -> Self {
Self(inner)
}
fn inner(&self) -> &ItemMetaInner {
&self.0
}
}

pub(crate) struct ClassItemMeta(ItemMetaInner);

impl ItemMeta for ClassItemMeta {
Expand Down
36 changes: 8 additions & 28 deletions stdlib/src/binascii.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,18 @@ mod decl {
};
use itertools::Itertools;

#[pyattr(name = "Error")]
#[pyattr(name = "Error", once)]
fn error_type(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static BINASCII_ERROR: PyTypeRef;
}
BINASCII_ERROR
.get_or_init(|| {
vm.ctx.new_class(
Some("binascii"),
"Error",
&vm.ctx.exceptions.value_error,
Default::default(),
)
})
.clone()
vm.ctx.new_exception_type(
"binascii",
"Error",
Some(vec![vm.ctx.exceptions.value_error.clone()]),
)
}

#[pyattr(name = "Incomplete")]
#[pyattr(name = "Incomplete", once)]
fn incomplete_type(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static BINASCII_INCOMPLTE: PyTypeRef;
}
BINASCII_INCOMPLTE
.get_or_init(|| {
vm.ctx.new_class(
Some("binascii"),
"Incomplete",
&vm.ctx.exceptions.exception_type,
Default::default(),
)
})
.clone()
vm.ctx.new_exception_type("binascii", "Incomplete", None)
}

fn hex_nibble(n: u8) -> u8 {
Expand Down
10 changes: 7 additions & 3 deletions stdlib/src/csv.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ pub(crate) fn make_module(vm: &VirtualMachine) -> PyObjectRef {
mod _csv {
use crate::common::lock::PyMutex;
use crate::vm::{
builtins::{PyStr, PyStrRef, PyType, PyTypeRef},
builtins::{PyStr, PyStrRef, PyTypeRef},
function::{ArgIterable, ArgumentError, FromArgs, FuncArgs},
match_class,
protocol::{PyIter, PyIterReturn},
Expand All @@ -30,9 +30,13 @@ mod _csv {
#[pyattr]
const QUOTE_NONE: i32 = QuoteStyle::None as i32;

#[pyattr(name = "Error")]
#[pyattr(name = "Error", once)]
fn error(vm: &VirtualMachine) -> PyTypeRef {
PyType::new_simple_ref("_csv.Error", &vm.ctx.exceptions.exception_type).unwrap()
vm.ctx.new_exception_type(
"_csv",
"Error",
Some(vec![vm.ctx.exceptions.exception_type.clone()]),
)
}

#[pyfunction]
Expand Down
60 changes: 18 additions & 42 deletions stdlib/src/socket.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,53 +80,29 @@ mod _socket {
vm.ctx.exceptions.os_error.clone()
}

#[pyattr]
#[pyattr(once)]
fn timeout(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static ERROR: PyTypeRef;
}
ERROR
.get_or_init(|| {
vm.ctx.new_class(
Some("socket"),
"timeout",
&vm.ctx.exceptions.os_error,
Default::default(),
)
})
.clone()
vm.ctx.new_exception_type(
"socket",
"timeout",
Some(vec![vm.ctx.exceptions.os_error.clone()]),
)
}
#[pyattr]
#[pyattr(once)]
fn herror(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static ERROR: PyTypeRef;
}
ERROR
.get_or_init(|| {
vm.ctx.new_class(
Some("socket"),
"herror",
&vm.ctx.exceptions.os_error,
Default::default(),
)
})
.clone()
vm.ctx.new_exception_type(
"socket",
"herror",
Some(vec![vm.ctx.exceptions.os_error.clone()]),
)
}
#[pyattr]
#[pyattr(once)]
fn gaierror(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static ERROR: PyTypeRef;
}
ERROR
.get_or_init(|| {
vm.ctx.new_class(
Some("socket"),
"gaierror",
&vm.ctx.exceptions.os_error,
Default::default(),
)
})
.clone()
vm.ctx.new_exception_type(
"socket",
"gaierror",
Some(vec![vm.ctx.exceptions.os_error.clone()]),
)
}

#[pyfunction]
Expand Down
102 changes: 35 additions & 67 deletions stdlib/src/ssl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ mod _ssl {
},
socket::{self, PySocket},
vm::{
builtins::{PyBaseException, PyBaseExceptionRef, PyStrRef, PyType, PyTypeRef, PyWeak},
builtins::{PyBaseExceptionRef, PyStrRef, PyType, PyTypeRef, PyWeak},
exceptions,
function::{
ArgBytesLike, ArgCallable, ArgMemoryBuffer, ArgStrOrBytesLike, IntoPyException,
Expand All @@ -39,7 +39,7 @@ mod _ssl {
stdlib::os::PyPathLike,
types::Constructor,
utils::{Either, ToCString},
ItemProtocol, PyClassImpl, PyObjectRef, PyRef, PyResult, PyValue, VirtualMachine,
ItemProtocol, PyObjectRef, PyRef, PyResult, PyValue, VirtualMachine,
},
};
use crossbeam_utils::atomic::AtomicCell;
Expand Down Expand Up @@ -174,90 +174,58 @@ mod _ssl {
parse_version_info(openssl_api_version)
}

#[pyattr(name = "SSLError")]
/// An error occurred in the SSL implementation.
#[pyattr(name = "SSLError", once)]
fn ssl_error(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static ERROR: PyTypeRef;
}
ERROR
.get_or_init(|| {
PyType::new_simple_ref("ssl.SSLError", &vm.ctx.exceptions.os_error).unwrap()
})
.clone()
vm.ctx.new_exception_type(
"ssl",
"SSLError",
Some(vec![vm.ctx.exceptions.os_error.clone()]),
)
}

#[pyattr(name = "SSLCertVerificationError")]
/// A certificate could not be verified.
#[pyattr(name = "SSLCertVerificationError", once)]
fn ssl_cert_verification_error(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static ERROR: PyTypeRef;
}
ERROR
.get_or_init(|| {
let ssl_error = ssl_error(vm);
PyType::new_ref(
"ssl.SSLCertVerificationError",
vec![ssl_error, vm.ctx.exceptions.value_error.clone()],
Default::default(),
PyBaseException::make_slots(),
vm.ctx.types.type_type.clone(),
)
.unwrap()
})
.clone()
vm.ctx.new_exception_type(
"ssl",
"SSLCertVerificationError",
Some(vec![ssl_error(vm), vm.ctx.exceptions.value_error.clone()]),
)
}

#[pyattr(name = "SSLZeroReturnError")]
/// SSL/TLS session closed cleanly.
#[pyattr(name = "SSLZeroReturnError", once)]
fn ssl_zero_return_error(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static ERROR: PyTypeRef;
}
ERROR
.get_or_init(|| {
PyType::new_simple_ref("ssl.SSLZeroReturnError", &ssl_error(vm)).unwrap()
})
.clone()
vm.ctx
.new_exception_type("ssl", "SSLZeroReturnError", Some(vec![ssl_error(vm)]))
}

#[pyattr(name = "SSLWantReadError")]
/// Non-blocking SSL socket needs to read more data before the requested operation can be completed.
#[pyattr(name = "SSLWantReadError", once)]
fn ssl_want_read_error(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static ERROR: PyTypeRef;
}
ERROR
.get_or_init(|| PyType::new_simple_ref("ssl.SSLWantReadError", &ssl_error(vm)).unwrap())
.clone()
vm.ctx
.new_exception_type("ssl", "SSLWantReadError", Some(vec![ssl_error(vm)]))
}

#[pyattr(name = "SSLWantWriteError")]
/// Non-blocking SSL socket needs to write more data before the requested operation can be completed.
#[pyattr(name = "SSLWantWriteError", once)]
fn ssl_want_write_error(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static ERROR: PyTypeRef;
}
ERROR
.get_or_init(|| {
PyType::new_simple_ref("ssl.SSLWantWriteError", &ssl_error(vm)).unwrap()
})
.clone()
vm.ctx
.new_exception_type("ssl", "SSLWantWriteError", Some(vec![ssl_error(vm)]))
}

#[pyattr(name = "SSLSyscallError")]
/// System error when attempting SSL operation.
#[pyattr(name = "SSLSyscallError", once)]
fn ssl_syscall_error(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static ERROR: PyTypeRef;
}
ERROR
.get_or_init(|| PyType::new_simple_ref("ssl.SSLSyscallError", &ssl_error(vm)).unwrap())
.clone()
vm.ctx
.new_exception_type("ssl", "SSLSyscallError", Some(vec![ssl_error(vm)]))
}

#[pyattr(name = "SSLEOFError")]
/// SSL/TLS connection terminated abruptly.
#[pyattr(name = "SSLEOFError", once)]
fn ssl_eof_error(vm: &VirtualMachine) -> PyTypeRef {
rustpython_common::static_cell! {
static ERROR: PyTypeRef;
}
ERROR
.get_or_init(|| PyType::new_simple_ref("ssl.SSLEOFError", &ssl_error(vm)).unwrap())
.clone()
PyType::new_simple_ref("ssl.SSLEOFError", &ssl_error(vm)).unwrap()
}

type OpensslVersionInfo = (u8, u8, u8, u8, u8);
Expand Down
Loading