Merge branch 'master' into examples-debug

This commit is contained in:
Yuji Kanagawa 2019-09-07 11:53:00 +09:00 committed by GitHub
commit 5eb7656a5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
97 changed files with 591 additions and 456 deletions

View File

@ -7,5 +7,6 @@ Here are some things you should check for submitting your pull request:
- If applicable, add an entry in the changelog.
- If applicable, add documentation to all new items and extend the guide.
- If applicable, add tests for all new or fixed functions
- If you changed any python code, run `black .`. You can install black with `pip install black`)
You might want to run `tox` (`pip install tox`) locally to check compatibility with all supported python versions. If you're using linux or mac you might find the Makefile helpful for testing.

View File

@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
## [0.8.0]
## [0.8.0] - 2018-09-05
### Added
@ -29,6 +29,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
* Implementing the Using the `gc` parameter for `pyclass` (e.g. `#[pyclass(gc)]`) without implementing the `class::PyGCProtocol` trait is now a compile-time error. Failing to implement this trait could lead to segfaults. [#532](https://github.com/PyO3/pyo3/pull/532)
* `PyByteArray::data` has been replaced with `PyDataArray::to_vec` because returning a `&[u8]` is unsound. (See [this comment](https://github.com/PyO3/pyo3/issues/373#issuecomment-512332696) for a great write-up for why that was unsound)
* Replace `mashup` with `paste`.
* `GILPool` gained a `Python` marker to prevent it from being misused to release Python objects without the GIL held.
## [0.7.0] - 2018-05-26
@ -56,6 +57,8 @@ and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.
the items are not hashable.
* Fixed building using `venv` on Windows.
* `PyTuple::new` now returns `&PyTuple` instead of `Py<PyTuple>`.
* Fixed several issues with argument parsing; notable, the `*args` and `**kwargs`
tuple/dict now doesn't contain arguments that are otherwise assigned to parameters.
## [0.6.0] - 2018-03-28
@ -314,7 +317,8 @@ Yanked
* Initial release
[Unreleased]: https://github.com/pyo3/pyo3/compare/v0.7.0...HEAD
[Unreleased]: https://github.com/pyo3/pyo3/compare/v0.8.0...HEAD
[0.8.0]: https://github.com/pyo3/pyo3/compare/v0.7.0...v0.8.0
[0.7.0]: https://github.com/pyo3/pyo3/compare/v0.6.0...v0.7.0
[0.6.0]: https://github.com/pyo3/pyo3/compare/v0.5.3...v0.6.0
[0.5.3]: https://github.com/pyo3/pyo3/compare/v0.5.2...v0.5.3

View File

@ -1,6 +1,6 @@
[package]
name = "pyo3"
version = "0.7.0"
version = "0.8.0"
description = "Bindings to Python interpreter"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
readme = "README.md"
@ -22,7 +22,7 @@ appveyor = { repository = "fafhrd91/pyo3" }
libc = "0.2.62"
spin = "0.5.1"
num-traits = "0.2.8"
pyo3cls = { path = "pyo3cls", version = "=0.7.0" }
pyo3cls = { path = "pyo3cls", version = "=0.8.0" }
num-complex = { version = "0.2.3", optional = true }
inventory = "0.1.4"
indoc = "0.3.4"

View File

@ -16,6 +16,7 @@ test_py3:
fmt:
cargo fmt --all -- --check
black . --check
clippy:
@touch src/lib.rs # Touching file to ensure that cargo clippy will re-check the project

View File

@ -46,7 +46,7 @@ name = "string_sum"
crate-type = ["cdylib"]
[dependencies.pyo3]
version = "0.7.0"
version = "0.8.0"
features = ["extension-module"]
```
@ -83,7 +83,7 @@ rustflags = [
For developing, you can copy and rename the shared library from the target folder: On MacOS, rename `libstring_sum.dylib` to `string_sum.so`, on Windows `libstring_sum.dll` to `string_sum.pyd` and on Linux `libstring_sum.so` to `string_sum.so`. Then open a Python shell in the same folder and you'll be able to `import string_sum`.
To build, test and publish your crate as a Python module, you can use [pyo3-pack](https://github.com/PyO3/pyo3-pack) or [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an example for setuptools-rust in [examples/word-count](examples/word-count), while pyo3-pack should work on your crate without any configuration.
To build, test and publish your crate as a Python module, you can use [maturin](https://github.com/PyO3/maturin) or [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an example for setuptools-rust in [examples/word-count](examples/word-count), while maturin should work on your crate without any configuration.
## Using Python from Rust
@ -91,7 +91,7 @@ Add `pyo3` to your `Cargo.toml` like this:
```toml
[dependencies]
pyo3 = "0.7.0"
pyo3 = "0.8.0"
```
Example program displaying the value of `sys.version` and the current user name:

View File

@ -11,6 +11,7 @@ else
fi
if [ "$TRAVIS_JOB_NAME" = "Minimum nightly" ]; then
pip install --pre black==19.3b0
make lint
fi

View File

@ -40,8 +40,8 @@ MIN_DAYS = pdt.timedelta.min // pdt.timedelta(days=1)
MAX_MICROSECONDS = int(pdt.timedelta.max.total_seconds() * 1e6)
MIN_MICROSECONDS = int(pdt.timedelta.min.total_seconds() * 1e6)
IS_X86 = platform.architecture()[0] == '32bit'
IS_WINDOWS = sys.platform == 'win32'
IS_X86 = platform.architecture()[0] == "32bit"
IS_WINDOWS = sys.platform == "win32"
if IS_WINDOWS:
MIN_DATETIME_FROM_TIMESTAMP = pdt.datetime.fromtimestamp(86400)
if IS_X86:
@ -85,8 +85,9 @@ def test_invalid_date_fails():
rdt.make_date(2017, 2, 30)
@given(d=st.dates(MIN_DATETIME_FROM_TIMESTAMP.date(),
MAX_DATETIME_FROM_TIMESTAMP.date()))
@given(
d=st.dates(MIN_DATETIME_FROM_TIMESTAMP.date(), MAX_DATETIME_FROM_TIMESTAMP.date())
)
def test_date_from_timestamp(d):
if PYPY and d < pdt.date(1900, 1, 1):
pytest.xfail("pdt.datetime.timestamp will raise on PyPy with dates before 1900")
@ -225,8 +226,7 @@ def test_datetime_typeerror():
rdt.make_datetime("2011", 1, 1, 0, 0, 0, 0)
@given(dt=st.datetimes(MIN_DATETIME_FROM_TIMESTAMP,
MAX_DATETIME_FROM_TIMESTAMP))
@given(dt=st.datetimes(MIN_DATETIME_FROM_TIMESTAMP, MAX_DATETIME_FROM_TIMESTAMP))
@example(dt=pdt.datetime(1970, 1, 2, 0, 0))
def test_datetime_from_timestamp(dt):
if PYPY and dt < pdt.datetime(1900, 1, 1):

View File

@ -1,10 +1,8 @@
import pytest
from rustapi_module.test_dict import DictSize
@pytest.mark.parametrize(
"size",
[64, 128, 256],
)
@pytest.mark.parametrize("size", [64, 128, 256])
def test_size(size):
d = {}
for i in range(size):

View File

@ -2,7 +2,8 @@ import platform
from rustapi_module.subclassing import Subclassable
PYPY = platform.python_implementation() == 'PyPy'
PYPY = platform.python_implementation() == "PyPy"
class SomeSubClass(Subclassable):
pass

View File

@ -36,20 +36,21 @@ class CargoModifiedSdist(SdistCommand):
super().make_release_tree(base_dir, files)
import toml
# Cargo.toml is now staged and ready to be modified
cargo_loc = os.path.join(base_dir, 'Cargo.toml')
cargo_loc = os.path.join(base_dir, "Cargo.toml")
assert os.path.exists(cargo_loc)
with open(cargo_loc, 'r') as f:
with open(cargo_loc, "r") as f:
cargo_toml = toml.load(f)
rel_pyo3_path = cargo_toml['dependencies']['pyo3']['path']
rel_pyo3_path = cargo_toml["dependencies"]["pyo3"]["path"]
base_path = os.path.dirname(__file__)
abs_pyo3_path = os.path.abspath(os.path.join(base_path, rel_pyo3_path))
cargo_toml['dependencies']['pyo3']['path'] = abs_pyo3_path
cargo_toml["dependencies"]["pyo3"]["path"] = abs_pyo3_path
with open(cargo_loc, 'w') as f:
with open(cargo_loc, "w") as f:
toml.dump(cargo_toml, f)
@ -87,8 +88,5 @@ setup(
setup_requires=setup_requires,
include_package_data=True,
zip_safe=False,
cmdclass={
'test': PyTest,
'sdist': CargoModifiedSdist,
},
cmdclass={"test": PyTest, "sdist": CargoModifiedSdist},
)

View File

@ -12,7 +12,7 @@ Currently, [#341](https://github.com/PyO3/pyo3/issues/341) causes `cargo test` t
```toml
[dependencies.pyo3]
version = "0.7.0"
version = "0.8.0"
[features]
extension-module = ["pyo3/extension-module"]

View File

@ -36,7 +36,7 @@ On Linux/macOS you might have to change `LD_LIBRARY_PATH` to include libpython,
## Distribution
There are two ways to distribute your module as a Python package: the old, [setuptools-rust](https://github.com/PyO3/setuptools-rust), and the new, [pyo3-pack](https://github.com/pyo3/pyo3-pack). setuptools-rust needs some configuration files (`setup.py`, `MANIFEST.in`, `build-wheels.sh`, etc.) and external tools (docker, twine). pyo3-pack doesn't need any configuration files. It can not yet build sdist though ([pyo3/pyo3-pack#2](https://github.com/PyO3/pyo3-pack/issues/2)).
There are two ways to distribute your module as a Python package: the old, [setuptools-rust](https://github.com/PyO3/setuptools-rust), and the new, [maturin](https://github.com/pyo3/maturin). setuptools-rust needs some configuration files (`setup.py`, `MANIFEST.in`, `build-wheels.sh`, etc.) and external tools (docker, twine). maturin doesn't need any configuration files. It can not yet build sdist though ([pyo3/maturin#2](https://github.com/PyO3/maturin/issues/2)).
## Cross Compiling

View File

@ -477,7 +477,7 @@ each protocol implementation block has to be annotated with the `#[pyproto]` att
### Basic object customization
The [`PyObjectProtocol`](https://docs.rs/pyo3/0.7.0/pyo3/class/basic/trait.PyObjectProtocol.html) trait provides several basic customizations.
The [`PyObjectProtocol`](https://docs.rs/pyo3/0.8.0/pyo3/class/basic/trait.PyObjectProtocol.html) trait provides several basic customizations.
#### Attribute access
@ -531,7 +531,7 @@ Each method corresponds to Python's `self.attr`, `self.attr = value` and `del se
If your type owns references to other Python objects, you will need to
integrate with Python's garbage collector so that the GC is aware of
those references.
To do this, implement the [`PyGCProtocol`](https://docs.rs/pyo3/0.7.0/pyo3/class/gc/trait.PyGCProtocol.html) trait for your struct.
To do this, implement the [`PyGCProtocol`](https://docs.rs/pyo3/0.8.0/pyo3/class/gc/trait.PyGCProtocol.html) trait for your struct.
It includes two methods `__traverse__` and `__clear__`.
These correspond to the slots `tp_traverse` and `tp_clear` in the Python C API.
`__traverse__` must call `visit.call()` for each reference to another Python object.
@ -587,7 +587,7 @@ struct GCTracked {} // Fails because it does not implement PyGCProtocol
### Iterator Types
Iterators can be defined using the
[`PyIterProtocol`](https://docs.rs/pyo3/0.7.0/pyo3/class/iter/trait.PyIterProtocol.html) trait.
[`PyIterProtocol`](https://docs.rs/pyo3/0.8.0/pyo3/class/iter/trait.PyIterProtocol.html) trait.
It includes two methods `__iter__` and `__next__`:
* `fn __iter__(slf: PyRefMut<Self>) -> PyResult<impl IntoPy<PyObject>>`
* `fn __next__(slf: PyRefMut<Self>) -> PyResult<Option<impl IntoPy<PyObject>>>`

View File

@ -106,8 +106,8 @@ Many conversions in PyO3 can't use `std::convert::Into` because they need a GIL
Eventually, traits such as `ToPyObject` will be replaced by this trait and a `FromPy` trait will be added that will implement `IntoPy`, just like with `From` and `Into`.
[`ToPyObject`]: https://docs.rs/pyo3/0.7.0/pyo3/trait.ToPyObject.html
[PyObject]: https://docs.rs/pyo3/0.7.0/pyo3/struct.PyObject.html
[PyTuple]: https://docs.rs/pyo3/0.7.0/pyo3/types/struct.PyTuple.html
[ObjectProtocol]: https://docs.rs/pyo3/0.7.0/pyo3/trait.ObjectProtocol.html
[IntoPyDict]: https://docs.rs/pyo3/0.7.0/pyo3/types/trait.IntoPyDict.html
[`ToPyObject`]: https://docs.rs/pyo3/0.8.0/pyo3/trait.ToPyObject.html
[PyObject]: https://docs.rs/pyo3/0.8.0/pyo3/struct.PyObject.html
[PyTuple]: https://docs.rs/pyo3/0.8.0/pyo3/types/struct.PyTuple.html
[ObjectProtocol]: https://docs.rs/pyo3/0.8.0/pyo3/trait.ObjectProtocol.html
[IntoPyDict]: https://docs.rs/pyo3/0.8.0/pyo3/types/trait.IntoPyDict.html

View File

@ -35,7 +35,7 @@ fn main() {
## Raise an exception
To raise an exception, first you need to obtain an exception type and construct a new [`PyErr`](https://docs.rs/pyo3/0.7.0/pyo3/struct.PyErr.html), then call the [`PyErr::restore()`](https://docs.rs/pyo3/0.7.0/pyo3/struct.PyErr.html#method.restore) method to write the exception back to the Python interpreter's global state.
To raise an exception, first you need to obtain an exception type and construct a new [`PyErr`](https://docs.rs/pyo3/0.8.0/pyo3/struct.PyErr.html), then call the [`PyErr::restore()`](https://docs.rs/pyo3/0.8.0/pyo3/struct.PyErr.html#method.restore) method to write the exception back to the Python interpreter's global state.
```rust
use pyo3::{Python, PyErr};
@ -50,7 +50,7 @@ fn main() {
}
```
If you already have a Python exception instance, you can simply call [`PyErr::from_instance()`](https://docs.rs/pyo3/0.7.0/pyo3/struct.PyErr.html#method.from_instance).
If you already have a Python exception instance, you can simply call [`PyErr::from_instance()`](https://docs.rs/pyo3/0.8.0/pyo3/struct.PyErr.html#method.from_instance).
```rust,ignore
PyErr::from_instance(py, err).restore(py);
@ -77,7 +77,7 @@ fn my_func(arg: PyObject) -> PyResult<()> {
## Check exception type
Python has an [`isinstance`](https://docs.python.org/3/library/functions.html#isinstance) method to check an object's type,
in PyO3 there is a [`Python::is_instance()`](https://docs.rs/pyo3/0.7.0/pyo3/struct.Python.html#method.is_instance) method which does the same thing.
in PyO3 there is a [`Python::is_instance()`](https://docs.rs/pyo3/0.8.0/pyo3/struct.Python.html#method.is_instance) method which does the same thing.
```rust
use pyo3::Python;
@ -93,7 +93,7 @@ fn main() {
}
```
[`Python::is_instance()`](https://docs.rs/pyo3/0.7.0/pyo3/struct.Python.html#method.is_instance) calls the underlying [`PyType::is_instance`](https://docs.rs/pyo3/0.7.0/pyo3/types/struct.PyType.html#method.is_instance) method to do the actual work.
[`Python::is_instance()`](https://docs.rs/pyo3/0.8.0/pyo3/struct.Python.html#method.is_instance) calls the underlying [`PyType::is_instance`](https://docs.rs/pyo3/0.8.0/pyo3/types/struct.PyType.html#method.is_instance) method to do the actual work.
To check the type of an exception, you can simply do:
@ -110,10 +110,10 @@ err.is_instance::<exceptions::TypeError>(py);
## Handle Rust Errors
The vast majority of operations in this library will return [`PyResult<T>`](https://docs.rs/pyo3/0.7.0/pyo3/prelude/type.PyResult.html).
The vast majority of operations in this library will return [`PyResult<T>`](https://docs.rs/pyo3/0.8.0/pyo3/prelude/type.PyResult.html).
This is an alias for the type `Result<T, PyErr>`.
A [`PyErr`](https://docs.rs/pyo3/0.7.0/pyo3/struct.PyErr.html) represents a Python exception.
A [`PyErr`](https://docs.rs/pyo3/0.8.0/pyo3/struct.PyErr.html) represents a Python exception.
Errors within the PyO3 library are also exposed as Python exceptions.
The PyO3 library handles Python exceptions in two stages. During the first stage, a `PyErr` instance is
@ -124,7 +124,7 @@ In simple cases, for custom errors adding an implementation of `std::convert::Fr
for this custom error is enough. `PyErr::new` accepts an argument in the form
of `ToPyObject + 'static`. If the `'static` constraint can not be satisfied or
more complex arguments are required, the
[`PyErrArguments`](https://docs.rs/pyo3/0.7.0/pyo3/trait.PyErrArguments.html)
[`PyErrArguments`](https://docs.rs/pyo3/0.8.0/pyo3/trait.PyErrArguments.html)
trait can be implemented. In that case, actual exception argument creation is delayed
until a `Python` object is available.
@ -202,5 +202,5 @@ fn tell(file: PyObject) -> PyResult<u64> {
```
[`pyo3::exceptions`](https://docs.rs/pyo3/0.7.0/pyo3/exceptions/index.html)
[`pyo3::exceptions`](https://docs.rs/pyo3/0.8.0/pyo3/exceptions/index.html)
defines exceptions for several standard library modules.

View File

@ -46,6 +46,34 @@ fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
# fn main() {}
```
## Argument parsing
Both the `#[pyfunction]` and `#[pyfn]` attributes support specifying details of
argument parsing. The details are given in the section "Method arguments" in
the [Classes](class.md) chapter. Here is an example for a function that accepts
arbitrary keyword arguments (`**kwargs` in Python syntax) and returns the number
that was passed:
```rust
# extern crate pyo3;
use pyo3::prelude::*;
use pyo3::wrap_pyfunction;
use pyo3::types::PyDict;
#[pyfunction(kwds="**")]
fn num_kwds(kwds: Option<&PyDict>) -> usize {
kwds.map_or(0, |dict| dict.len())
}
#[pymodule]
fn module_with_functions(py: Python, m: &PyModule) -> PyResult<()> {
m.add_wrapped(wrap_pyfunction!(num_kwds)).unwrap();
Ok(())
}
# fn main() {}
```
### Making the function signature available to Python
In order to make the function signature available to Python to be retrieved via

View File

@ -40,7 +40,7 @@ name = "string_sum"
crate-type = ["cdylib"]
[dependencies.pyo3]
version = "0.7.0"
version = "0.8.0"
features = ["extension-module"]
```
@ -77,7 +77,7 @@ rustflags = [
For developing, you can copy and rename the shared library from the target folder: On MacOS, rename `libstring_sum.dylib` to `string_sum.so`, on Windows `libstring_sum.dll` to `string_sum.pyd` and on Linux `libstring_sum.so` to `string_sum.so`. Then open a Python shell in the same folder and you'll be able to `import string_sum`.
To build, test and publish your crate as a Python module, you can use [pyo3-pack](https://github.com/PyO3/pyo3-pack) or [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an example for setuptools-rust in [examples/word-count](examples/word-count), while pyo3-pack should work on your crate without any configuration.
To build, test and publish your crate as a Python module, you can use [maturin](https://github.com/PyO3/maturin) or [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an example for setuptools-rust in [examples/word-count](examples/word-count), while maturin should work on your crate without any configuration.
## Using Python from Rust
@ -85,7 +85,7 @@ Add `pyo3` to your `Cargo.toml` like this:
```toml
[dependencies]
pyo3 = "0.7.0"
pyo3 = "0.8.0"
```
Example program displaying the value of `sys.version` and the current user name:

View File

@ -33,7 +33,7 @@ fn sum_as_string(a:i64, b:i64) -> String {
The `#[pymodule]` procedural macro attribute takes care of exporting the initialization function of your module to Python. It can take as an argument the name of your module, which must be the name of the `.so` or `.pyd` file; the default is the Rust function's name.
To import the module, either copy the shared library as described in [Get Started](./overview.md) or use a tool, e.g. `pyo3-pack develop` with [pyo3-pack](https://github.com/PyO3/pyo3-pack) or `python setup.py develop` with [setuptools-rust](https://github.com/PyO3/setuptools-rust).
To import the module, either copy the shared library as described in [Get Started](./overview.md) or use a tool, e.g. `maturin develop` with [maturin](https://github.com/PyO3/maturin) or `python setup.py develop` with [setuptools-rust](https://github.com/PyO3/setuptools-rust).
## Documentation

View File

@ -4,7 +4,7 @@ CPython has the infamous GIL (Global Interpreter Lock), which prevents developer
from getting true parallelism when running pure Python code. With PyO3, you can
release the GIL when executing Rust code to achieve true parallelism.
The [`Python::allow_threads`](https://docs.rs/pyo3/0.7.0/pyo3/struct.Python.html#method.allow_threads)
The [`Python::allow_threads`](https://docs.rs/pyo3/0.8.0/pyo3/struct.Python.html#method.allow_threads)
method temporarily releases the GIL, thus allowing other Python threads to run.
```rust,ignore

View File

@ -1,6 +1,6 @@
[package]
name = "pyo3-derive-backend"
version = "0.7.0"
version = "0.8.0"
description = "Code generation for PyO3 package"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
keywords = ["pyo3", "python", "cpython", "ffi"]

View File

@ -5,6 +5,7 @@ use crate::pyfunction::PyFunctionAttr;
use proc_macro2::TokenStream;
use quote::quote;
use quote::ToTokens;
use syn::spanned::Spanned;
#[derive(Clone, PartialEq, Debug)]
pub struct FnArg<'a> {
@ -390,13 +391,23 @@ fn replace_self(path: &syn::TypePath) -> syn::TypePath {
let mut res = path.to_owned();
for seg in &mut res.path.segments {
if let syn::PathArguments::AngleBracketed(ref mut g) = seg.arguments {
for arg in &mut g.args {
let mut args = syn::punctuated::Punctuated::new();
for arg in &g.args {
let mut add_arg = true;
if let syn::GenericArgument::Lifetime(_) = arg {
add_arg = false;
}
if let syn::GenericArgument::Type(syn::Type::Path(p)) = arg {
if p.path.segments.len() == 1 && p.path.segments[0].ident == "Self" {
*arg = infer(p.path.segments[0].ident.span());
args.push(infer(p.span()));
add_arg = false;
}
}
if add_arg {
args.push(arg.clone());
}
}
g.args = args;
}
}
res

View File

@ -204,8 +204,8 @@ fn function_c_wrapper(name: &Ident, spec: &method::FnSpec<'_>) -> TokenStream {
{
const _LOCATION: &'static str = concat!(stringify!(#name), "()");
let _pool = pyo3::GILPool::new();
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);

View File

@ -113,8 +113,8 @@ fn impl_wrap_common(
{
const _LOCATION: &'static str = concat!(
stringify!(#cls), ".", stringify!(#name), "()");
let _pool = pyo3::GILPool::new();
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
#slf
let _result = {
pyo3::derive_utils::IntoPyResult::into_py_result(#body)
@ -135,8 +135,8 @@ fn impl_wrap_common(
{
const _LOCATION: &'static str = concat!(
stringify!(#cls), ".", stringify!(#name), "()");
let _pool = pyo3::GILPool::new();
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
#slf
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
@ -163,8 +163,8 @@ pub fn impl_proto_wrap(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) ->
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = pyo3::GILPool::new();
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
@ -194,8 +194,8 @@ pub fn impl_wrap_new(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> T
use pyo3::type_object::PyTypeInfo;
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = pyo3::GILPool::new();
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
match pyo3::type_object::PyRawObject::new(_py, #cls::type_object(), _cls) {
Ok(_obj) => {
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
@ -240,8 +240,8 @@ fn impl_wrap_init(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -> Toke
_kwargs: *mut pyo3::ffi::PyObject) -> pyo3::libc::c_int
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = pyo3::GILPool::new();
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
@ -274,8 +274,8 @@ pub fn impl_wrap_class(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) ->
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = pyo3::GILPool::new();
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _cls = pyo3::types::PyType::from_type_ptr(_py, _cls as *mut pyo3::ffi::PyTypeObject);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
@ -303,8 +303,8 @@ pub fn impl_wrap_static(cls: &syn::Type, name: &syn::Ident, spec: &FnSpec<'_>) -
_kwargs: *mut pyo3::ffi::PyObject) -> *mut pyo3::ffi::PyObject
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = pyo3::GILPool::new();
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _args = _py.from_borrowed_ptr::<pyo3::types::PyTuple>(_args);
let _kwargs: Option<&pyo3::types::PyDict> = _py.from_borrowed_ptr_or_opt(_kwargs);
@ -329,8 +329,8 @@ pub(crate) fn impl_wrap_getter(cls: &syn::Type, name: &syn::Ident, takes_py: boo
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = pyo3::GILPool::new();
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf);
let result = pyo3::derive_utils::IntoPyResult::into_py_result(#fncall);
@ -370,8 +370,8 @@ pub(crate) fn impl_wrap_setter(
_value: *mut pyo3::ffi::PyObject, _: *mut ::std::os::raw::c_void) -> pyo3::libc::c_int
{
const _LOCATION: &'static str = concat!(stringify!(#cls),".",stringify!(#name),"()");
let _pool = pyo3::GILPool::new();
let _py = pyo3::Python::assume_gil_acquired();
let _pool = pyo3::GILPool::new(_py);
let _slf = _py.mut_from_borrowed_ptr::<#cls>(_slf);
let _value = _py.from_borrowed_ptr(_value);
@ -470,13 +470,15 @@ pub fn impl_arg_params(spec: &FnSpec<'_>, body: TokenStream) -> TokenStream {
];
let mut output = [#(#placeholders),*];
let mut _args = _args;
let mut _kwargs = _kwargs;
// Workaround to use the question mark operator without rewriting everything
let _result = (|| {
pyo3::derive_utils::parse_fn_args(
let (_args, _kwargs) = pyo3::derive_utils::parse_fn_args(
Some(_LOCATION),
PARAMS,
&_args,
_args,
_kwargs,
#accept_args,
#accept_kwargs,

View File

@ -1,6 +1,6 @@
[package]
name = "pyo3cls"
version = "0.7.0"
version = "0.8.0"
description = "Proc macros for PyO3 package"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
keywords = ["pyo3", "python", "cpython", "ffi"]
@ -17,7 +17,7 @@ proc-macro = true
quote = "1"
proc-macro2 = "1"
syn = { version = "1", features = ["full", "extra-traits"] }
pyo3-derive-backend = { path = "../pyo3-derive-backend", version = "=0.7.0" }
pyo3-derive-backend = { path = "../pyo3-derive-backend", version = "=0.8.0" }
[features]
unsound-subclass = ["pyo3-derive-backend/unsound-subclass"]

18
pyproject.toml Normal file
View File

@ -0,0 +1,18 @@
[tool.black]
target_version = ['py35']
include = '\.pyi?$'
exclude = '''
(
/(
\.eggs # exclude a few common directories in the
| \.git # root of the project
| \.mypy_cache
| \.tox
| \.venv
| venv
| target
| dist
)/
)
'''

View File

@ -215,8 +215,8 @@ where
where
T: for<'p> PyObjectGetAttrProtocol<'p>,
{
let _pool = crate::GILPool::new();
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
// Behave like python's __getattr__ (as opposed to __getattribute__) and check
// for existing fields and methods first
@ -450,8 +450,8 @@ where
where
T: for<'p> PyObjectRichcmpProtocol<'p>,
{
let _pool = crate::GILPool::new();
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.from_borrowed_ptr::<T>(slf);
let arg = py.from_borrowed_ptr::<PyAny>(arg);

View File

@ -85,8 +85,8 @@ where
where
T: for<'p> PyBufferGetBufferProtocol<'p>,
{
let _pool = crate::GILPool::new();
let py = crate::Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let result = slf.bf_getbuffer(arg1, arg2).into();

View File

@ -85,8 +85,8 @@ where
where
T: for<'p> PyGCTraverseProtocol<'p>,
{
let _pool = crate::GILPool::new();
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let visit = PyVisit {
@ -122,8 +122,8 @@ where
where
T: for<'p> PyGCClearProtocol<'p>,
{
let _pool = crate::GILPool::new();
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
slf.__clear__();

View File

@ -17,8 +17,8 @@ macro_rules! py_unary_func {
where
T: for<'p> $trait<'p>,
{
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let res = slf.$f().into();
$crate::callback::cb_convert($conv, py, res.map(|x| x))
@ -36,8 +36,8 @@ macro_rules! py_unary_pyref_func {
T: for<'p> $trait<'p>,
{
use $crate::instance::PyRefMut;
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let res = $class::$f(PyRefMut::from_mut(slf)).into();
$crate::callback::cb_convert($conv, py, res)
@ -54,8 +54,8 @@ macro_rules! py_len_func {
where
T: for<'p> $trait<'p>,
{
let _pool = $crate::GILPool::new();
let py = Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let result = slf.$f().into();
@ -84,8 +84,8 @@ macro_rules! py_binary_func {
T: for<'p> $trait<'p>,
{
use $crate::ObjectProtocol;
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let arg = py.from_borrowed_ptr::<$crate::types::PyAny>(arg);
@ -112,8 +112,8 @@ macro_rules! py_binary_num_func {
T: for<'p> $trait<'p>,
{
use $crate::ObjectProtocol;
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let lhs = py.from_borrowed_ptr::<$crate::types::PyAny>(lhs);
let rhs = py.from_borrowed_ptr::<$crate::types::PyAny>(rhs);
@ -144,8 +144,8 @@ macro_rules! py_binary_self_func {
{
use $crate::ObjectProtocol;
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf1 = py.mut_from_borrowed_ptr::<T>(slf);
let arg = py.from_borrowed_ptr::<$crate::types::PyAny>(arg);
@ -180,8 +180,8 @@ macro_rules! py_ssizearg_func {
where
T: for<'p> $trait<'p>,
{
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let result = slf.$f(arg.into()).into();
$crate::callback::cb_convert($conv, py, result)
@ -213,8 +213,8 @@ macro_rules! py_ternary_func {
{
use $crate::ObjectProtocol;
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let arg1 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg1);
let arg2 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg2);
@ -247,8 +247,8 @@ macro_rules! py_ternary_num_func {
{
use $crate::ObjectProtocol;
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let arg1 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg1);
let arg2 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg2);
let arg3 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg3);
@ -284,8 +284,8 @@ macro_rules! py_ternary_self_func {
{
use $crate::ObjectProtocol;
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf1 = py.mut_from_borrowed_ptr::<T>(slf);
let arg1 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg1);
let arg2 = py.from_borrowed_ptr::<$crate::types::PyAny>(arg2);
@ -323,8 +323,8 @@ macro_rules! py_func_set {
{
use $crate::ObjectProtocol;
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<$generic>(slf);
let result = if value.is_null() {
@ -371,8 +371,8 @@ macro_rules! py_func_del {
{
use $crate::ObjectProtocol;
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let result = if value.is_null() {
let slf = py.mut_from_borrowed_ptr::<U>(slf);
@ -413,8 +413,8 @@ macro_rules! py_func_set_del {
{
use $crate::ObjectProtocol;
let _pool = $crate::GILPool::new();
let py = $crate::Python::assume_gil_acquired();
let _pool = $crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<$generic>(slf);
let name = py.from_borrowed_ptr::<$crate::types::PyAny>(name);

View File

@ -221,8 +221,8 @@ where
where
T: for<'p> PySequenceSetItemProtocol<'p>,
{
let _pool = crate::GILPool::new();
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let result = if value.is_null() {
@ -295,8 +295,8 @@ mod sq_ass_item_impl {
where
T: for<'p> PySequenceDelItemProtocol<'p>,
{
let _pool = crate::GILPool::new();
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let result = if value.is_null() {
@ -341,8 +341,8 @@ mod sq_ass_item_impl {
where
T: for<'p> PySequenceSetItemProtocol<'p> + for<'p> PySequenceDelItemProtocol<'p>,
{
let _pool = crate::GILPool::new();
let py = Python::assume_gil_acquired();
let _pool = crate::GILPool::new(py);
let slf = py.mut_from_borrowed_ptr::<T>(slf);
let result = if value.is_null() {

View File

@ -7,9 +7,9 @@
use crate::err::PyResult;
use crate::exceptions::TypeError;
use crate::init_once;
use crate::types::{PyAny, PyDict, PyModule, PyString, PyTuple};
use crate::instance::PyNativeType;
use crate::types::{PyAny, PyDict, PyModule, PyTuple};
use crate::GILPool;
use crate::PyTryFrom;
use crate::Python;
use crate::{ffi, IntoPy, PyObject};
use std::ptr;
@ -41,72 +41,76 @@ pub fn parse_fn_args<'p>(
accept_args: bool,
accept_kwargs: bool,
output: &mut [Option<&'p PyAny>],
) -> PyResult<()> {
) -> PyResult<(&'p PyTuple, Option<&'p PyDict>)> {
let nargs = args.len();
let nkeywords = kwargs.map_or(0, PyDict::len);
if !accept_args && !accept_kwargs && (nargs + nkeywords > params.len()) {
return Err(TypeError::py_err(format!(
"{}{} takes at most {} argument{} ({} given)",
fname.unwrap_or("function"),
if fname.is_some() { "()" } else { "" },
params.len(),
if params.len() == 1 { "s" } else { "" },
nargs + nkeywords
)));
let mut used_args = 0;
macro_rules! raise_error {
($s: expr $(,$arg:expr)*) => (return Err(TypeError::py_err(format!(
concat!("{} ", $s), fname.unwrap_or("function") $(,$arg)*
))))
}
let mut used_keywords = 0;
// Copy kwargs not to modify it
let kwargs = match kwargs {
Some(k) => Some(k.copy()?),
None => None,
};
// Iterate through the parameters and assign values to output:
for (i, (p, out)) in params.iter().zip(output).enumerate() {
match kwargs.and_then(|d| d.get_item(p.name)) {
*out = match kwargs.and_then(|d| d.get_item(p.name)) {
Some(kwarg) => {
*out = Some(kwarg);
used_keywords += 1;
if i < nargs {
return Err(TypeError::py_err(format!(
"Argument given by name ('{}') and position ({})",
p.name,
i + 1
)));
raise_error!("got multiple values for argument: {}", p.name)
}
kwargs.as_ref().unwrap().del_item(p.name).unwrap();
Some(kwarg)
}
None => {
if p.kw_only {
if !p.is_optional {
return Err(TypeError::py_err(format!(
"Required argument ('{}') is keyword only argument",
p.name
)));
raise_error!("missing required keyword-only argument: {}", p.name)
}
*out = None;
None
} else if i < nargs {
*out = Some(args.get_item(i));
used_args += 1;
Some(args.get_item(i))
} else {
*out = None;
if !p.is_optional {
return Err(TypeError::py_err(format!(
"Required argument ('{}') (pos {}) not found",
p.name,
i + 1
)));
raise_error!("missing required positional argument: {}", p.name)
}
None
}
}
}
}
if !accept_kwargs && used_keywords != nkeywords {
// check for extraneous keyword arguments
for item in kwargs.unwrap().items().iter() {
let item = <PyTuple as PyTryFrom>::try_from(item)?;
let key = <PyString as PyTryFrom>::try_from(item.get_item(0))?.to_string()?;
if !params.iter().any(|p| p.name == key) {
return Err(TypeError::py_err(format!(
"'{}' is an invalid keyword argument for this function",
key
)));
}
}
let is_kwargs_empty = kwargs.as_ref().map_or(true, |dict| dict.is_empty());
// Raise an error when we get an unknown key
if !accept_kwargs && !is_kwargs_empty {
let (key, _) = kwargs.unwrap().iter().next().unwrap();
raise_error!("got an unexpected keyword argument: {}", key)
}
Ok(())
// Raise an error when we get too many positional args
if !accept_args && used_args < nargs {
raise_error!(
"takes at most {} positional argument{} ({} given)",
used_args,
if used_args == 1 { "" } else { "s" },
nargs
)
}
// Adjust the remaining args
let args = if accept_args {
let py = args.py();
let slice = args.slice(used_args as isize, nargs as isize).into_py(py);
py.checked_cast_as(slice).unwrap()
} else {
args
};
let kwargs = if accept_kwargs && is_kwargs_empty {
None
} else {
kwargs
};
Ok((args, kwargs))
}
/// Builds a module (or null) from a user given initializer. Used for `#[pymodule]`.
@ -135,8 +139,8 @@ pub unsafe fn make_module(
return module;
}
let _pool = GILPool::new();
let py = Python::assume_gil_acquired();
let _pool = GILPool::new(py);
let module = match py.from_owned_ptr_or_err::<PyModule>(module) {
Ok(m) => m,
Err(e) => {

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::PyTypeObject;
use crate::ffi::object::PyTypeObject;
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {

View File

@ -1,5 +1,5 @@
use crate::ffi3::longobject::PyLongObject;
use crate::ffi3::object::*;
use crate::ffi::longobject::PyLongObject;
use crate::ffi::object::*;
use std::os::raw::{c_int, c_long};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,7 +1,7 @@
#[cfg(Py_3_6)]
use crate::ffi3::code::FreeFunc;
use crate::ffi3::object::PyObject;
use crate::ffi3::pystate::PyThreadState;
use crate::ffi::code::FreeFunc;
use crate::ffi::object::PyObject;
use crate::ffi::pystate::PyThreadState;
use std::os::raw::{c_char, c_int, c_void};
#[cfg_attr(windows, link(name = "pythonXY"))]
@ -36,7 +36,7 @@ extern "C" {
pub fn PyEval_GetGlobals() -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyEval_GetLocals")]
pub fn PyEval_GetLocals() -> *mut PyObject;
pub fn PyEval_GetFrame() -> *mut crate::ffi3::PyFrameObject;
pub fn PyEval_GetFrame() -> *mut crate::ffi::PyFrameObject;
#[cfg_attr(PyPy, link_name = "PyPy_AddPendingCall")]
pub fn Py_AddPendingCall(
func: Option<extern "C" fn(arg1: *mut c_void) -> c_int>,
@ -55,22 +55,22 @@ extern "C" {
// TODO: Py_EnterRecursiveCall etc.
#[cfg(Py_3_6)]
pub type _PyFrameEvalFunction =
extern "C" fn(*mut crate::ffi3::PyFrameObject, c_int) -> *mut PyObject;
extern "C" fn(*mut crate::ffi::PyFrameObject, c_int) -> *mut PyObject;
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
pub fn PyEval_GetFuncName(arg1: *mut PyObject) -> *const c_char;
pub fn PyEval_GetFuncDesc(arg1: *mut PyObject) -> *const c_char;
pub fn PyEval_GetCallStats(arg1: *mut PyObject) -> *mut PyObject;
pub fn PyEval_EvalFrame(arg1: *mut crate::ffi3::PyFrameObject) -> *mut PyObject;
pub fn PyEval_EvalFrame(arg1: *mut crate::ffi::PyFrameObject) -> *mut PyObject;
#[cfg(Py_3_6)]
pub fn _PyEval_EvalFrameDefault(
arg1: *mut crate::ffi3::PyFrameObject,
arg1: *mut crate::ffi::PyFrameObject,
exc: c_int,
) -> *mut PyObject;
#[cfg(Py_3_6)]
pub fn _PyEval_RequestCodeExtraIndex(func: FreeFunc) -> c_int;
pub fn PyEval_EvalFrameEx(f: *mut crate::ffi3::PyFrameObject, exc: c_int) -> *mut PyObject;
pub fn PyEval_EvalFrameEx(f: *mut crate::ffi::PyFrameObject, exc: c_int) -> *mut PyObject;
#[cfg_attr(PyPy, link_name = "PyPyEval_SaveThread")]
pub fn PyEval_SaveThread() -> *mut PyThreadState;
#[cfg_attr(PyPy, link_name = "PyPyEval_RestoreThread")]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int, c_uchar, c_void};
#[repr(C)]
@ -124,5 +124,5 @@ pub unsafe fn PyCode_Check(op: *mut PyObject) -> c_int {
#[inline]
#[cfg_attr(PyPy, link_name = "PyPyCode_GetNumFree")]
pub unsafe fn PyCode_GetNumFree(op: *mut PyCodeObject) -> Py_ssize_t {
crate::ffi3::tupleobject::PyTuple_GET_SIZE((*op).co_freevars)
crate::ffi::tupleobject::PyTuple_GET_SIZE((*op).co_freevars)
}

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::PyObject;
use crate::ffi::object::PyObject;
use std::os::raw::{c_char, c_int};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,7 +1,7 @@
use crate::ffi3::code::*;
use crate::ffi3::object::PyObject;
use crate::ffi3::pyarena::*;
use crate::ffi3::pythonrun::*;
use crate::ffi::code::*;
use crate::ffi::object::PyObject;
use crate::ffi::pyarena::*;
use crate::ffi::pythonrun::*;
use std::os::raw::{c_char, c_int};
#[repr(C)]

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::*;
use crate::ffi::object::*;
use std::os::raw::{c_double, c_int};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,8 +1,8 @@
use crate::ffi3::methodobject::PyMethodDef;
use crate::ffi3::object::{PyObject, PyTypeObject};
use crate::ffi::methodobject::PyMethodDef;
use crate::ffi::object::{PyObject, PyTypeObject};
#[cfg(not(PyPy))]
use crate::ffi3::object::{PyObject_GenericGetDict, PyObject_GenericSetDict};
use crate::ffi3::structmember::PyMemberDef;
use crate::ffi::object::{PyObject_GenericGetDict, PyObject_GenericSetDict};
use crate::ffi::structmember::PyMemberDef;
use std::os::raw::{c_char, c_int, c_void};
use std::ptr;

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::PyTypeObject;
use crate::ffi::object::PyTypeObject;
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::PyObject;
use crate::ffi::object::PyObject;
use std::os::raw::c_int;
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::PyObject;
use crate::ffi::object::PyObject;
use std::os::raw::{c_char, c_int};
pub const PY_STDIOTEXTMODE: &str = "b";

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::*;
use crate::ffi::object::*;
use std::os::raw::{c_double, c_int};
#[cfg(not(Py_LIMITED_API))]

View File

@ -1,6 +1,6 @@
use crate::ffi3::code::{PyCodeObject, CO_MAXBLOCKS};
use crate::ffi3::object::*;
use crate::ffi3::pystate::PyThreadState;
use crate::ffi::code::{PyCodeObject, CO_MAXBLOCKS};
use crate::ffi::object::*;
use crate::ffi::pystate::PyThreadState;
use std::os::raw::{c_char, c_int};
#[repr(C)]

View File

@ -1,6 +1,6 @@
use crate::ffi3::frameobject::PyFrameObject;
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::frameobject::PyFrameObject;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::c_int;
#[repr(C)]

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::PyObject;
use crate::ffi::object::PyObject;
use std::os::raw::{c_char, c_int, c_long};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::*;
use crate::ffi::object::*;
use std::os::raw::c_int;
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::c_int;
#[repr(C)]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use libc::size_t;
use std::os::raw::{
c_char, c_double, c_int, c_long, c_longlong, c_uchar, c_ulong, c_ulonglong, c_void,

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::{PyObject, PyTypeObject, Py_TYPE};
use crate::ffi::object::{PyObject, PyTypeObject, Py_TYPE};
use std::os::raw::{c_char, c_int};
use std::{mem, ptr};
@ -19,7 +19,7 @@ pub type PyCFunction =
pub type _PyCFunctionFast = unsafe extern "C" fn(
slf: *mut PyObject,
args: *mut *mut PyObject,
nargs: crate::ffi3::pyport::Py_ssize_t,
nargs: crate::ffi::pyport::Py_ssize_t,
kwnames: *mut PyObject,
) -> *mut PyObject;

View File

@ -1,9 +1,157 @@
#![allow(non_camel_case_types, non_upper_case_globals, non_snake_case)]
pub use crate::ffi3::*;
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
#![cfg_attr(Py_LIMITED_API, allow(unused_imports))]
#![cfg_attr(feature="cargo-clippy", allow(clippy::inline_always))]
pub use self::bltinmodule::*;
pub use self::boolobject::*;
pub use self::bytearrayobject::*;
pub use self::bytesobject::*;
pub use self::ceval::*;
pub use self::code::*;
pub use self::codecs::*;
pub use self::compile::*;
pub use self::complexobject::*;
pub use self::datetime::*;
pub use self::descrobject::*;
pub use self::dictobject::*;
pub use self::enumobject::*;
pub use self::eval::*;
pub use self::fileobject::*;
pub use self::floatobject::*;
pub use self::frameobject::PyFrameObject;
pub use self::genobject::*;
pub use self::import::*;
pub use self::intrcheck::*;
pub use self::iterobject::*;
pub use self::listobject::*;
pub use self::longobject::*;
pub use self::marshal::*;
pub use self::memoryobject::*;
pub use self::methodobject::*;
pub use self::modsupport::*;
pub use self::moduleobject::*;
pub use self::object::*;
pub use self::objectabstract::*;
pub use self::objimpl::*;
#[cfg(Py_3_6)]
pub use self::osmodule::*;
pub use self::pyarena::*;
pub use self::pycapsule::*;
pub use self::pydebug::*;
pub use self::pyerrors::*;
pub use self::pyhash::*;
pub use self::pymem::*;
pub use self::pyport::*;
pub use self::pystate::*;
pub use self::pystrtod::*;
pub use self::pythonrun::*;
pub use self::rangeobject::*;
pub use self::setobject::*;
pub use self::sliceobject::*;
pub use self::structseq::*;
pub use self::sysmodule::*;
pub use self::traceback::*;
pub use self::tupleobject::*;
pub use self::typeslots::*;
pub use self::unicodeobject::*;
pub use self::warnings::*;
pub use self::weakrefobject::*;
mod pyport;
// mod pymacro; contains nothing of interest for Rust
// mod pyatomic; contains nothing of interest for Rust
// mod pymath; contains nothing of interest for Rust
// [cfg(not(Py_LIMITED_API))]
// mod pytime; contains nothing of interest
mod pymem;
mod object;
mod objimpl;
mod pydebug;
mod pyhash;
mod typeslots;
mod bytearrayobject;
mod bytesobject;
mod longobject;
mod unicodeobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod longintrepr; TODO excluded by PEP-384
mod boolobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod complexobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod dictobject;
mod floatobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod listobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod memoryobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod rangeobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod tupleobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod odictobject; TODO new in 3.5
mod enumobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod methodobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod moduleobject;
mod setobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod funcobject; TODO excluded by PEP-384
// mod classobject; TODO excluded by PEP-384
mod fileobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod pycapsule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod sliceobject;
mod traceback; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod cellobject; TODO excluded by PEP-384
mod descrobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod genobject; // TODO excluded by PEP-384
mod iterobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod structseq;
mod warnings; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod weakrefobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod namespaceobject; TODO
mod codecs; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod pyerrors; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod pystate; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(Py_LIMITED_API)]
mod pyarena {}
mod modsupport; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(not(Py_LIMITED_API))]
mod pyarena; // TODO: incomplete
mod pythonrun; // TODO some functions need to be moved to pylifecycle
//mod pylifecycle; // TODO new in 3.5
mod ceval; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod import;
mod intrcheck; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(Py_3_6)]
mod osmodule;
mod sysmodule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod bltinmodule;
mod objectabstract; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(Py_LIMITED_API)]
mod code {}
#[cfg(not(Py_LIMITED_API))]
mod code;
mod compile; // TODO: incomplete
mod eval; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod pyctype; TODO excluded by PEP-384
mod pystrtod; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod pystrcmp; TODO nothing interesting for Rust?
// mod dtoa; TODO excluded by PEP-384
// mod fileutils; TODO no public functions?
// mod pyfpe; TODO probably not interesting for rust
// Additional headers that are not exported by Python.h
pub mod structmember; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(not(Py_LIMITED_API))]
pub mod frameobject;
#[cfg(Py_LIMITED_API)]
pub mod frameobject {
pub enum PyFrameObject {}
}
pub(crate) mod datetime;
pub(crate) mod marshal;

View File

@ -1,7 +1,7 @@
use crate::ffi3::methodobject::PyMethodDef;
use crate::ffi3::moduleobject::PyModuleDef;
use crate::ffi3::object::PyObject;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::methodobject::PyMethodDef;
use crate::ffi::moduleobject::PyModuleDef;
use crate::ffi::object::PyObject;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int, c_long};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,6 +1,6 @@
use crate::ffi3::methodobject::PyMethodDef;
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::methodobject::PyMethodDef;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int, c_void};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,4 +1,4 @@
use crate::ffi3::pyport::{Py_hash_t, Py_ssize_t};
use crate::ffi::pyport::{Py_hash_t, Py_ssize_t};
#[cfg(PyPy)]
use std::ffi::CStr;
use std::mem;
@ -77,8 +77,8 @@ pub unsafe fn Py_REFCNT(ob: *mut PyObject) -> Py_ssize_t {
#[cfg(PyPy)]
pub unsafe fn _PyObject_NextNotImplemented(arg1: *mut PyObject) -> *mut PyObject {
return crate::ffi3::pyerrors::PyErr_Format(
crate::ffi3::pyerrors::PyExc_TypeError,
return crate::ffi::pyerrors::PyErr_Format(
crate::ffi::pyerrors::PyExc_TypeError,
CStr::from_bytes_with_nul(b"'%.200s' object is not iterable\0")
.unwrap()
.as_ptr(),
@ -132,7 +132,7 @@ pub type objobjargproc =
#[cfg(not(Py_LIMITED_API))]
mod bufferinfo {
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::pyport::Py_ssize_t;
use std::mem;
use std::os::raw::{c_char, c_int, c_void};
@ -140,7 +140,7 @@ mod bufferinfo {
#[derive(Copy, Clone)]
pub struct Py_buffer {
pub buf: *mut c_void,
pub obj: *mut crate::ffi3::PyObject,
pub obj: *mut crate::ffi::PyObject,
pub len: Py_ssize_t,
pub itemsize: Py_ssize_t,
pub readonly: c_int,
@ -160,12 +160,12 @@ mod bufferinfo {
}
pub type getbufferproc = unsafe extern "C" fn(
arg1: *mut crate::ffi3::PyObject,
arg1: *mut crate::ffi::PyObject,
arg2: *mut Py_buffer,
arg3: c_int,
) -> c_int;
pub type releasebufferproc =
unsafe extern "C" fn(arg1: *mut crate::ffi3::PyObject, arg2: *mut Py_buffer) -> ();
unsafe extern "C" fn(arg1: *mut crate::ffi::PyObject, arg2: *mut Py_buffer) -> ();
/// Maximum number of dimensions
pub const PyBUF_MAX_NDIM: c_int = 64;
@ -249,8 +249,8 @@ mod typeobject {
#[cfg(not(Py_LIMITED_API))]
mod typeobject {
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi3::{self, object};
use crate::ffi::pyport::Py_ssize_t;
use crate::ffi::{self, object};
use std::mem;
use std::os::raw::{c_char, c_uint, c_ulong, c_void};
use std::ptr;
@ -485,27 +485,27 @@ mod typeobject {
pub tp_weaklistoffset: Py_ssize_t,
pub tp_iter: Option<object::getiterfunc>,
pub tp_iternext: Option<object::iternextfunc>,
pub tp_methods: *mut ffi3::methodobject::PyMethodDef,
pub tp_members: *mut ffi3::structmember::PyMemberDef,
pub tp_getset: *mut ffi3::descrobject::PyGetSetDef,
pub tp_methods: *mut ffi::methodobject::PyMethodDef,
pub tp_members: *mut ffi::structmember::PyMemberDef,
pub tp_getset: *mut ffi::descrobject::PyGetSetDef,
pub tp_base: *mut PyTypeObject,
pub tp_dict: *mut ffi3::object::PyObject,
pub tp_descr_get: Option<ffi3::object::descrgetfunc>,
pub tp_descr_set: Option<ffi3::object::descrsetfunc>,
pub tp_dict: *mut ffi::object::PyObject,
pub tp_descr_get: Option<ffi::object::descrgetfunc>,
pub tp_descr_set: Option<ffi::object::descrsetfunc>,
pub tp_dictoffset: Py_ssize_t,
pub tp_init: Option<ffi3::object::initproc>,
pub tp_alloc: Option<ffi3::object::allocfunc>,
pub tp_new: Option<ffi3::object::newfunc>,
pub tp_free: Option<ffi3::object::freefunc>,
pub tp_is_gc: Option<ffi3::object::inquiry>,
pub tp_bases: *mut ffi3::object::PyObject,
pub tp_mro: *mut ffi3::object::PyObject,
pub tp_cache: *mut ffi3::object::PyObject,
pub tp_subclasses: *mut ffi3::object::PyObject,
pub tp_weaklist: *mut ffi3::object::PyObject,
pub tp_del: Option<ffi3::object::destructor>,
pub tp_init: Option<ffi::object::initproc>,
pub tp_alloc: Option<ffi::object::allocfunc>,
pub tp_new: Option<ffi::object::newfunc>,
pub tp_free: Option<ffi::object::freefunc>,
pub tp_is_gc: Option<ffi::object::inquiry>,
pub tp_bases: *mut ffi::object::PyObject,
pub tp_mro: *mut ffi::object::PyObject,
pub tp_cache: *mut ffi::object::PyObject,
pub tp_subclasses: *mut ffi::object::PyObject,
pub tp_weaklist: *mut ffi::object::PyObject,
pub tp_del: Option<ffi::object::destructor>,
pub tp_version_tag: c_uint,
pub tp_finalize: Option<ffi3::object::destructor>,
pub tp_finalize: Option<ffi::object::destructor>,
#[cfg(PyPy)]
pub tp_pypy_flags: ::std::os::raw::c_long,
#[cfg(py_sys_config = "COUNT_ALLOCS")]
@ -543,7 +543,7 @@ mod typeobject {
tp_getattro: None,
tp_setattro: None,
tp_as_buffer: ptr::null_mut(),
tp_flags: ffi3::object::Py_TPFLAGS_DEFAULT,
tp_flags: ffi::object::Py_TPFLAGS_DEFAULT,
tp_doc: ptr::null(),
tp_traverse: None,
tp_clear: None,
@ -597,8 +597,8 @@ mod typeobject {
macro_rules! py_type_object_init {
($tp_as_async:ident, $($tail:tt)*) => {
_type_object_init!({
ob_base: ffi3::object::PyVarObject {
ob_base: ffi3::object::PyObject_HEAD_INIT,
ob_base: ffi::object::PyVarObject {
ob_base: ffi::object::PyObject_HEAD_INIT,
ob_size: 0
},}
$tp_as_async,
@ -640,9 +640,9 @@ mod typeobject {
pub as_mapping: PyMappingMethods,
pub as_sequence: PySequenceMethods,
pub as_buffer: PyBufferProcs,
pub ht_name: *mut ffi3::object::PyObject,
pub ht_slots: *mut ffi3::object::PyObject,
pub ht_qualname: *mut ffi3::object::PyObject,
pub ht_name: *mut ffi::object::PyObject,
pub ht_slots: *mut ffi::object::PyObject,
pub ht_qualname: *mut ffi::object::PyObject,
pub ht_cached_keys: *mut c_void,
}
@ -656,10 +656,10 @@ mod typeobject {
#[inline]
pub unsafe fn PyHeapType_GET_MEMBERS(
etype: *mut PyHeapTypeObject,
) -> *mut ffi3::structmember::PyMemberDef {
let py_type = ffi3::object::Py_TYPE(etype as *mut ffi3::object::PyObject);
) -> *mut ffi::structmember::PyMemberDef {
let py_type = ffi::object::Py_TYPE(etype as *mut ffi::object::PyObject);
let ptr = etype.offset((*py_type).tp_basicsize);
ptr as *mut ffi3::structmember::PyMemberDef
ptr as *mut ffi::structmember::PyMemberDef
}
}

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int, c_void};
use std::ptr;
@ -161,7 +161,7 @@ pub unsafe fn PyIter_Check(o: *mut PyObject) -> c_int {
(match (*(*o).ob_type).tp_iternext {
Some(tp_iternext) => {
tp_iternext as *const c_void
!= crate::ffi3::object::_PyObject_NextNotImplemented as *const c_void
!= crate::ffi::object::_PyObject_NextNotImplemented as *const c_void
}
None => false,
}) as c_int

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use libc::size_t;
use std::os::raw::{c_int, c_void};

View File

@ -1,5 +1,5 @@
// This header is new in Python 3.6
use crate::ffi3::object::PyObject;
use crate::ffi::object::PyObject;
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::*;
use crate::ffi::object::*;
use std::os::raw::{c_char, c_int, c_void};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,7 +1,7 @@
use crate::ffi3::object::*;
use crate::ffi::object::*;
#[cfg(PyPy)]
use crate::ffi3::objectabstract::PyObject_CallFunction;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::objectabstract::PyObject_CallFunction;
use crate::ffi::pyport::Py_ssize_t;
#[cfg(PyPy)]
use std::ffi::CStr;
use std::os::raw::{c_char, c_int};

View File

@ -1,4 +1,4 @@
use crate::ffi3::pyport::{Py_hash_t, Py_ssize_t};
use crate::ffi::pyport::{Py_hash_t, Py_ssize_t};
use std::os::raw::{c_char, c_int, c_void};
#[repr(C)]

View File

@ -1,7 +1,7 @@
#[cfg(Py_3_6)]
use crate::ffi3::ceval::_PyFrameEvalFunction;
use crate::ffi3::moduleobject::PyModuleDef;
use crate::ffi3::object::PyObject;
use crate::ffi::ceval::_PyFrameEvalFunction;
use crate::ffi::moduleobject::PyModuleDef;
use crate::ffi::object::PyObject;
use std::os::raw::{c_int, c_long};
#[cfg(Py_3_6)]

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::PyObject;
use crate::ffi::object::PyObject;
use std::os::raw::{c_char, c_double, c_int};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,7 +1,7 @@
use crate::ffi3::object::*;
use crate::ffi::object::*;
#[cfg(not(Py_LIMITED_API))]
use crate::ffi3::pyarena::PyArena;
use crate::ffi3::pystate::PyThreadState;
use crate::ffi::pyarena::PyArena;
use crate::ffi::pystate::PyThreadState;
use libc::{wchar_t, FILE};
use std::os::raw::{c_char, c_int};
use std::ptr;

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::*;
use crate::ffi::object::*;
use std::os::raw::c_int;
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::c_int;
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::c_int;
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::PyObject;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::PyObject;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int};
#[repr(C)]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::{PyObject, PyTypeObject};
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::{PyObject, PyTypeObject};
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int};
#[repr(C)]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::PyObject;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::PyObject;
use crate::ffi::pyport::Py_ssize_t;
use libc::wchar_t;
use std::os::raw::{c_char, c_int};

View File

@ -1,10 +1,10 @@
use crate::ffi3::object::*;
use crate::ffi::object::*;
use std::os::raw::c_int;
#[cfg_attr(windows, link(name = "pythonXY"))]
extern "C" {
#[cfg_attr(PyPy, link_name = "PyPyTraceBack_Here")]
pub fn PyTraceBack_Here(arg1: *mut crate::ffi3::PyFrameObject) -> c_int;
pub fn PyTraceBack_Here(arg1: *mut crate::ffi::PyFrameObject) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyTraceBack_Print")]
pub fn PyTraceBack_Print(arg1: *mut PyObject, arg2: *mut PyObject) -> c_int;
#[cfg_attr(PyPy, link_name = "PyPyTraceBack_Type")]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::c_int;
#[repr(C)]

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::*;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::*;
use crate::ffi::pyport::Py_ssize_t;
use libc::wchar_t;
use std::os::raw::{c_char, c_int, c_void};

View File

@ -1,5 +1,5 @@
use crate::ffi3::object::PyObject;
use crate::ffi3::pyport::Py_ssize_t;
use crate::ffi::object::PyObject;
use crate::ffi::pyport::Py_ssize_t;
use std::os::raw::{c_char, c_int};
#[cfg_attr(windows, link(name = "pythonXY"))]

View File

@ -1,4 +1,4 @@
use crate::ffi3::object::*;
use crate::ffi::object::*;
use std::os::raw::c_int;
pub enum PyWeakReference {}

View File

@ -1,153 +0,0 @@
//! Rust FFI declarations for Python 3
#![allow(non_camel_case_types, non_snake_case, non_upper_case_globals)]
#![cfg_attr(Py_LIMITED_API, allow(unused_imports))]
#![cfg_attr(feature="cargo-clippy", allow(clippy::inline_always))]
pub use self::bltinmodule::*;
pub use self::boolobject::*;
pub use self::bytearrayobject::*;
pub use self::bytesobject::*;
pub use self::ceval::*;
pub use self::code::*;
pub use self::codecs::*;
pub use self::compile::*;
pub use self::complexobject::*;
pub use self::descrobject::*;
pub use self::dictobject::*;
pub use self::enumobject::*;
pub use self::eval::*;
pub use self::fileobject::*;
pub use self::floatobject::*;
pub use self::frameobject::PyFrameObject;
pub use self::genobject::*;
pub use self::import::*;
pub use self::intrcheck::*;
pub use self::iterobject::*;
pub use self::listobject::*;
pub use self::longobject::*;
pub use self::memoryobject::*;
pub use self::methodobject::*;
pub use self::modsupport::*;
pub use self::moduleobject::*;
pub use self::object::*;
pub use self::objectabstract::*;
pub use self::objimpl::*;
#[cfg(Py_3_6)]
pub use self::osmodule::*;
pub use self::pyarena::*;
pub use self::pycapsule::*;
pub use self::pydebug::*;
pub use self::pyerrors::*;
pub use self::pyhash::*;
pub use self::pymem::*;
pub use self::pyport::*;
pub use self::pystate::*;
pub use self::pystrtod::*;
pub use self::pythonrun::*;
pub use self::rangeobject::*;
pub use self::setobject::*;
pub use self::sliceobject::*;
pub use self::structseq::*;
pub use self::sysmodule::*;
pub use self::traceback::*;
pub use self::tupleobject::*;
pub use self::typeslots::*;
pub use self::unicodeobject::*;
pub use self::warnings::*;
pub use self::weakrefobject::*;
mod pyport;
// mod pymacro; contains nothing of interest for Rust
// mod pyatomic; contains nothing of interest for Rust
// mod pymath; contains nothing of interest for Rust
// [cfg(not(Py_LIMITED_API))]
// mod pytime; contains nothing of interest
mod pymem;
mod object;
mod objimpl;
mod pydebug;
mod pyhash;
mod typeslots;
mod bytearrayobject;
mod bytesobject;
mod longobject;
mod unicodeobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod longintrepr; TODO excluded by PEP-384
mod boolobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod complexobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod dictobject;
mod floatobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod listobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod memoryobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod rangeobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod tupleobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod odictobject; TODO new in 3.5
mod enumobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod methodobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod moduleobject;
mod setobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod funcobject; TODO excluded by PEP-384
// mod classobject; TODO excluded by PEP-384
mod fileobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod pycapsule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod sliceobject;
mod traceback; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod cellobject; TODO excluded by PEP-384
mod descrobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod genobject; // TODO excluded by PEP-384
mod iterobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod structseq;
mod warnings; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod weakrefobject; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod namespaceobject; TODO
mod codecs; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod pyerrors; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod pystate; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(Py_LIMITED_API)]
mod pyarena {}
mod modsupport; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(not(Py_LIMITED_API))]
mod pyarena; // TODO: incomplete
mod pythonrun; // TODO some functions need to be moved to pylifecycle
//mod pylifecycle; // TODO new in 3.5
mod ceval; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod import;
mod intrcheck; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(Py_3_6)]
mod osmodule;
mod sysmodule; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
mod bltinmodule;
mod objectabstract; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(Py_LIMITED_API)]
mod code {}
#[cfg(not(Py_LIMITED_API))]
mod code;
mod compile; // TODO: incomplete
mod eval; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod pyctype; TODO excluded by PEP-384
mod pystrtod; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
// mod pystrcmp; TODO nothing interesting for Rust?
// mod dtoa; TODO excluded by PEP-384
// mod fileutils; TODO no public functions?
// mod pyfpe; TODO probably not interesting for rust
// Additional headers that are not exported by Python.h
pub mod structmember; // TODO supports PEP-384 only; needs adjustment for Python 3.3 and 3.5
#[cfg(not(Py_LIMITED_API))]
pub mod frameobject;
#[cfg(Py_LIMITED_API)]
pub mod frameobject {
pub enum PyFrameObject {}
}

View File

@ -111,7 +111,7 @@ impl Drop for GILGuard {
fn drop(&mut self) {
unsafe {
let pool: &'static mut ReleasePool = &mut *POOL;
pool.drain(self.owned, self.borrowed, true);
pool.drain(self.python(), self.owned, self.borrowed, true);
ffi::PyGILState_Release(self.gstate);
}
@ -156,7 +156,7 @@ impl ReleasePool {
vec.set_len(0);
}
pub unsafe fn drain(&mut self, owned: usize, borrowed: usize, pointers: bool) {
pub unsafe fn drain(&mut self, _py: Python, owned: usize, borrowed: usize, pointers: bool) {
// Release owned objects(call decref)
while owned < self.owned.len() {
let last = self.owned.pop_back().unwrap();
@ -176,35 +176,31 @@ impl ReleasePool {
static mut POOL: *mut ReleasePool = ::std::ptr::null_mut();
#[doc(hidden)]
pub struct GILPool {
pub struct GILPool<'p> {
py: Python<'p>,
owned: usize,
borrowed: usize,
pointers: bool,
no_send: marker::PhantomData<rc::Rc<()>>,
}
impl Default for GILPool {
impl<'p> GILPool<'p> {
#[inline]
fn default() -> GILPool {
pub fn new(py: Python) -> GILPool {
let p: &'static mut ReleasePool = unsafe { &mut *POOL };
GILPool {
py,
owned: p.owned.len(),
borrowed: p.borrowed.len(),
pointers: true,
no_send: marker::PhantomData,
}
}
}
impl GILPool {
#[inline]
pub fn new() -> GILPool {
GILPool::default()
}
#[inline]
pub fn new_no_pointers() -> GILPool {
pub fn new_no_pointers(py: Python) -> GILPool {
let p: &'static mut ReleasePool = unsafe { &mut *POOL };
GILPool {
py,
owned: p.owned.len(),
borrowed: p.borrowed.len(),
pointers: false,
@ -213,11 +209,11 @@ impl GILPool {
}
}
impl Drop for GILPool {
impl<'p> Drop for GILPool<'p> {
fn drop(&mut self) {
unsafe {
let pool: &'static mut ReleasePool = &mut *POOL;
pool.drain(self.owned, self.borrowed, self.pointers);
pool.drain(self.py, self.owned, self.borrowed, self.pointers);
}
}
}
@ -394,7 +390,7 @@ mod test {
let p: &'static mut ReleasePool = &mut *POOL;
{
let _pool = GILPool::new();
let _pool = GILPool::new(py);
assert_eq!(p.owned.len(), 0);
let _ = gil::register_owned(py, obj.into_nonnull());
@ -402,7 +398,7 @@ mod test {
assert_eq!(p.owned.len(), 1);
assert_eq!(ffi::Py_REFCNT(obj_ptr), 2);
{
let _pool = GILPool::new();
let _pool = GILPool::new(py);
let obj = get_object();
let _ = gil::register_owned(py, obj.into_nonnull());
assert_eq!(p.owned.len(), 2);
@ -463,7 +459,7 @@ mod test {
assert_eq!(ffi::Py_REFCNT(obj_ptr), 1);
{
let _pool = GILPool::new();
let _pool = GILPool::new(py);
assert_eq!(p.borrowed.len(), 1);
gil::register_borrowed(py, NonNull::new(obj_ptr).unwrap());
assert_eq!(p.borrowed.len(), 2);

View File

@ -48,7 +48,7 @@
//! crate-type = ["cdylib"]
//!
//! [dependencies.pyo3]
//! version = "0.7.0"
//! version = "0.8.0"
//! features = ["extension-module"]
//! ```
//!
@ -85,7 +85,7 @@
//!
//! For developing, you can copy and rename the shared library from the target folder: On macOS, rename `libstring_sum.dylib` to `string_sum.so`, on windows `libstring_sum.dll` to `string_sum.pyd` and on linux `libstring_sum.so` to `string_sum.so`. Then open a python shell in the same folder and you'll be able to `import string_sum`.
//!
//! To build, test and publish your crate as python module, you can use [pyo3-pack](https://github.com/PyO3/pyo3-pack) or [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an example for setuptools-rust in [examples/word-count](examples/word-count), while pyo3-pack should work on your crate without any configuration.
//! To build, test and publish your crate as python module, you can use [maturin](https://github.com/PyO3/maturin) or [setuptools-rust](https://github.com/PyO3/setuptools-rust). You can find an example for setuptools-rust in [examples/word-count](examples/word-count), while maturin should work on your crate without any configuration.
//!
//! ## Using python from rust
//!
@ -93,7 +93,7 @@
//!
//! ```toml
//! [dependencies]
//! pyo3 = "0.7.0"
//! pyo3 = "0.8.0"
//! ```
//!
//! Example program displaying the value of `sys.version`:
@ -149,8 +149,6 @@ pub use unindent;
/// Raw ffi declarations for the c interface of python
pub mod ffi;
mod ffi3;
pub mod buffer;
#[doc(hidden)]
pub mod callback;

View File

@ -420,8 +420,8 @@ unsafe extern "C" fn tp_dealloc_callback<T>(obj: *mut ffi::PyObject)
where
T: PyObjectAlloc,
{
let _pool = gil::GILPool::new_no_pointers();
let py = Python::assume_gil_acquired();
let _pool = gil::GILPool::new_no_pointers(py);
<T as PyObjectAlloc>::dealloc(py, obj)
}
fn py_class_flags<T: PyTypeInfo>(type_object: &mut ffi::PyTypeObject) {

View File

@ -416,7 +416,7 @@ mod test {
let cnt;
{
let _pool = crate::GILPool::new();
let _pool = crate::GILPool::new(py);
let none = py.None();
cnt = none.get_refcnt();
let _dict = [(10, none)].into_py_dict(py);

View File

@ -140,7 +140,7 @@ mod tests {
let none;
let count;
{
let _pool = GILPool::new();
let _pool = GILPool::new(py);
let l = PyList::empty(py);
none = py.None();
l.append(10).unwrap();
@ -150,7 +150,7 @@ mod tests {
}
{
let _pool = GILPool::new();
let _pool = GILPool::new(py);
let inst = obj.as_ref(py);
let mut it = inst.iter().unwrap();

View File

@ -278,7 +278,7 @@ mod test {
let cnt;
{
let _pool = crate::GILPool::new();
let _pool = crate::GILPool::new(py);
let v = vec![2];
let ob = v.to_object(py);
let list = <PyList as PyTryFrom>::try_from(ob.as_ref(py)).unwrap();
@ -313,7 +313,7 @@ mod test {
let cnt;
{
let _pool = crate::GILPool::new();
let _pool = crate::GILPool::new(py);
let list = PyList::empty(py);
let none = py.None();
cnt = none.get_refcnt();
@ -342,7 +342,7 @@ mod test {
let cnt;
{
let _pool = crate::GILPool::new();
let _pool = crate::GILPool::new(py);
let list = PyList::empty(py);
let none = py.None();
cnt = none.get_refcnt();

View File

@ -232,6 +232,28 @@ impl MethArgs {
) -> PyResult<PyObject> {
Ok([args.into(), kwargs.to_object(py)].to_object(py))
}
#[args(args = "*", kwargs = "**")]
fn get_pos_arg_kw(
&self,
py: Python,
a: i32,
args: &PyTuple,
kwargs: Option<&PyDict>,
) -> PyObject {
[a.to_object(py), args.into(), kwargs.to_object(py)].to_object(py)
}
#[args(kwargs = "**")]
fn get_pos_kw(&self, py: Python, a: i32, kwargs: Option<&PyDict>) -> PyObject {
[a.to_object(py), kwargs.to_object(py)].to_object(py)
}
// "args" can be anything that can be extracted from PyTuple
#[args(args = "*")]
fn args_as_vec(&self, args: Vec<i32>) -> i32 {
args.iter().sum()
}
}
#[test]
@ -259,6 +281,27 @@ fn meth_args() {
inst,
"assert inst.get_kwargs(1,2,3,t=1,n=2) == [(1,2,3), {'t': 1, 'n': 2}]"
);
py_run!(py, inst, "assert inst.get_pos_arg_kw(1) == [1, (), None]");
py_run!(
py,
inst,
"assert inst.get_pos_arg_kw(1, 2, 3) == [1, (2, 3), None]"
);
py_run!(
py,
inst,
"assert inst.get_pos_arg_kw(1, b=2) == [1, (), {'b': 2}]"
);
py_run!(py, inst, "assert inst.get_pos_arg_kw(a=1) == [1, (), None]");
py_expect_exception!(py, inst, "inst.get_pos_arg_kw()", TypeError);
py_expect_exception!(py, inst, "inst.get_pos_arg_kw(1, a=1)", TypeError);
py_expect_exception!(py, inst, "inst.get_pos_arg_kw(b=2)", TypeError);
py_run!(py, inst, "assert inst.get_pos_kw(1, b=2) == [1, {'b': 2}]");
py_expect_exception!(py, inst, "inst.get_pos_kw(1,2)", TypeError);
py_run!(py, inst, "assert inst.args_as_vec(1,2,3) == 6");
}
#[pyclass]

View File

@ -1,6 +1,6 @@
use pyo3::prelude::*;
use pyo3::types::IntoPyDict;
use pyo3::types::{IntoPyDict, PyTuple};
mod common;
@ -194,3 +194,35 @@ fn test_module_nesting() {
"supermodule.submodule.subfunction() == 'Subfunction'"
);
}
// Test that argument parsing specification works for pyfunctions
#[pyfunction(a = 5, vararg = "*")]
fn ext_vararg_fn(py: Python, a: i32, vararg: &PyTuple) -> PyObject {
[a.to_object(py), vararg.into()].to_object(py)
}
#[pymodule]
fn vararg_module(_py: Python, m: &PyModule) -> PyResult<()> {
#[pyfn(m, "int_vararg_fn", a = 5, vararg = "*")]
fn int_vararg_fn(py: Python, a: i32, vararg: &PyTuple) -> PyObject {
ext_vararg_fn(py, a, vararg)
}
m.add_wrapped(pyo3::wrap_pyfunction!(ext_vararg_fn))
.unwrap();
Ok(())
}
#[test]
fn test_vararg_module() {
let gil = Python::acquire_gil();
let py = gil.python();
let m = pyo3::wrap_pymodule!(vararg_module)(py);
py_assert!(py, m, "m.ext_vararg_fn() == [5, ()]");
py_assert!(py, m, "m.ext_vararg_fn(1, 2) == [1, (2,)]");
py_assert!(py, m, "m.int_vararg_fn() == [5, ()]");
py_assert!(py, m, "m.int_vararg_fn(1, 2) == [1, (2,)]");
}

View File

@ -20,6 +20,9 @@ impl Reader {
fn clone_ref(slf: PyRef<Self>) -> PyRef<Self> {
slf
}
fn clone_ref_with_py<'py>(slf: PyRef<'py, Self>, _py: Python<'py>) -> PyRef<'py, Self> {
slf
}
fn get_iter(slf: PyRef<Self>, keys: Py<PyBytes>) -> PyResult<Iter> {
Ok(Iter {
reader: slf.into(),
@ -98,6 +101,7 @@ fn test_clone_ref() {
let py = gil.python();
let reader: PyObject = reader().into_py(py);
py_assert!(py, reader, "reader == reader.clone_ref()");
py_assert!(py, reader, "reader == reader.clone_ref_with_py()");
}
#[test]