Skip to content

Commit

Permalink
Merge branch 'main' into with-type-info
Browse files Browse the repository at this point in the history
  • Loading branch information
op8867555 committed Feb 9, 2023
2 parents 7ff993e + 5d1e219 commit c6210e6
Show file tree
Hide file tree
Showing 29 changed files with 349 additions and 60 deletions.
26 changes: 25 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,28 @@ To see unreleased changes, please see the [CHANGELOG on the main branch guide](h

<!-- towncrier release notes start -->

## [0.18.1] - 2023-02-07

### Added

- Add `PyErr::write_unraisable()`. [#2889](https://github.com/PyO3/pyo3/pull/2889)
- Add `Python::Ellipsis()` and `PyAny::is_ellipsis()` methods. [#2911](https://github.com/PyO3/pyo3/pull/2911)
- Add `PyDict::update()` and `PyDict::update_if_missing()` methods. [#2912](https://github.com/PyO3/pyo3/pull/2912)

### Changed

- FFI definition `PyIter_Check` on CPython 3.7 is now implemented as `hasattr(type(obj), "__next__")`, which works correctly on all platforms and adds support for `abi3`. [#2914](https://github.com/PyO3/pyo3/pull/2914)
- Warn about unknown config keys in `PYO3_CONFIG_FILE` instead of denying. [#2926](https://github.com/PyO3/pyo3/pull/2926)

### Fixed

- Send errors returned by `__releasebuffer__` to `sys.unraisablehook` rather than causing `SystemError`. [#2886](https://github.com/PyO3/pyo3/pull/2886)
- Fix downcast to `PyIterator` succeeding for Python classes which did not implement `__next__`. [#2914](https://github.com/PyO3/pyo3/pull/2914)
- Fix segfault in `__traverse__` when visiting `None` fields of `Option<T: AsPyPointer>`. [#2921](https://github.com/PyO3/pyo3/pull/2921)
- Fix `#[pymethods(crate = "...")]` option being ignored. [#2923](https://github.com/PyO3/pyo3/pull/2923)
- Link against `pythonXY_d.dll` for debug Python builds on Windows. [#2937](https://github.com/PyO3/pyo3/pull/2937)


## [0.18.0] - 2023-01-17

### Packaging
Expand Down Expand Up @@ -124,6 +146,7 @@ To see unreleased changes, please see the [CHANGELOG on the main branch guide](h
- Add `PyCode` and `PyFrame` high level objects. [#2408](https://github.com/PyO3/pyo3/pull/2408)
- Add FFI definitions `Py_fstring_input`, `sendfunc`, and `_PyErr_StackItem`. [#2423](https://github.com/PyO3/pyo3/pull/2423)
- Add `PyDateTime::new_with_fold`, `PyTime::new_with_fold`, `PyTime::get_fold`, and `PyDateTime::get_fold` for PyPy. [#2428](https://github.com/PyO3/pyo3/pull/2428)
- Add `#[pyclass(frozen)]`. [#2448](https://github.com/PyO3/pyo3/pull/2448)
- Accept `#[pyo3(name)]` on enum variants. [#2457](https://github.com/PyO3/pyo3/pull/2457)
- Add `CompareOp::matches` to implement `__richcmp__` as the result of a Rust `std::cmp::Ordering` comparison. [#2460](https://github.com/PyO3/pyo3/pull/2460)
- Add `PySuper` type. [#2486](https://github.com/PyO3/pyo3/pull/2486)
Expand Down Expand Up @@ -1369,7 +1392,8 @@ Yanked

- Initial release

[Unreleased]: https://github.com/pyo3/pyo3/compare/v0.18.0...HEAD
[Unreleased]: https://github.com/pyo3/pyo3/compare/v0.18.1...HEAD
[0.18.1]: https://github.com/pyo3/pyo3/compare/v0.18.0...v0.18.1
[0.18.0]: https://github.com/pyo3/pyo3/compare/v0.17.3...v0.18.0
[0.17.3]: https://github.com/pyo3/pyo3/compare/v0.17.2...v0.17.3
[0.17.2]: https://github.com/pyo3/pyo3/compare/v0.17.1...v0.17.2
Expand Down
8 changes: 4 additions & 4 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pyo3"
version = "0.18.0"
version = "0.18.1"
description = "Bindings to Python interpreter"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
readme = "README.md"
Expand All @@ -20,10 +20,10 @@ parking_lot = ">= 0.11, < 0.13"
memoffset = "0.8"

# ffi bindings to the python interpreter, split into a separate crate so they can be used independently
pyo3-ffi = { path = "pyo3-ffi", version = "=0.18.0" }
pyo3-ffi = { path = "pyo3-ffi", version = "=0.18.1" }

# support crates for macros feature
pyo3-macros = { path = "pyo3-macros", version = "=0.18.0", optional = true }
pyo3-macros = { path = "pyo3-macros", version = "=0.18.1", optional = true }
indoc = { version = "1.0.3", optional = true }
unindent = { version = "0.1.4", optional = true }

Expand Down Expand Up @@ -56,7 +56,7 @@ rayon = "1.0.2"
widestring = "0.5.1"

[build-dependencies]
pyo3-build-config = { path = "pyo3-build-config", version = "0.18.0", features = ["resolve-config"] }
pyo3-build-config = { path = "pyo3-build-config", version = "0.18.1", features = ["resolve-config"] }

[features]
default = ["macros", "experimental-inspect"]
Expand Down
4 changes: 2 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ name = "string_sum"
crate-type = ["cdylib"]

[dependencies]
pyo3 = { version = "0.18.0", features = ["extension-module"] }
pyo3 = { version = "0.18.1", features = ["extension-module"] }
```

**`src/lib.rs`**
Expand Down Expand Up @@ -137,7 +137,7 @@ Start a new project with `cargo new` and add `pyo3` to the `Cargo.toml` like th

```toml
[dependencies.pyo3]
version = "0.18.0"
version = "0.18.1"
features = ["auto-initialize"]
```

Expand Down
2 changes: 1 addition & 1 deletion examples/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ publish = false
edition = "2018"

[dev-dependencies]
pyo3 = { version = "0.18.0", path = "..", features = ["auto-initialize", "extension-module"] }
pyo3 = { version = "0.18.1", path = "..", features = ["auto-initialize", "extension-module"] }

[[example]]
name = "decorator"
Expand Down
2 changes: 1 addition & 1 deletion examples/decorator/.template/pre-script.rhai
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
variable::set("PYO3_VERSION", "0.18.0");
variable::set("PYO3_VERSION", "0.18.1");
file::rename(".template/Cargo.toml", "Cargo.toml");
file::rename(".template/pyproject.toml", "pyproject.toml");
file::rename(".template/tox.ini", "tox.ini");
Expand Down
2 changes: 1 addition & 1 deletion examples/maturin-starter/.template/pre-script.rhai
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
variable::set("PYO3_VERSION", "0.18.0");
variable::set("PYO3_VERSION", "0.18.1");
file::rename(".template/Cargo.toml", "Cargo.toml");
file::rename(".template/pyproject.toml", "pyproject.toml");
file::rename(".template/tox.ini", "tox.ini");
Expand Down
2 changes: 1 addition & 1 deletion examples/plugin/.template/pre-script.rhai
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
variable::set("PYO3_VERSION", "0.18.0");
variable::set("PYO3_VERSION", "0.18.1");
file::rename(".template/Cargo.toml", "Cargo.toml");
file::rename(".template/plugin_api/Cargo.toml", "plugin_api/Cargo.toml");
file::delete(".template");
2 changes: 1 addition & 1 deletion examples/setuptools-rust-starter/.template/pre-script.rhai
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
variable::set("PYO3_VERSION", "0.18.0");
variable::set("PYO3_VERSION", "0.18.1");
file::rename(".template/Cargo.toml", "Cargo.toml");
file::rename(".template/setup.cfg", "setup.cfg");
file::rename(".template/tox.ini", "tox.ini");
Expand Down
2 changes: 1 addition & 1 deletion examples/word-count/.template/pre-script.rhai
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
variable::set("PYO3_VERSION", "0.18.0");
variable::set("PYO3_VERSION", "0.18.1");
file::rename(".template/Cargo.toml", "Cargo.toml");
file::rename(".template/tox.ini", "tox.ini");
file::delete(".template");
81 changes: 80 additions & 1 deletion guide/src/function/signature.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

The `#[pyfunction]` attribute also accepts parameters to control how the generated Python function accepts arguments. Just like in Python, arguments can be positional-only, keyword-only, or accept either. `*args` lists and `**kwargs` dicts can also be accepted. These parameters also work for `#[pymethods]` which will be introduced in the [Python Classes](../class.md) section of the guide.

Like Python, by default PyO3 accepts all arguments as either positional or keyword arguments. There are two ways to modify this behaviour:
Like Python, by default PyO3 accepts all arguments as either positional or keyword arguments. Most arguments are required by default, except for trailing `Option<_>` arguments, which are [implicitly given a default of `None`](#trailing-optional-arguments). There are two ways to modify this behaviour:
- The `#[pyo3(signature = (...))]` option which allows writing a signature in Python syntax.
- Extra arguments directly to `#[pyfunction]`. (See deprecated form)

Expand Down Expand Up @@ -77,6 +77,22 @@ impl MyClass {
}
}
```

Arguments of type `Python` must not be part of the signature:

```rust
# #![allow(dead_code)]
# use pyo3::prelude::*;
#[pyfunction]
#[pyo3(signature = (lambda))]
pub fn simple_python_bound_function(
py: Python<'_>,
lambda: PyObject,
) -> PyResult<()> {
Ok(())
}
```

N.B. the position of the `/` and `*` arguments (if included) control the system of handling positional and keyword arguments. In Python:
```python
import mymodule
Expand Down Expand Up @@ -106,6 +122,69 @@ num=-1
> }
> ```
## Trailing optional arguments
As a convenience, functions without a `#[pyo3(signature = (...))]` option will treat trailing `Option<T>` arguments as having a default of `None`. In the example below, PyO3 will create `increment` with a signature of `increment(x, amount=None)`.
```rust
use pyo3::prelude::*;
/// Returns a copy of `x` increased by `amount`.
///
/// If `amount` is unspecified or `None`, equivalent to `x + 1`.
#[pyfunction]
fn increment(x: u64, amount: Option<u64>) -> u64 {
x + amount.unwrap_or(1)
}
#
# fn main() -> PyResult<()> {
# Python::with_gil(|py| {
# let fun = pyo3::wrap_pyfunction!(increment, py)?;
#
# let inspect = PyModule::import(py, "inspect")?.getattr("signature")?;
# let sig: String = inspect
# .call1((fun,))?
# .call_method0("__str__")?
# .extract()?;
#
# #[cfg(Py_3_8)] // on 3.7 the signature doesn't render b, upstream bug?
# assert_eq!(sig, "(x, amount=Ellipsis)");
#
# Ok(())
# })
# }
```
To make trailing `Option<T>` arguments required, but still accept `None`, add a `#[pyo3(signature = (...))]` annotation. For the example above, this would be `#[pyo3(signature = (x, amount))]`:

```rust
# use pyo3::prelude::*;
#[pyfunction]
#[pyo3(signature = (x, amount))]
fn increment(x: u64, amount: Option<u64>) -> u64 {
x + amount.unwrap_or(1)
}
#
# fn main() -> PyResult<()> {
# Python::with_gil(|py| {
# let fun = pyo3::wrap_pyfunction!(increment, py)?;
#
# let inspect = PyModule::import(py, "inspect")?.getattr("signature")?;
# let sig: String = inspect
# .call1((fun,))?
# .call_method0("__str__")?
# .extract()?;
#
# #[cfg(Py_3_8)] // on 3.7 the signature doesn't render b, upstream bug?
# assert_eq!(sig, "(x, amount)");
#
# Ok(())
# })
# }
```

To help avoid confusion, PyO3 requires `#[pyo3(signature = (...))]` when an `Option<T>` argument is surrounded by arguments which aren't `Option<T>`.

## Deprecated form

The `#[pyfunction]` macro can take the argument specification directly, but this method is deprecated in PyO3 0.18 because the `#[pyo3(signature)]` option offers a simpler syntax and better validation.
Expand Down
2 changes: 1 addition & 1 deletion guide/src/getting_started.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ You should also create a `pyproject.toml` with the following contents:

```toml
[build-system]
requires = ["maturin>=0.13,<0.14"]
requires = ["maturin>=0.14,<0.15"]
build-backend = "maturin"

[project]
Expand Down
1 change: 0 additions & 1 deletion newsfragments/2886.fixed.md

This file was deleted.

1 change: 0 additions & 1 deletion newsfragments/2889.added.md

This file was deleted.

1 change: 0 additions & 1 deletion newsfragments/2911.added.md

This file was deleted.

1 change: 0 additions & 1 deletion newsfragments/2921.fixed.md

This file was deleted.

1 change: 0 additions & 1 deletion newsfragments/2923.fixed.md

This file was deleted.

1 change: 0 additions & 1 deletion newsfragments/2926.changed.md

This file was deleted.

2 changes: 1 addition & 1 deletion pyo3-build-config/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "pyo3-build-config"
version = "0.18.0"
version = "0.18.1"
description = "Build configuration for the PyO3 ecosystem"
authors = ["PyO3 Project and Contributors <https://github.com/PyO3>"]
keywords = ["pyo3", "python", "cpython", "ffi"]
Expand Down
51 changes: 45 additions & 6 deletions pyo3-build-config/src/impl_.rs
Original file line number Diff line number Diff line change
Expand Up @@ -230,6 +230,7 @@ print_if_set("base_prefix", base_prefix)
print("executable", sys.executable)
print("calcsize_pointer", struct.calcsize("P"))
print("mingw", get_platform().startswith("mingw"))
print("ext_suffix", get_config_var("EXT_SUFFIX"))
"#;
let output = run_python_script(interpreter.as_ref(), SCRIPT)?;
let map: HashMap<String, String> = parse_script_output(&output);
Expand Down Expand Up @@ -261,6 +262,10 @@ print("mingw", get_platform().startswith("mingw"))
implementation,
abi3,
map["mingw"].as_str() == "True",
// This is the best heuristic currently available to detect debug build
// on Windows from sysconfig - e.g. ext_suffix may be
// `_d.cp312-win_amd64.pyd` for 3.12 debug build
map["ext_suffix"].starts_with("_d."),
)
} else {
default_lib_name_unix(
Expand Down Expand Up @@ -1418,6 +1423,7 @@ fn default_abi3_config(host: &Triple, version: PythonVersion) -> InterpreterConf
implementation,
abi3,
false,
false,
))
} else {
None
Expand Down Expand Up @@ -1493,6 +1499,7 @@ fn default_lib_name_for_target(
implementation,
abi3,
false,
false,
))
} else if is_linking_libpython_for_target(target) {
Some(default_lib_name_unix(version, implementation, None))
Expand All @@ -1506,8 +1513,13 @@ fn default_lib_name_windows(
implementation: PythonImplementation,
abi3: bool,
mingw: bool,
debug: bool,
) -> String {
if abi3 && !implementation.is_pypy() {
if debug {
// CPython bug: linking against python3_d.dll raises error
// https://github.com/python/cpython/issues/101614
format!("python{}{}_d", version.major, version.minor)
} else if abi3 && !implementation.is_pypy() {
WINDOWS_ABI3_LIB_NAME.to_owned()
} else if mingw {
// https://packages.msys2.org/base/mingw-w64-python
Expand Down Expand Up @@ -2244,7 +2256,8 @@ mod tests {
PythonVersion { major: 3, minor: 7 },
CPython,
false,
false
false,
false,
),
"python37",
);
Expand All @@ -2253,7 +2266,8 @@ mod tests {
PythonVersion { major: 3, minor: 7 },
CPython,
true,
false
false,
false,
),
"python3",
);
Expand All @@ -2262,7 +2276,8 @@ mod tests {
PythonVersion { major: 3, minor: 7 },
CPython,
false,
true
true,
false,
),
"python3.7",
);
Expand All @@ -2271,7 +2286,8 @@ mod tests {
PythonVersion { major: 3, minor: 7 },
CPython,
true,
true
true,
false,
),
"python3",
);
Expand All @@ -2280,10 +2296,33 @@ mod tests {
PythonVersion { major: 3, minor: 7 },
PyPy,
true,
false
false,
false,
),
"python37",
);
assert_eq!(
super::default_lib_name_windows(
PythonVersion { major: 3, minor: 7 },
CPython,
false,
false,
true,
),
"python37_d",
);
// abi3 debug builds on windows use version-specific lib
// to workaround https://github.com/python/cpython/issues/101614
assert_eq!(
super::default_lib_name_windows(
PythonVersion { major: 3, minor: 7 },
CPython,
true,
false,
true,
),
"python37_d",
);
}

#[test]
Expand Down
Loading

0 comments on commit c6210e6

Please # to comment.