Move function items out of pyobject module

This commit is contained in:
Joey committed 2019-03-15 21:27:11 -07:00
1 parent fa9e48a5b3
commit 7bfd2e6e84
58 files changed
+670 -628

No files matched your search

+5 -4
View File
@@ -7,6 +7,8 @@ use std::char;
use std::io::{self, Write};
use std::path::PathBuf;
use num_traits::{Signed, ToPrimitive};
use crate::compile;
use crate::import::import_module;
use crate::obj::objbool;
@@ -17,16 +19,15 @@ use crate::obj::objstr;
use crate::obj::objtype;
use crate::frame::Scope;
use crate::function::PyFuncArgs;
use crate::pyobject::{
AttributeProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
AttributeProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol,
};
use crate::vm::VirtualMachine;
#[cfg(not(target_arch = "wasm32"))]
use crate::stdlib::io::io_open;
use crate::vm::VirtualMachine;
use num_traits::{Signed, ToPrimitive};
fn get_locals(vm: &mut VirtualMachine) -> PyObjectRef {
let d = vm.new_dict();
// TODO: implement dict_iter_items?
+2 -1
View File
@@ -1,8 +1,9 @@
use crate::function::PyFuncArgs;
use crate::obj::objsequence;
use crate::obj::objstr;
use crate::obj::objtype;
use crate::pyobject::{
create_type, AttributeProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
create_type, AttributeProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol,
};
use crate::vm::VirtualMachine;
+3 -2
View File
@@ -8,6 +8,7 @@ use rustpython_parser::ast;
use crate::builtins;
use crate::bytecode;
use crate::function::PyFuncArgs;
use crate::obj::objbool;
use crate::obj::objbuiltinfunc::PyBuiltinFunction;
use crate::obj::objcode;
@@ -20,8 +21,8 @@ use crate::obj::objslice::PySlice;
use crate::obj::objstr;
use crate::obj::objtype;
use crate::pyobject::{
AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectRef,
PyResult, PyValue, TryFromObject, TypeProtocol,
AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyObject, PyObjectRef, PyResult,
PyValue, TryFromObject, TypeProtocol,
};
use crate::vm::VirtualMachine;
+436
View File
@@ -0,0 +1,436 @@
use std::collections::HashMap;
use std::iter;
use std::ops::RangeInclusive;
use crate::obj::objtype;
use crate::pyobject::{IntoPyObject, PyObjectRef, PyResult, TryFromObject, TypeProtocol};
use crate::vm::VirtualMachine;
use self::OptionalArg::*;
/// The `PyFuncArgs` struct is one of the most used structs then creating
/// a rust function that can be called from python. It holds both positional
/// arguments, as well as keyword arguments passed to the function.
#[derive(Debug, Default, Clone)]
pub struct PyFuncArgs {
pub args: Vec<PyObjectRef>,
pub kwargs: Vec<(String, PyObjectRef)>,
}
/// Conversion from vector of python objects to function arguments.
impl From<Vec<PyObjectRef>> for PyFuncArgs {
fn from(args: Vec<PyObjectRef>) -> Self {
PyFuncArgs {
args: args,
kwargs: vec![],
}
}
}
impl From<PyObjectRef> for PyFuncArgs {
fn from(arg: PyObjectRef) -> Self {
PyFuncArgs {
args: vec![arg],
kwargs: vec![],
}
}
}
impl PyFuncArgs {
pub fn new(mut args: Vec<PyObjectRef>, kwarg_names: Vec<String>) -> PyFuncArgs {
let mut kwargs = vec![];
for name in kwarg_names.iter().rev() {
kwargs.push((name.clone(), args.pop().unwrap()));
}
PyFuncArgs { args, kwargs }
}
pub fn insert(&self, item: PyObjectRef) -> PyFuncArgs {
let mut args = PyFuncArgs {
args: self.args.clone(),
kwargs: self.kwargs.clone(),
};
args.args.insert(0, item);
args
}
pub fn shift(&mut self) -> PyObjectRef {
self.args.remove(0)
}
pub fn get_kwarg(&self, key: &str, default: PyObjectRef) -> PyObjectRef {
for (arg_name, arg_value) in self.kwargs.iter() {
if arg_name == key {
return arg_value.clone();
}
}
default.clone()
}
pub fn get_optional_kwarg(&self, key: &str) -> Option<PyObjectRef> {
for (arg_name, arg_value) in self.kwargs.iter() {
if arg_name == key {
return Some(arg_value.clone());
}
}
None
}
pub fn get_optional_kwarg_with_type(
&self,
key: &str,
ty: PyObjectRef,
vm: &mut VirtualMachine,
) -> Result<Option<PyObjectRef>, PyObjectRef> {
match self.get_optional_kwarg(key) {
Some(kwarg) => {
if objtype::isinstance(&kwarg, &ty) {
Ok(Some(kwarg))
} else {
let expected_ty_name = vm.to_pystr(&ty)?;
let actual_ty_name = vm.to_pystr(&kwarg.typ())?;
Err(vm.new_type_error(format!(
"argument of type {} is required for named parameter `{}` (got: {})",
expected_ty_name, key, actual_ty_name
)))
}
}
None => Ok(None),
}
}
/// Serializes these arguments into an iterator starting with the positional
/// arguments followed by keyword arguments.
fn into_iter(self) -> impl Iterator<Item = PyArg> {
self.args.into_iter().map(PyArg::Positional).chain(
self.kwargs
.into_iter()
.map(|(name, value)| PyArg::Keyword(name, value)),
)
}
/// Binds these arguments to their respective values.
///
/// If there is an insufficient number of arguments, there are leftover
/// arguments after performing the binding, or if an argument is not of
/// the expected type, a TypeError is raised.
///
/// If the given `FromArgs` includes any conversions, exceptions raised
/// during the conversion will halt the binding and return the error.
fn bind<T: FromArgs>(self, vm: &mut VirtualMachine) -> PyResult<T> {
let given_args = self.args.len();
let mut args = self.into_iter().peekable();
let bound = match T::from_args(vm, &mut args) {
Ok(args) => args,
Err(ArgumentError::TooFewArgs) => {
return Err(vm.new_type_error(format!(
"Expected at least {} arguments ({} given)",
T::arity().start(),
given_args,
)));
}
Err(ArgumentError::Exception(ex)) => {
return Err(ex);
}
};
match args.next() {
None => Ok(bound),
Some(PyArg::Positional(_)) => Err(vm.new_type_error(format!(
"Expected at most {} arguments ({} given)",
T::arity().end(),
given_args,
))),
Some(PyArg::Keyword(name, _)) => {
Err(vm.new_type_error(format!("Unexpected keyword argument {}", name)))
}
}
}
}
pub enum PyArg {
Positional(PyObjectRef),
Keyword(String, PyObjectRef),
}
pub enum ArgumentError {
TooFewArgs,
Exception(PyObjectRef),
}
impl From<PyObjectRef> for ArgumentError {
fn from(ex: PyObjectRef) -> Self {
ArgumentError::Exception(ex)
}
}
/// Implemented by any type that can be accepted as a parameter to a built-in
/// function.
///
pub trait FromArgs: Sized {
/// The range of positional arguments permitted by the function signature.
///
/// Returns an empty range if not applicable.
fn arity() -> RangeInclusive<usize> {
0..=0
}
/// Extracts this item from the next argument(s).
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>;
}
/// A map of keyword arguments to their values.
///
/// A built-in function with a `KwArgs` parameter is analagous to a Python
/// function with `*kwargs`. All remaining keyword arguments are extracted
/// (and hence the function will permit an arbitrary number of them).
///
/// `KwArgs` optionally accepts a generic type parameter to allow type checks
/// or conversions of each argument.
pub struct KwArgs<T = PyObjectRef>(HashMap<String, T>);
impl<T> FromArgs for KwArgs<T>
where
T: TryFromObject,
{
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>,
{
let mut kwargs = HashMap::new();
while let Some(PyArg::Keyword(name, value)) = args.next() {
kwargs.insert(name, T::try_from_object(vm, value)?);
}
Ok(KwArgs(kwargs))
}
}
/// A list of positional argument values.
///
/// A built-in function with a `Args` parameter is analagous to a Python
/// function with `*args`. All remaining positional arguments are extracted
/// (and hence the function will permit an arbitrary number of them).
///
/// `Args` optionally accepts a generic type parameter to allow type checks
/// or conversions of each argument.
pub struct Args<T>(Vec<T>);
impl<T> FromArgs for Args<T>
where
T: TryFromObject,
{
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>,
{
let mut varargs = Vec::new();
while let Some(PyArg::Positional(value)) = args.next() {
varargs.push(T::try_from_object(vm, value)?);
}
Ok(Args(varargs))
}
}
impl<T> FromArgs for T
where
T: TryFromObject,
{
fn arity() -> RangeInclusive<usize> {
1..=1
}
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>,
{
if let Some(PyArg::Positional(value)) = args.next() {
Ok(T::try_from_object(vm, value)?)
} else {
Err(ArgumentError::TooFewArgs)
}
}
}
/// An argument that may or may not be provided by the caller.
///
/// This style of argument is not possible in pure Python.
pub enum OptionalArg<T> {
Present(T),
Missing,
}
impl<T> OptionalArg<T> {
pub fn into_option(self) -> Option<T> {
match self {
Present(value) => Some(value),
Missing => None,
}
}
}
impl<T> FromArgs for OptionalArg<T>
where
T: TryFromObject,
{
fn arity() -> RangeInclusive<usize> {
0..=1
}
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>,
{
Ok(if let Some(PyArg::Positional(_)) = args.peek() {
let value = if let Some(PyArg::Positional(value)) = args.next() {
value
} else {
unreachable!()
};
Present(T::try_from_object(vm, value)?)
} else {
Missing
})
}
}
// For functions that accept no arguments. Implemented explicitly instead of via
// macro below to avoid unused warnings.
impl FromArgs for () {
fn from_args<I>(
_vm: &mut VirtualMachine,
_args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>,
{
Ok(())
}
}
// A tuple of types that each implement `FromArgs` represents a sequence of
// arguments that can be bound and passed to a built-in function.
//
// Technically, a tuple can contain tuples, which can contain tuples, and so on,
// so this actually represents a tree of values to be bound from arguments, but
// in practice this is only used for the top-level parameters.
macro_rules! tuple_from_py_func_args {
($($T:ident),+) => {
impl<$($T),+> FromArgs for ($($T,)+)
where
$($T: FromArgs),+
{
fn arity() -> RangeInclusive<usize> {
let mut min = 0;
let mut max = 0;
$(
let (start, end) = $T::arity().into_inner();
min += start;
max += end;
)+
min..=max
}
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>
{
Ok(($($T::from_args(vm, args)?,)+))
}
}
};
}
// Implement `FromArgs` for up to 5-tuples, allowing built-in functions to bind
// up to 5 top-level parameters (note that `Args`, `KwArgs`, nested tuples, etc.
// count as 1, so this should actually be more than enough).
tuple_from_py_func_args!(A);
tuple_from_py_func_args!(A, B);
tuple_from_py_func_args!(A, B, C);
tuple_from_py_func_args!(A, B, C, D);
tuple_from_py_func_args!(A, B, C, D, E);
/// A built-in Python function.
pub type PyNativeFunc = Box<dyn Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult + 'static>;
/// Implemented by types that are or can generate built-in functions.
///
/// For example, any function that:
///
/// - Accepts a sequence of types that implement `FromArgs`, followed by a
/// `&mut VirtualMachine`
/// - Returns some type that implements `IntoPyObject`
///
/// will generate a `PyNativeFunc` that performs the appropriate type and arity
/// checking, any requested conversions, and then if successful call the function
/// with the bound values.
///
/// A bare `PyNativeFunc` also implements this trait, allowing the above to be
/// done manually, for rare situations that don't fit into this model.
pub trait IntoPyNativeFunc<T, R> {
fn into_func(self) -> PyNativeFunc;
}
impl<F> IntoPyNativeFunc<PyFuncArgs, PyResult> for F
where
F: Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult + 'static,
{
fn into_func(self) -> PyNativeFunc {
Box::new(self)
}
}
impl IntoPyNativeFunc<PyFuncArgs, PyResult> for PyNativeFunc {
fn into_func(self) -> PyNativeFunc {
self
}
}
// This is the "magic" that allows rust functions of varying signatures to
// generate native python functions.
//
// Note that this could be done without a macro - it is simply to avoid repetition.
macro_rules! into_py_native_func_tuple {
($(($n:tt, $T:ident)),*) => {
impl<F, $($T,)* R> IntoPyNativeFunc<($($T,)*), R> for F
where
F: Fn($($T,)* &mut VirtualMachine) -> R + 'static,
$($T: FromArgs,)*
($($T,)*): FromArgs,
R: IntoPyObject,
{
fn into_func(self) -> PyNativeFunc {
Box::new(move |vm, args| {
let ($($n,)*) = args.bind::<($($T,)*)>(vm)?;
(self)($($n,)* vm).into_pyobject(vm)
})
}
}
};
}
into_py_native_func_tuple!();
into_py_native_func_tuple!((a, A));
into_py_native_func_tuple!((a, A), (b, B));
into_py_native_func_tuple!((a, A), (b, B), (c, C));
into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D));
into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D), (e, E));
+1
View File
@@ -41,6 +41,7 @@ pub mod eval;
mod exceptions;
pub mod format;
pub mod frame;
pub mod function;
pub mod import;
pub mod obj;
pub mod pyobject;
+2 -1
View File
@@ -1,6 +1,7 @@
use num_traits::Zero;
use crate::pyobject::{IntoPyObject, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::function::PyFuncArgs;
use crate::pyobject::{IntoPyObject, PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
use super::objdict::PyDict;
+2 -1
View File
@@ -1,6 +1,7 @@
use std::fmt;
use crate::pyobject::{PyNativeFunc, PyObjectRef, PyValue};
use crate::function::PyNativeFunc;
use crate::pyobject::{PyObjectRef, PyValue};
use crate::vm::VirtualMachine;
pub struct PyBuiltinFunction {
+5 -6
View File
@@ -4,15 +4,14 @@ use std::cell::RefCell;
use std::fmt::Write;
use std::ops::{Deref, DerefMut};
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use num_traits::ToPrimitive;
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
use super::objint;
use super::objtype;
use crate::vm::VirtualMachine;
use num_traits::ToPrimitive;
#[derive(Debug)]
pub struct PyByteArray {
+7 -4
View File
@@ -2,13 +2,16 @@ use std::cell::Cell;
use std::hash::{Hash, Hasher};
use std::ops::Deref;
use super::objint;
use super::objtype;
use num_traits::ToPrimitive;
use crate::function::PyFuncArgs;
use crate::pyobject::{
PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
PyContext, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_traits::ToPrimitive;
use super::objint;
use super::objtype;
#[derive(Debug)]
pub struct PyBytes {
+2 -1
View File
@@ -1,4 +1,5 @@
use crate::pyobject::{AttributeProtocol, PyContext, PyFuncArgs, PyResult, TypeProtocol};
use crate::function::PyFuncArgs;
use crate::pyobject::{AttributeProtocol, PyContext, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
pub fn init(context: &PyContext) {
+5 -5
View File
@@ -2,13 +2,13 @@
*/
use crate::bytecode;
use crate::pyobject::{
IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
use std::fmt;
use crate::bytecode;
use crate::function::PyFuncArgs;
use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
pub struct PyCode {
code: bytecode::CodeObject,
}
+7 -6
View File
@@ -1,12 +1,13 @@
use num_complex::Complex64;
use num_traits::ToPrimitive;
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
use super::objfloat;
use super::objint;
use super::objtype;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_complex::Complex64;
use num_traits::ToPrimitive;
#[derive(Debug, Copy, Clone, PartialEq)]
pub struct PyComplex {
+3 -2
View File
@@ -3,9 +3,10 @@ use std::collections::HashMap;
use std::fmt;
use std::ops::{Deref, DerefMut};
use crate::function::PyFuncArgs;
use crate::pyobject::{
PyAttributes, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult,
PyValue, TypeProtocol,
PyAttributes, PyContext, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, PyValue,
TypeProtocol,
};
use crate::vm::{ReprGuard, VirtualMachine};
+2 -1
View File
@@ -1,4 +1,5 @@
use crate::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol};
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
pub fn init(context: &PyContext) {
+7 -6
View File
@@ -1,15 +1,16 @@
use std::cell::RefCell;
use std::ops::AddAssign;
use super::objint;
use super::objiter;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_bigint::BigInt;
use num_traits::Zero;
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
use super::objint;
use super::objiter;
#[derive(Debug)]
pub struct PyEnumerate {
counter: RefCell<BigInt>,
+2 -1
View File
@@ -1,5 +1,6 @@
use crate::function::PyFuncArgs;
use crate::pyobject::{
IdProtocol, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
IdProtocol, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine; // Required for arg_check! to use isinstance
+2 -1
View File
@@ -3,7 +3,8 @@
*/
use crate::frame::Frame;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
pub fn init(context: &PyContext) {
+2 -3
View File
@@ -1,7 +1,6 @@
use crate::frame::Scope;
use crate::pyobject::{
IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::function::PyFuncArgs;
use crate::pyobject::{IdProtocol, PyContext, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
#[derive(Debug)]
+2 -3
View File
@@ -3,9 +3,8 @@
*/
use crate::frame::{ExecutionResult, Frame};
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
#[derive(Debug)]
+3 -2
View File
@@ -5,9 +5,10 @@ use num_integer::Integer;
use num_traits::{Pow, Signed, ToPrimitive, Zero};
use crate::format::FormatSpec;
use crate::function::{OptionalArg, PyFuncArgs};
use crate::pyobject::{
IntoPyObject, OptionalArg, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyRef, PyResult,
PyValue, TryFromObject, TypeProtocol,
IntoPyObject, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue, TryFromObject,
TypeProtocol,
};
use crate::vm::VirtualMachine;
+2 -3
View File
@@ -2,9 +2,8 @@
* Various types to support iteration.
*/
use crate::pyobject::{
PyContext, PyFuncArgs, PyIteratorValue, PyObjectRef, PyResult, TypeProtocol,
};
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyIteratorValue, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
use super::objbool;
+10 -7
View File
@@ -1,4 +1,14 @@
use std::cell::{Cell, RefCell};
use std::fmt;
use num_traits::ToPrimitive;
use crate::function::{OptionalArg, PyFuncArgs};
use crate::pyobject::{
IdProtocol, PyContext, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, PyValue,
TypeProtocol,
};
use crate::vm::{ReprGuard, VirtualMachine};
use super::objbool;
use super::objint;
@@ -8,13 +18,6 @@ use super::objsequence::{
};
use super::objstr;
use super::objtype;
use crate::pyobject::{
IdProtocol, OptionalArg, PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyRef,
PyResult, PyValue, TypeProtocol,
};
use crate::vm::{ReprGuard, VirtualMachine};
use num_traits::ToPrimitive;
use std::fmt;
#[derive(Default)]
pub struct PyList {
+2 -3
View File
@@ -1,6 +1,5 @@
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
use super::objiter;
+2 -3
View File
@@ -1,6 +1,5 @@
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
#[derive(Debug)]
+2 -1
View File
@@ -1,5 +1,6 @@
use crate::function::PyFuncArgs;
use crate::pyobject::{
IntoPyObject, PyContext, PyFuncArgs, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
IntoPyObject, PyContext, PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
+8 -6
View File
@@ -1,12 +1,14 @@
use crate::function::PyFuncArgs;
use crate::obj::objproperty::PropertyBuilder;
use crate::pyobject::{
AttributeProtocol, DictProtocol, IdProtocol, PyAttributes, PyContext, PyObjectRef, PyRef,
PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
use super::objlist::PyList;
use super::objstr;
use super::objtype;
use crate::obj::objproperty::PropertyBuilder;
use crate::pyobject::{
AttributeProtocol, DictProtocol, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObjectRef,
PyRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
#[derive(Clone, Debug)]
pub struct PyInstance;
+4 -4
View File
@@ -2,12 +2,12 @@
*/
use crate::function::IntoPyNativeFunc;
use crate::function::OptionalArg;
use crate::obj::objstr::PyStringRef;
use crate::obj::objtype::PyClassRef;
use crate::pyobject::{
IntoPyNativeFunc, OptionalArg, PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue,
};
use crate::VirtualMachine;
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyRef, PyResult, PyValue};
use crate::vm::VirtualMachine;
/// Read-only property, doesn't have __set__ or __delete__
#[derive(Debug)]
+2 -1
View File
@@ -5,8 +5,9 @@ use num_bigint::{BigInt, Sign};
use num_integer::Integer;
use num_traits::{One, Signed, ToPrimitive, Zero};
use crate::function::PyFuncArgs;
use crate::pyobject::{
PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
PyContext, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
+6 -4
View File
@@ -7,15 +7,17 @@ use std::collections::{hash_map::DefaultHasher, HashMap};
use std::fmt;
use std::hash::{Hash, Hasher};
use crate::function::PyFuncArgs;
use crate::pyobject::{
PyContext, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::{ReprGuard, VirtualMachine};
use super::objbool;
use super::objint;
use super::objiter;
use super::objstr;
use super::objtype;
use crate::pyobject::{
PyContext, PyFuncArgs, PyIteratorValue, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::{ReprGuard, VirtualMachine};
#[derive(Default)]
pub struct PySet {
+6 -5
View File
@@ -1,10 +1,11 @@
use super::objint;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
use num_bigint::BigInt;
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
use super::objint;
#[derive(Debug)]
pub struct PySlice {
// TODO: should be private
+2 -1
View File
@@ -1,4 +1,5 @@
use crate::pyobject::{AttributeProtocol, PyContext, PyFuncArgs, PyResult, TypeProtocol};
use crate::function::PyFuncArgs;
use crate::pyobject::{AttributeProtocol, PyContext, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
pub fn init(context: &PyContext) {
+3 -2
View File
@@ -6,9 +6,10 @@ use num_traits::ToPrimitive;
use unicode_segmentation::UnicodeSegmentation;
use crate::format::{FormatParseError, FormatPart, FormatString};
use crate::function::{OptionalArg, PyFuncArgs};
use crate::pyobject::{
IdProtocol, IntoPyObject, OptionalArg, PyContext, PyFuncArgs, PyIterable, PyObjectRef, PyRef,
PyResult, PyValue, TryFromObject, TypeProtocol,
IdProtocol, IntoPyObject, PyContext, PyIterable, PyObjectRef, PyRef, PyResult, PyValue,
TryFromObject, TypeProtocol,
};
use crate::vm::VirtualMachine;
+4 -2
View File
@@ -6,10 +6,12 @@ https://github.com/python/cpython/blob/50b48572d9a90c5bb36e2bef6179548ea927a35a/
*/
use super::objtype;
use crate::pyobject::{PyContext, PyFuncArgs, PyResult, TypeProtocol};
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
use super::objtype;
pub fn init(context: &PyContext) {
let super_type = &context.super_type;
+2 -2
View File
@@ -2,9 +2,9 @@ use std::cell::{Cell, RefCell};
use std::fmt;
use std::hash::{Hash, Hasher};
use crate::function::OptionalArg;
use crate::pyobject::{
IdProtocol, OptionalArg, PyContext, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult,
PyValue,
IdProtocol, PyContext, PyIteratorValue, PyObject, PyObjectRef, PyRef, PyResult, PyValue,
};
use crate::vm::{ReprGuard, VirtualMachine};
+3 -2
View File
@@ -1,9 +1,10 @@
use std::cell::RefCell;
use std::collections::HashMap;
use crate::function::PyFuncArgs;
use crate::pyobject::{
AttributeProtocol, FromPyObjectRef, IdProtocol, PyAttributes, PyContext, PyFuncArgs, PyObject,
PyObjectRef, PyRef, PyResult, PyValue, TypeProtocol,
AttributeProtocol, FromPyObjectRef, IdProtocol, PyAttributes, PyContext, PyObject, PyObjectRef,
PyRef, PyResult, PyValue, TypeProtocol,
};
use crate::vm::VirtualMachine;
+2 -3
View File
@@ -1,6 +1,5 @@
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
use super::objiter;
+3 -433
View File
@@ -2,10 +2,9 @@ use std::any::Any;
use std::cell::{Cell, RefCell};
use std::collections::HashMap;
use std::fmt;
use std::iter;
use std::marker::PhantomData;
use std::mem;
use std::ops::{Deref, RangeInclusive};
use std::ops::Deref;
use std::ptr;
use std::rc::Rc;
@@ -16,6 +15,7 @@ use num_traits::{One, Zero};
use crate::bytecode;
use crate::exceptions;
use crate::frame::{Frame, Scope};
use crate::function::{IntoPyNativeFunc, PyFuncArgs};
use crate::obj::objbool;
use crate::obj::objbuiltinfunc::PyBuiltinFunction;
use crate::obj::objbytearray;
@@ -40,6 +40,7 @@ use crate::obj::objmodule::{self, PyModule};
use crate::obj::objnone;
use crate::obj::objobject;
use crate::obj::objproperty;
use crate::obj::objproperty::PropertyBuilder;
use crate::obj::objrange;
use crate::obj::objset::{self, PySet};
use crate::obj::objslice;
@@ -975,166 +976,6 @@ impl fmt::Debug for PyObject {
}
}
/// The `PyFuncArgs` struct is one of the most used structs then creating
/// a rust function that can be called from python. It holds both positional
/// arguments, as well as keyword arguments passed to the function.
#[derive(Debug, Default, Clone)]
pub struct PyFuncArgs {
pub args: Vec<PyObjectRef>,
pub kwargs: Vec<(String, PyObjectRef)>,
}
/// Conversion from vector of python objects to function arguments.
impl From<Vec<PyObjectRef>> for PyFuncArgs {
fn from(args: Vec<PyObjectRef>) -> Self {
PyFuncArgs {
args: args,
kwargs: vec![],
}
}
}
impl From<PyObjectRef> for PyFuncArgs {
fn from(arg: PyObjectRef) -> Self {
PyFuncArgs {
args: vec![arg],
kwargs: vec![],
}
}
}
impl PyFuncArgs {
pub fn new(mut args: Vec<PyObjectRef>, kwarg_names: Vec<String>) -> PyFuncArgs {
let mut kwargs = vec![];
for name in kwarg_names.iter().rev() {
kwargs.push((name.clone(), args.pop().unwrap()));
}
PyFuncArgs { args, kwargs }
}
pub fn insert(&self, item: PyObjectRef) -> PyFuncArgs {
let mut args = PyFuncArgs {
args: self.args.clone(),
kwargs: self.kwargs.clone(),
};
args.args.insert(0, item);
args
}
pub fn shift(&mut self) -> PyObjectRef {
self.args.remove(0)
}
pub fn get_kwarg(&self, key: &str, default: PyObjectRef) -> PyObjectRef {
for (arg_name, arg_value) in self.kwargs.iter() {
if arg_name == key {
return arg_value.clone();
}
}
default.clone()
}
pub fn get_optional_kwarg(&self, key: &str) -> Option<PyObjectRef> {
for (arg_name, arg_value) in self.kwargs.iter() {
if arg_name == key {
return Some(arg_value.clone());
}
}
None
}
pub fn get_optional_kwarg_with_type(
&self,
key: &str,
ty: PyObjectRef,
vm: &mut VirtualMachine,
) -> Result<Option<PyObjectRef>, PyObjectRef> {
match self.get_optional_kwarg(key) {
Some(kwarg) => {
if objtype::isinstance(&kwarg, &ty) {
Ok(Some(kwarg))
} else {
let expected_ty_name = vm.to_pystr(&ty)?;
let actual_ty_name = vm.to_pystr(&kwarg.typ())?;
Err(vm.new_type_error(format!(
"argument of type {} is required for named parameter `{}` (got: {})",
expected_ty_name, key, actual_ty_name
)))
}
}
None => Ok(None),
}
}
/// Serializes these arguments into an iterator starting with the positional
/// arguments followed by keyword arguments.
fn into_iter(self) -> impl Iterator<Item = PyArg> {
self.args.into_iter().map(PyArg::Positional).chain(
self.kwargs
.into_iter()
.map(|(name, value)| PyArg::Keyword(name, value)),
)
}
/// Binds these arguments to their respective values.
///
/// If there is an insufficient number of arguments, there are leftover
/// arguments after performing the binding, or if an argument is not of
/// the expected type, a TypeError is raised.
///
/// If the given `FromArgs` includes any conversions, exceptions raised
/// during the conversion will halt the binding and return the error.
fn bind<T: FromArgs>(self, vm: &mut VirtualMachine) -> PyResult<T> {
let given_args = self.args.len();
let mut args = self.into_iter().peekable();
let bound = match T::from_args(vm, &mut args) {
Ok(args) => args,
Err(ArgumentError::TooFewArgs) => {
return Err(vm.new_type_error(format!(
"Expected at least {} arguments ({} given)",
T::arity().start(),
given_args,
)));
}
Err(ArgumentError::Exception(ex)) => {
return Err(ex);
}
};
match args.next() {
None => Ok(bound),
Some(PyArg::Positional(_)) => Err(vm.new_type_error(format!(
"Expected at most {} arguments ({} given)",
T::arity().end(),
given_args,
))),
Some(PyArg::Keyword(name, _)) => {
Err(vm.new_type_error(format!("Unexpected keyword argument {}", name)))
}
}
}
}
/// Implemented by any type that can be accepted as a parameter to a built-in
/// function.
///
pub trait FromArgs: Sized {
/// The range of positional arguments permitted by the function signature.
///
/// Returns an empty range if not applicable.
fn arity() -> RangeInclusive<usize> {
0..=0
}
/// Extracts this item from the next argument(s).
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>;
}
/// An iterable Python object.
///
/// `PyIterable` implements `FromArgs` so that a built-in function can accept
@@ -1224,151 +1065,6 @@ impl<T: TryFromObject> TryFromObject for Option<T> {
}
}
/// A map of keyword arguments to their values.
///
/// A built-in function with a `KwArgs` parameter is analagous to a Python
/// function with `*kwargs`. All remaining keyword arguments are extracted
/// (and hence the function will permit an arbitrary number of them).
///
/// `KwArgs` optionally accepts a generic type parameter to allow type checks
/// or conversions of each argument.
pub struct KwArgs<T = PyObjectRef>(HashMap<String, T>);
impl<T> FromArgs for KwArgs<T>
where
T: TryFromObject,
{
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>,
{
let mut kwargs = HashMap::new();
while let Some(PyArg::Keyword(name, value)) = args.next() {
kwargs.insert(name, T::try_from_object(vm, value)?);
}
Ok(KwArgs(kwargs))
}
}
/// A list of positional argument values.
///
/// A built-in function with a `Args` parameter is analagous to a Python
/// function with `*args`. All remaining positional arguments are extracted
/// (and hence the function will permit an arbitrary number of them).
///
/// `Args` optionally accepts a generic type parameter to allow type checks
/// or conversions of each argument.
pub struct Args<T>(Vec<T>);
impl<T> FromArgs for Args<T>
where
T: TryFromObject,
{
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>,
{
let mut varargs = Vec::new();
while let Some(PyArg::Positional(value)) = args.next() {
varargs.push(T::try_from_object(vm, value)?);
}
Ok(Args(varargs))
}
}
impl<T> FromArgs for T
where
T: TryFromObject,
{
fn arity() -> RangeInclusive<usize> {
1..=1
}
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>,
{
if let Some(PyArg::Positional(value)) = args.next() {
Ok(T::try_from_object(vm, value)?)
} else {
Err(ArgumentError::TooFewArgs)
}
}
}
/// An argument that may or may not be provided by the caller.
///
/// This style of argument is not possible in pure Python.
pub enum OptionalArg<T> {
Present(T),
Missing,
}
use self::OptionalArg::*;
use crate::obj::objproperty::PropertyBuilder;
impl<T> OptionalArg<T> {
pub fn into_option(self) -> Option<T> {
match self {
Present(value) => Some(value),
Missing => None,
}
}
}
impl<T> FromArgs for OptionalArg<T>
where
T: TryFromObject,
{
fn arity() -> RangeInclusive<usize> {
0..=1
}
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>,
{
Ok(if let Some(PyArg::Positional(_)) = args.peek() {
let value = if let Some(PyArg::Positional(value)) = args.next() {
value
} else {
unreachable!()
};
Present(T::try_from_object(vm, value)?)
} else {
Missing
})
}
}
pub enum PyArg {
Positional(PyObjectRef),
Keyword(String, PyObjectRef),
}
pub enum ArgumentError {
TooFewArgs,
Exception(PyObjectRef),
}
impl From<PyObjectRef> for ArgumentError {
fn from(ex: PyObjectRef) -> Self {
ArgumentError::Exception(ex)
}
}
/// Implemented by any type that can be created from a Python object.
///
/// Any type that implements `TryFromObject` is automatically `FromArgs`, and
@@ -1413,132 +1109,6 @@ where
}
}
// For functions that accept no arguments. Implemented explicitly instead of via
// macro below to avoid unused warnings.
impl FromArgs for () {
fn from_args<I>(
_vm: &mut VirtualMachine,
_args: &mut iter::Peekable<I>,
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>,
{
Ok(())
}
}
// A tuple of types that each implement `FromArgs` represents a sequence of
// arguments that can be bound and passed to a built-in function.
//
// Technically, a tuple can contain tuples, which can contain tuples, and so on,
// so this actually represents a tree of values to be bound from arguments, but
// in practice this is only used for the top-level parameters.
macro_rules! tuple_from_py_func_args {
($($T:ident),+) => {
impl<$($T),+> FromArgs for ($($T,)+)
where
$($T: FromArgs),+
{
fn arity() -> RangeInclusive<usize> {
let mut min = 0;
let mut max = 0;
$(
let (start, end) = $T::arity().into_inner();
min += start;
max += end;
)+
min..=max
}
fn from_args<I>(
vm: &mut VirtualMachine,
args: &mut iter::Peekable<I>
) -> Result<Self, ArgumentError>
where
I: Iterator<Item = PyArg>
{
Ok(($($T::from_args(vm, args)?,)+))
}
}
};
}
// Implement `FromArgs` for up to 5-tuples, allowing built-in functions to bind
// up to 5 top-level parameters (note that `Args`, `KwArgs`, nested tuples, etc.
// count as 1, so this should actually be more than enough).
tuple_from_py_func_args!(A);
tuple_from_py_func_args!(A, B);
tuple_from_py_func_args!(A, B, C);
tuple_from_py_func_args!(A, B, C, D);
tuple_from_py_func_args!(A, B, C, D, E);
/// A built-in Python function.
pub type PyNativeFunc = Box<dyn Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult + 'static>;
/// Implemented by types that are or can generate built-in functions.
///
/// For example, any function that:
///
/// - Accepts a sequence of types that implement `FromArgs`, followed by a
/// `&mut VirtualMachine`
/// - Returns some type that implements `IntoPyObject`
///
/// will generate a `PyNativeFunc` that performs the appropriate type and arity
/// checking, any requested conversions, and then if successful call the function
/// with the bound values.
///
/// A bare `PyNativeFunc` also implements this trait, allowing the above to be
/// done manually, for rare situations that don't fit into this model.
pub trait IntoPyNativeFunc<T, R> {
fn into_func(self) -> PyNativeFunc;
}
impl<F> IntoPyNativeFunc<PyFuncArgs, PyResult> for F
where
F: Fn(&mut VirtualMachine, PyFuncArgs) -> PyResult + 'static,
{
fn into_func(self) -> PyNativeFunc {
Box::new(self)
}
}
impl IntoPyNativeFunc<PyFuncArgs, PyResult> for PyNativeFunc {
fn into_func(self) -> PyNativeFunc {
self
}
}
// This is the "magic" that allows rust functions of varying signatures to
// generate native python functions.
//
// Note that this could be done without a macro - it is simply to avoid repetition.
macro_rules! into_py_native_func_tuple {
($(($n:tt, $T:ident)),*) => {
impl<F, $($T,)* R> IntoPyNativeFunc<($($T,)*), R> for F
where
F: Fn($($T,)* &mut VirtualMachine) -> R + 'static,
$($T: FromArgs,)*
($($T,)*): FromArgs,
R: IntoPyObject,
{
fn into_func(self) -> PyNativeFunc {
Box::new(move |vm, args| {
let ($($n,)*) = args.bind::<($($T,)*)>(vm)?;
(self)($($n,)* vm).into_pyobject(vm)
})
}
}
};
}
into_py_native_func_tuple!();
into_py_native_func_tuple!((a, A));
into_py_native_func_tuple!((a, A), (b, B));
into_py_native_func_tuple!((a, A), (b, B), (c, C));
into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D));
into_py_native_func_tuple!((a, A), (b, B), (c, C), (d, D), (e, E));
// TODO: This is a workaround and shouldn't exist.
// Each iterable type should have its own distinct iterator type.
#[derive(Debug)]
+9 -7
View File
@@ -3,15 +3,17 @@
//! This module makes use of the parser logic, and translates all ast nodes
//! into python ast.AST objects.
extern crate rustpython_parser;
use self::rustpython_parser::{ast, parser};
use crate::obj::objstr;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::VirtualMachine;
use num_complex::Complex64;
use std::ops::Deref;
use num_complex::Complex64;
use rustpython_parser::{ast, parser};
use crate::function::PyFuncArgs;
use crate::obj::objstr;
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
/*
* Idea: maybe we can create a sort of struct with some helper functions?
struct AstToPyAst {
+2 -1
View File
@@ -1,5 +1,6 @@
use crate::function::PyFuncArgs;
use crate::obj::objcode;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
fn dis_dis(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
+3 -7
View File
@@ -2,29 +2,25 @@
* I/O core tools.
*/
//library imports
use std::collections::HashSet;
use std::fs::File;
use std::io::prelude::*;
use std::io::BufReader;
use std::path::PathBuf;
//3rd party imports
use num_bigint::ToBigInt;
use num_traits::ToPrimitive;
//custom imports
use super::os;
use crate::function::PyFuncArgs;
use crate::import;
use crate::obj::objbytearray::PyByteArray;
use crate::obj::objbytes;
use crate::obj::objint;
use crate::obj::objstr;
use crate::pyobject::{
AttributeProtocol, BufferProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol,
AttributeProtocol, BufferProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol,
};
use crate::import;
use crate::vm::VirtualMachine;
fn compute_c_flag(mode: &str) -> u16 {
+2 -2
View File
@@ -5,14 +5,14 @@ use serde::de::{DeserializeSeed, Visitor};
use serde::ser::{SerializeMap, SerializeSeq};
use serde_json;
use crate::function::PyFuncArgs;
use crate::obj::{
objbool, objdict, objfloat, objint, objsequence,
objstr::{self, PyString},
objtype,
};
use crate::pyobject::{
create_type, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult,
TypeProtocol,
create_type, DictProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol,
};
use crate::VirtualMachine;
use num_traits::cast::ToPrimitive;
+5 -4
View File
@@ -2,11 +2,12 @@
* Testing if a string is a keyword.
*/
extern crate rustpython_parser;
use self::rustpython_parser::lexer;
use rustpython_parser::lexer;
use crate::function::PyFuncArgs;
use crate::obj::objstr;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::VirtualMachine;
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
fn keyword_iskeyword(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(s, Some(vm.ctx.str_type()))]);
+5 -4
View File
@@ -3,12 +3,13 @@
*
*/
use crate::obj::objfloat;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::VirtualMachine;
use statrs::function::erf::{erf, erfc};
use statrs::function::gamma::{gamma, ln_gamma};
use std;
use crate::function::PyFuncArgs;
use crate::obj::objfloat;
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
// Helper macro:
macro_rules! make_math_func {
+2 -7
View File
@@ -1,18 +1,13 @@
//library imports
use std::fs::File;
use std::fs::OpenOptions;
use std::io::ErrorKind;
// use std::env;
//3rd party imports
use num_traits::cast::ToPrimitive;
//custom imports
use crate::function::PyFuncArgs;
use crate::obj::objint;
use crate::obj::objstr;
// use crate::obj::objdict;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
#[cfg(unix)]
+3 -4
View File
@@ -1,7 +1,6 @@
extern crate rustc_version_runtime;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult};
use crate::VirtualMachine;
use crate::function::PyFuncArgs;
use crate::pyobject::{PyContext, PyObjectRef, PyResult};
use crate::vm::VirtualMachine;
pub fn make_module(ctx: &PyContext) -> PyObjectRef {
py_module!(ctx, "platform", {
+7 -6
View File
@@ -7,15 +7,16 @@
* https://docs.rs/byteorder/1.2.6/byteorder/
*/
extern crate byteorder;
use self::byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use std::io::{Cursor, Read, Write};
use crate::obj::{objbool, objbytes, objfloat, objint, objstr, objtype};
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::VirtualMachine;
use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt};
use num_bigint::BigInt;
use num_traits::ToPrimitive;
use std::io::{Cursor, Read, Write};
use crate::function::PyFuncArgs;
use crate::obj::{objbool, objbytes, objfloat, objint, objstr, objtype};
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::VirtualMachine;
#[derive(Debug)]
struct FormatCode {
+4 -4
View File
@@ -1,11 +1,11 @@
//! Random module.
extern crate rand;
use rand::distributions::{Distribution, Normal};
use crate::function::PyFuncArgs;
use crate::obj::objfloat;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::stdlib::random::rand::distributions::{Distribution, Normal};
use crate::VirtualMachine;
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
pub fn make_module(ctx: &PyContext) -> PyObjectRef {
py_module!(ctx, "random", {
+3 -3
View File
@@ -9,13 +9,13 @@ use std::path::PathBuf;
use regex::{Match, Regex};
use crate::function::PyFuncArgs;
use crate::import;
use crate::obj::objstr;
use crate::pyobject::{
AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue,
TypeProtocol,
AttributeProtocol, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::VirtualMachine;
use crate::vm::VirtualMachine;
impl PyValue for Regex {
fn class(vm: &mut VirtualMachine) -> PyObjectRef {
+2 -3
View File
@@ -5,13 +5,12 @@ use std::io::Write;
use std::net::{SocketAddr, TcpListener, TcpStream, ToSocketAddrs, UdpSocket};
use std::ops::Deref;
use crate::function::PyFuncArgs;
use crate::obj::objbytes;
use crate::obj::objint;
use crate::obj::objsequence::get_elements;
use crate::obj::objstr;
use crate::pyobject::{
PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use crate::pyobject::{PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol};
use crate::vm::VirtualMachine;
use num_traits::ToPrimitive;
+5 -3
View File
@@ -1,11 +1,13 @@
//! The python `time` module.
use crate::obj::objfloat;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::VirtualMachine;
use std::thread;
use std::time::{Duration, SystemTime, UNIX_EPOCH};
use crate::function::PyFuncArgs;
use crate::obj::objfloat;
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
fn time_sleep(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(seconds, Some(vm.ctx.float_type()))]);
let seconds = objfloat::get_value(seconds);
+4 -4
View File
@@ -2,14 +2,14 @@
* python tokenize module.
*/
extern crate rustpython_parser;
use std::iter::FromIterator;
use self::rustpython_parser::lexer;
use rustpython_parser::lexer;
use crate::function::PyFuncArgs;
use crate::obj::objstr;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::VirtualMachine;
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
fn tokenize_tokenize(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
arg_check!(vm, args, required = [(readline, Some(vm.ctx.str_type()))]);
+2 -1
View File
@@ -2,8 +2,9 @@
* Dynamic type creation and names for built in types.
*/
use crate::function::PyFuncArgs;
use crate::obj::objtype;
use crate::pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::pyobject::{PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::VirtualMachine;
fn types_new_class(vm: &mut VirtualMachine, args: PyFuncArgs) -> PyResult {
+7 -4
View File
@@ -1,10 +1,13 @@
use crate::obj::objint;
use crate::pyobject::{DictProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
use num_traits::ToPrimitive;
use std::rc::Rc;
use std::{env, mem};
use num_traits::ToPrimitive;
use crate::function::PyFuncArgs;
use crate::obj::objint;
use crate::pyobject::{DictProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol};
use crate::vm::VirtualMachine;
/*
* The magic sys module.
*/
+2 -2
View File
@@ -14,6 +14,7 @@ use std::sync::{Mutex, MutexGuard};
use crate::builtins;
use crate::bytecode;
use crate::frame::{ExecutionResult, Frame, Scope};
use crate::function::PyFuncArgs;
use crate::obj::objbool;
use crate::obj::objbuiltinfunc::PyBuiltinFunction;
use crate::obj::objcode;
@@ -27,8 +28,7 @@ use crate::obj::objstr;
use crate::obj::objtuple::PyTuple;
use crate::obj::objtype;
use crate::pyobject::{
AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyFuncArgs, PyObjectRef, PyResult,
TypeProtocol,
AttributeProtocol, DictProtocol, IdProtocol, PyContext, PyObjectRef, PyResult, TypeProtocol,
};
use crate::stdlib;
use crate::sysmodule;
+12 -7
View File
@@ -1,16 +1,21 @@
use crate::{convert, vm_class::AccessibleVM, wasm_builtins::window};
use std::path::PathBuf;
use futures::Future;
use js_sys::Promise;
use num_traits::cast::ToPrimitive;
use wasm_bindgen::prelude::*;
use wasm_bindgen::JsCast;
use wasm_bindgen_futures::{future_to_promise, JsFuture};
use rustpython_vm::function::PyFuncArgs;
use rustpython_vm::import::import_module;
use rustpython_vm::obj::{objint, objstr};
use rustpython_vm::pyobject::{
AttributeProtocol, PyContext, PyFuncArgs, PyObject, PyObjectRef, PyResult, PyValue,
TypeProtocol,
AttributeProtocol, PyContext, PyObject, PyObjectRef, PyResult, PyValue, TypeProtocol,
};
use rustpython_vm::{import::import_module, VirtualMachine};
use std::path::PathBuf;
use wasm_bindgen::{prelude::*, JsCast};
use wasm_bindgen_futures::{future_to_promise, JsFuture};
use rustpython_vm::VirtualMachine;
use crate::{convert, vm_class::AccessibleVM, wasm_builtins::window};
enum FetchResponseFormat {
Json,
+11 -10
View File
@@ -1,14 +1,15 @@
use crate::browser_module;
use crate::vm_class::{AccessibleVM, WASMVirtualMachine};
use js_sys::{Array, ArrayBuffer, Object, Promise, Reflect, Uint8Array};
use num_traits::cast::ToPrimitive;
use rustpython_vm::obj::{objbytes, objint, objsequence, objtype};
use rustpython_vm::pyobject::{
self, AttributeProtocol, DictProtocol, PyFuncArgs, PyObjectRef, PyResult,
};
use rustpython_vm::VirtualMachine;
use wasm_bindgen::{closure::Closure, prelude::*, JsCast};
use rustpython_vm::function::PyFuncArgs;
use rustpython_vm::obj::{objbytes, objint, objsequence, objtype};
use rustpython_vm::pyobject::{AttributeProtocol, DictProtocol, PyObjectRef, PyResult};
use rustpython_vm::VirtualMachine;
use crate::browser_module;
use crate::vm_class::{AccessibleVM, WASMVirtualMachine};
pub fn py_err_to_js_err(vm: &mut VirtualMachine, py_err: &PyObjectRef) -> JsValue {
macro_rules! map_exceptions {
($py_exc:ident, $msg:expr, { $($py_exc_ty:expr => $js_err_new:expr),*$(,)? }) => {
@@ -83,7 +84,7 @@ pub fn py_to_js(vm: &mut VirtualMachine, py_obj: PyObjectRef) -> JsValue {
let vm = &mut acc_vm
.upgrade()
.expect("acc. VM to be invalid when WASM vm is valid");
let mut py_func_args = rustpython_vm::pyobject::PyFuncArgs::default();
let mut py_func_args = PyFuncArgs::default();
if let Some(ref args) = args {
for arg in args.values() {
py_func_args.args.push(js_to_py(vm, arg?));
@@ -132,7 +133,7 @@ pub fn py_to_js(vm: &mut VirtualMachine, py_obj: PyObjectRef) -> JsValue {
.expect("Couldn't get json module")
.get_attr("dumps".into())
.expect("Couldn't get json dumps");
match vm.invoke(dumps, pyobject::PyFuncArgs::new(vec![py_obj], vec![])) {
match vm.invoke(dumps, PyFuncArgs::new(vec![py_obj], vec![])) {
Ok(value) => {
let json = vm.to_pystr(&value).unwrap();
js_sys::JSON::parse(&json).unwrap_or(JsValue::UNDEFINED)
@@ -239,7 +240,7 @@ pub fn js_to_py(vm: &mut VirtualMachine, js_val: JsValue) -> PyObjectRef {
};
let py_json = vm.new_str(json);
vm.invoke(loads, pyobject::PyFuncArgs::new(vec![py_json], vec![]))
vm.invoke(loads, PyFuncArgs::new(vec![py_json], vec![]))
// can safely unwrap because we know it's valid JSON
.unwrap()
}
+12 -10
View File
@@ -1,18 +1,20 @@
use crate::browser_module::setup_browser_module;
use crate::convert;
use crate::wasm_builtins;
use js_sys::{Object, Reflect, SyntaxError, TypeError};
use rustpython_vm::{
compile,
frame::{NameProtocol, Scope},
pyobject::{PyContext, PyFuncArgs, PyObjectRef, PyResult},
VirtualMachine,
};
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::{Rc, Weak};
use js_sys::{Object, Reflect, SyntaxError, TypeError};
use wasm_bindgen::{prelude::*, JsCast};
use rustpython_vm::compile;
use rustpython_vm::frame::{NameProtocol, Scope};
use rustpython_vm::function::PyFuncArgs;
use rustpython_vm::pyobject::{PyContext, PyObjectRef, PyResult};
use rustpython_vm::VirtualMachine;
use crate::browser_module::setup_browser_module;
use crate::convert;
use crate::wasm_builtins;
pub trait HeldRcInner {}
impl<T> HeldRcInner for T {}
+5 -3
View File
@@ -5,11 +5,13 @@
//! Implements functions listed here: https://docs.python.org/3/library/builtins.html.
use js_sys::{self, Array};
use rustpython_vm::obj::{objstr, objtype};
use rustpython_vm::pyobject::{IdProtocol, PyFuncArgs, PyObjectRef, PyResult, TypeProtocol};
use rustpython_vm::VirtualMachine;
use web_sys::{self, console};
use rustpython_vm::function::PyFuncArgs;
use rustpython_vm::obj::{objstr, objtype};
use rustpython_vm::pyobject::{IdProtocol, PyObjectRef, PyResult, TypeProtocol};
use rustpython_vm::VirtualMachine;
pub(crate) fn window() -> web_sys::Window {
web_sys::window().expect("Window to be available")
}