Skip to content
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

Make more constructors return &PyX instead of Py<PyX> #446

Merged
merged 1 commit into from
May 6, 2019

Conversation

birkenfeld
Copy link
Member

fixes #405

Remaining one is PyTuple, where I'm running into a test failure. Will provide as a separate PR.

@birkenfeld
Copy link
Member Author

Missing changelog entry; I'd like to combine this with the one for PySet when both are merged.

@konstin
Copy link
Member

konstin commented Apr 18, 2019

CC @pganssle for the datetime constructors

@pganssle
Copy link
Member

The datetime constructors broke a bunch of tests. I have a half-completed branch somewhere that fixes the tests, but IIRC it was semi-blocked on #392.

@birkenfeld If you don't want to be bothered with fixing the datetime changes, I can handle them later.

@birkenfeld
Copy link
Member Author

@pganssle I've found them now 😄

Do you know how to change the utcoffset method? Trying to make it return PyResult<&'p PyDelta> makes the proc-macro complain:

190 | #[pymethods]
    | ^^^^^^^^^^^^
    |
    = help: message: python method can not be generic: Ident { ident: "utcoffset", span: #0 bytes(4224..4233) }

The pyfunctions seem to be fine with it. Although, trying to import that module makes python3 segfault...

@kngwyu
Copy link
Member

kngwyu commented Apr 19, 2019

Do you know how to change the utcoffset method? Trying to make it return PyResult<&'p PyDelta> makes the proc-macro complain

Changing it to return Py<PyDelta> works but I think it's better to separate datetime fixes into an other PR.

@birkenfeld
Copy link
Member Author

Sorry, can you be more specific what you want to separate? Without the datetime changes there isn't much left here...

@birkenfeld
Copy link
Member Author

Also it's unclear to me how to get the Py from the reference 😄

@kngwyu
Copy link
Member

kngwyu commented Apr 22, 2019

Without the datetime changes there isn't much left here...

Yeah but there's many examples for datetime module and I thought it's tough stuff to fix all of them.
But spending after some time fixing this, I found it not too much difficult.

Also it's unclear to me how to get the Py from the reference

use pyo3::AsPyPointer;
#[pyfunction]
fn make_date(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult<Py<PyDate>> {
    PyDate::new(py, year, month, day).map(|d| unsafe { Py::from_borrowed_ptr(d.as_ptr()) })
}

This works but maybe we need an easier way.

@birkenfeld
Copy link
Member Author

use pyo3::AsPyPointer;
#[pyfunction]
fn make_date(py: Python<'_>, year: i32, month: u8, day: u8) -> PyResult<Py<PyDate>> {
    PyDate::new(py, year, month, day).map(|d| unsafe { Py::from_borrowed_ptr(d.as_ptr()) })
}

This works but maybe we need an easier way.

Uh oh. Should unsafe really be required here?

@konstin
Copy link
Member

konstin commented Apr 23, 2019

I think we need a generic impl of that snippet:

pyo3/src/types/tuple.rs

Lines 137 to 141 in 874d8a0

impl<'a> FromPy<&'a PyTuple> for Py<PyTuple> {
fn from_py(tuple: &'a PyTuple, _py: Python) -> Py<PyTuple> {
unsafe { Py::from_borrowed_ptr(tuple.as_ptr()) }
}
}

This would also avoid unsafe in downstream code

@konstin
Copy link
Member

konstin commented Apr 23, 2019

This seems to work:

impl<'a, T: AsPyPointer> FromPy<&'a T> for Py<T> {
    fn from_py(tuple: &'a T, _py: Python) -> Py<T> {
        unsafe { Py::from_borrowed_ptr(tuple.as_ptr()) }
    }
}

Might be good idea to investigate this for soundness and make another pull request of that.

@kngwyu
Copy link
Member

kngwyu commented Apr 23, 2019

@konstin
Yeah I agree.

I noticed we can return PyResult<&T> for some pyfunctions in the datetime example.
E.g.,

#[pyfunction]
fn make_date(py: Python, year: i32, month: u8, day: u8) -> PyResult<&PyDate> {
    PyDate::new(py, year, month, day)
}

But when we have &PyTzInfo as an argument, it doesn't work for the lifetime reason. We have to return Py<T> in datetime_from_timestamp and make_datetime.

#[pyfunction]
fn datetime_from_timestamp(py: Python, ts: f64, tz: Option<&PyTzInfo>) -> PyResult<&PyDateTime> {
    PyDateTime::from_timestamp(py, ts, tz)
}

I think this can be resolved by hacking proc-macro codes, but not sure.

@pganssle
Copy link
Member

pganssle commented Apr 23, 2019

@kngwyu Why can't we use:

fn datetime_from_timestamp(py: Python<'p>,
                           ts: f64, tz: Option<&'p PyTzInfo>)
                        -> PyResult<&'p PyDateTime> {

The PyTzInfo just has to live as long as the PyDateTime or longer, so the annotation seems correct.

@kngwyu
Copy link
Member

kngwyu commented Apr 23, 2019

@pganssle
We can't use the lifetime specifier py there. It's the limitation of our proc macro codes.
So the compiler can't know python and tz has the same lifetime.

@kngwyu
Copy link
Member

kngwyu commented Apr 24, 2019

@pganssle
Hoops, sorry I noticed this works.

#[pyfunction]
fn datetime_from_timestamp<'py>(
    py: Python<'py>,
    ts: f64,
    tz: Option<&'py PyTzInfo>,
) -> PyResult<&'py PyDateTime> {
    PyDateTime::from_timestamp(py, ts, tz)
}

But now methods can't take lifetime specifiers so we can't compile

    fn utcoffset<'py>(&self, py: Python<'py>, _dt: &'py PyDateTime) -> PyResult<&'py PyDelta> {
        PyDelta::new(py, 0, 3600, 0, true)
    }

Edited
#461 make it possible to compile pymethods with lifetime specifiers

@codecov
Copy link

codecov bot commented May 6, 2019

Codecov Report

Merging #446 into master will decrease coverage by 0.1%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #446      +/-   ##
==========================================
- Coverage   87.87%   87.76%   -0.11%     
==========================================
  Files          65       65              
  Lines        3398     3393       -5     
==========================================
- Hits         2986     2978       -8     
- Misses        412      415       +3
Impacted Files Coverage Δ
src/types/string.rs 89.83% <100%> (ø) ⬆️
src/types/floatob.rs 95.23% <100%> (ø) ⬆️
src/types/datetime.rs 100% <100%> (ø) ⬆️
src/err.rs 61.21% <0%> (-1.22%) ⬇️
src/buffer.rs 69.9% <0%> (-0.49%) ⬇️
src/instance.rs 96.73% <0%> (-0.11%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 74600f5...cdabf9e. Read the comment docs.

@codecov
Copy link

codecov bot commented May 6, 2019

Codecov Report

Merging #446 into master will decrease coverage by 0.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #446      +/-   ##
==========================================
- Coverage   87.87%   87.85%   -0.02%     
==========================================
  Files          65       65              
  Lines        3398     3393       -5     
==========================================
- Hits         2986     2981       -5     
  Misses        412      412
Impacted Files Coverage Δ
src/types/string.rs 89.83% <100%> (ø) ⬆️
src/types/floatob.rs 95.23% <100%> (ø) ⬆️
src/types/datetime.rs 100% <100%> (ø) ⬆️
src/instance.rs 96.73% <0%> (-0.11%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 74600f5...cdabf9e. Read the comment docs.

@birkenfeld
Copy link
Member Author

Whoops, rustfmt fixed.

@konstin
Copy link
Member

konstin commented May 6, 2019

Thank you!

@konstin konstin merged commit 71b635e into PyO3:master May 6, 2019
@birkenfeld birkenfeld deleted the other_new branch March 13, 2020 05:51
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Safe datetime constructors should return PyErr<&T>
4 participants