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 GILOnceCell::get_or_try_init_type_ref public #4542

Merged
merged 5 commits into from
Sep 21, 2024

Conversation

glevco
Copy link
Contributor

@glevco glevco commented Sep 10, 2024

Resolves #4516.

  • Change GILOnceCell::get_or_try_init_type_ref to GILOnceCell::import and make it public API, adding an example for it.
  • Update "Executing existing Python code" section of the guide:
    • Add mention to GILOnceCell::import.
    • Change Python::eval_bound (which is deprecated) to Python::eval.
    • Change Python::run_bound (which is deprecated) to Python::run, also adding missing link.

Copy link
Member

@mejrs mejrs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change PyModule::import suggestion to Python::import instead

Why? I don't have a strong opinion either way, but slightly prefer PyModule::import.

src/sync.rs Outdated
/// # });
/// ```
///
pub fn get_or_try_init_type_ref<'py>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This can use a better name. Maybe just "import"? 🤔

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree, but then maybe it should be implemented for GILOnceCell<Py<T>> where T: PyTypeInfo instead of GILOnceCell<Py<PyType>>? Otherwise, I would call it import_type.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd be fine with that. I think you want T: PyTypeCheck rather than T: PyTypeInfo, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Right, done in 79568f6!

@glevco
Copy link
Contributor Author

glevco commented Sep 11, 2024

@mejrs

Why? I don't have a strong opinion either way, but slightly prefer PyModule::import.

Since Python::import was used in the implementation of get_or_try_init_type_ref, I assumed it was preferable. Also, it pairs nicely with the other entries in this section of the guide, as they recommend other "global" functions such as Python::eval and Python::run. What do you think?

@davidhewitt
Copy link
Member

I prefer PyModule::import too, I think it's nicer to think of that as a "constructor" for the PyModule type.

@mejrs
Copy link
Member

mejrs commented Sep 14, 2024

What do you think?

From a documentation perspective I would prefer that people visit PyModule::import over Python::import. Python has a lot of not module related api, and its page is a lot bigger.

Also, using "constructor" syntax also makes it clear that when they use it, they're getting a module (rather than something arbitrary like from foo import bar might do).

@glevco
Copy link
Contributor Author

glevco commented Sep 14, 2024

@davidhewitt @mejrs Fair enough, I reverted the guide back to PyModule::import in 79568f6. I also changed the method name to GILOnceCell::import and made its impl generic for PyTypeCheck, as discussed above. I updated the PR description accordingly.

Copy link
Member

@mejrs mejrs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry for the late review. I have a couple of nits about the documentation.

src/sync.rs Outdated
impl<T> GILOnceCell<Py<T>>
where
T: PyTypeCheck,
{
/// Get a reference to the contained Python type, initializing it if needed.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just to clarify that "it" refers to the GILOnceCell, not the class in it

Suggested change
/// Get a reference to the contained Python type, initializing it if needed.
/// Get a reference to the contained Python type, initializing the cell if needed.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done! bcb883c

Comment on lines 26 to 29
[`PyModule::import`] introduces an overhead each time it's called. To avoid this in functions that are called multiple times,
using a [`GILOnceCell`]({{#PYO3_DOCS_URL}}/pyo3/sync/struct.GILOnceCell.html) is recommended. Specifically, for importing types,
[`GILOnceCell::import`]({{#PYO3_DOCS_URL}}/pyo3/sync/struct.GILOnceCell.html#method.import) is provided
(check out the [example]({{#PYO3_DOCS_URL}}/pyo3/sync/struct.GILOnceCell.html#example-using-giloncecell-to-avoid-the-overhead-of-importing-a-class-multiple-times)).
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

IMO this is not the right place for this.

  1. I would like to keep this section of the guide as concise as possible.
  2. GILOnceCell::import does not work in the context of the example because sum is not a class, which would be confusing.
  3. Please avoid terminology like "overhead" or "is recommended". Just say what it does, for example, "if you want to import a class, you can store a reference to it with GILOnceCell::import".

I think such a footnote would fit better on https://pyo3.rs/main/doc/pyo3/types/struct.pymodule#method.import

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure, just made those changes in 46b18cc.

However, since I changed the implementation from PyType to T: PyTypeCheck, this does work:

#[pyfunction]
fn sum<'py>(py: Python<'py>, l: Py<PyList>) -> PyResult<Bound<'py, PyAny>> {
    static SUM: GILOnceCell<Py<PyAny>> = GILOnceCell::new();
    SUM.import(py, "builtins", "sum")?
        .call1((l,))
}

I guess this raises some questions. Is there any benefit in storing functions such as sum in the GILOnceCell, too? If not, should we prevent it (maybe by changing it back to PyType)? And if yes, should we be explicit in the docs that this is not only for importing classes?

src/sync.rs Outdated
Comment on lines 225 to 226
/// # Example: Using `GILOnceCell` to avoid the overhead of importing a class multiple times
///
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is better to just say what the example does, this makes for nicer URLs as well.

Suggested change
/// # Example: Using `GILOnceCell` to avoid the overhead of importing a class multiple times
///
/// # Example: Using `GILOnceCell` to store a class in a static variable.
///
/// `GILOnceCell` can be used to avoid importing a class multiple times

(this also explicitly mentions "static", which is important. We don't want people to have local (or worse, const) GILOnceCells).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done: 5d95fba

glevco and others added 3 commits September 20, 2024 12:37
Co-authored-by: Bruno Kolenbrander <59372212+mejrs@users.noreply.github.com>
Co-authored-by: Bruno Kolenbrander <59372212+mejrs@users.noreply.github.com>
@glevco glevco requested a review from mejrs September 20, 2024 16:23
Copy link
Member

@mejrs mejrs left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

@mejrs mejrs added this pull request to the merge queue Sep 21, 2024
Merged via the queue into PyO3:main with commit 6b3f887 Sep 21, 2024
42 of 43 checks passed
@glevco glevco deleted the pub_get_or_try_init_type_ref branch September 23, 2024 15:24
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.

Make GILOnceCell<Py<PyType>>'s get_or_try_init_type_ref public
3 participants