-
Notifications
You must be signed in to change notification settings - Fork 1.3k
Fix itertools.count to take PyNumber instead of PyInt #3822
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Conversation
vm/src/stdlib/itertools.rs
Outdated
#[pyarg(positional, optional)] | ||
start: OptionalArg<PyIntRef>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
#[pyarg]
and OptinoalArg
is not expected to be removed.
(See the test results how this change broke tests)
Use OptionalArg<PyObjectRef>
vm/src/stdlib/itertools.rs
Outdated
if let Some(step) = &zelf.step { | ||
*cur = vm._iadd(&*cur, step.as_object())?; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doesn't 1
have to be added when step is None
?
vm/src/stdlib/itertools.rs
Outdated
stdlib::sys, | ||
types::{Constructor, IterNext, IterNextIterable}, | ||
AsObject, Py, PyObjectRef, PyPayload, PyRef, PyResult, PyWeakRef, VirtualMachine, | ||
}; | ||
use crossbeam_utils::atomic::AtomicCell; | ||
use num_bigint::BigInt; | ||
use num_traits::{One, Signed, ToPrimitive, Zero}; | ||
// use num_bigint::BigInt; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
// use num_bigint::BigInt; |
vm/src/stdlib/itertools.rs
Outdated
cur: PyRwLock<BigInt>, | ||
step: BigInt, | ||
cur: PyRwLock<PyObjectRef>, | ||
step: Option<PyIntRef>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can I ask you is there any reason for making step
as Option
?
And It seems step
also need to be checked via PyNumber::check
in cpython which means that any type that implements number protocol
can be fitted.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
step: Option<PyIntRef>, | |
step: PyObjectRef, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because step is an optional value as the second argument of count, set it as Option.
And when processing, there is something similar to repeat, so I considered it.
But if I need to set it up differently, I will.
I checked all reviews. thank. I'll fix.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What's different between saving it as a PyIntRef
and Option<PyIntRef>
?
e.g. Does it affect to repr
result? If they act same for everything, we don't need to distinguish them.
vm/src/stdlib/itertools.rs
Outdated
let start = match start.into_option() { | ||
Some(int) => int.as_bigint().clone(), | ||
None => BigInt::zero(), | ||
Some(num) => vm.new_pyobj(num), | ||
None => vm.new_pyobj(0), | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let start: PyObjectRef = start.into_option().unwrap_or_else(|| vm.new_pyobj(0));
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I tried but got an error
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sorry. I was wrong. I'll fix it. Thanks for the suggestion.
vm/src/stdlib/itertools.rs
Outdated
let step = match step.into_option() { | ||
Some(int) => int.as_bigint().clone(), | ||
None => BigInt::one(), | ||
Some(int) => { | ||
let val: isize = int.try_to_primitive(vm)?; | ||
Some(vm.new_pyref(val.to_usize().unwrap_or(0))) | ||
} | ||
None => None, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
let step: PyObjectRef = step.into_option().unwrap_or_else(|| vm.new_pyobj(1));
}; | ||
if !PyNumber::check(&start, vm) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if !PyNumber::check(&start, vm) { | |
if !PyNumber::check(&start, vm) || !PyNumber::check(&step, vm) { |
It seems step
also need to be checked via PyNumber::check
.
https://github.com/python/cpython/blob/3.10/Modules/itertoolsmodule.c#L4178-L4182
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I didn't because it's a PyIntRef. I'll fix it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PyIntRef is always a PyNumber.
vm/src/stdlib/itertools.rs
Outdated
if let Some(step) = &zelf.step { | ||
*cur = vm._iadd(&*cur, step.as_object())?; | ||
} else { | ||
let one = vm.new_pyobj(1); | ||
*cur = vm._add(&*cur, &one)?; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if let Some(step) = &zelf.step { | |
*cur = vm._iadd(&*cur, step.as_object())?; | |
} else { | |
let one = vm.new_pyobj(1); | |
*cur = vm._add(&*cur, &one)?; | |
} | |
*cur = vm._add(&*cur, &zelf.step)?; |
If you have interest, this line could be replaced with PyNumber::add
which is not yet implemented in rustpython
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
that will not be easy before #3819
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I feel like iadd
fits better.
if let Some(step) = &zelf.step { | |
*cur = vm._iadd(&*cur, step.as_object())?; | |
} else { | |
let one = vm.new_pyobj(1); | |
*cur = vm._add(&*cur, &one)?; | |
} | |
vm._iadd(&*cur, step.as_object())?; |
let result = cur.clone(); | ||
*cur += &zelf.step; | ||
*cur = vm._iadd(&*cur, step.as_object())?; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is iadd
intended to be used with return value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh, it does. I didn't know that.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Looks good, thank you for contributing!
No description provided.