Skip to content

Commit

Permalink
Merge pull request #1169 from PyO3/doc-null-check
Browse files Browse the repository at this point in the history
Add null-check for function's documents
  • Loading branch information
kngwyu authored Oct 10, 2020
2 parents 1d34ed7 + 2684547 commit cb90c51
Show file tree
Hide file tree
Showing 15 changed files with 251 additions and 188 deletions.
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,16 @@ 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).

## [Unreleased]
## Added
### Added
- Add support for keyword-only arguments without default values in `#[pyfunction]`. [#1209](https://github.com/PyO3/pyo3/pull/1209)
- Add a wrapper for `PyErr_CheckSignals()` as `Python::check_signals()`. [#1214](https://github.com/PyO3/pyo3/pull/1214)

### Changed
- Fields of `PyMethodDef`, `PyGetterDef`, `PySetterDef`, and `PyClassAttributeDef` are now private. [#1169](https://github.com/PyO3/pyo3/pull/1169)

### Fixed
- Fix invalid document for protocol methods. [#1169](https://github.com/PyO3/pyo3/pull/1169)

## [0.12.1] - 2020-09-16
### Fixed
- Fix building for a 32-bit Python on 64-bit Windows with a 64-bit Rust toolchain. [#1179](https://github.com/PyO3/pyo3/pull/1179)
Expand Down
8 changes: 4 additions & 4 deletions guide/src/class.md
Original file line number Diff line number Diff line change
Expand Up @@ -754,14 +754,14 @@ impl pyo3::IntoPy<PyObject> for MyClass {
}

pub struct Pyo3MethodsInventoryForMyClass {
methods: &'static [pyo3::class::PyMethodDefType],
methods: Vec<pyo3::class::PyMethodDefType>,
}
impl pyo3::class::methods::PyMethodsInventory for Pyo3MethodsInventoryForMyClass {
fn new(methods: &'static [pyo3::class::PyMethodDefType]) -> Self {
fn new(methods: Vec<pyo3::class::PyMethodDefType>) -> Self {
Self { methods }
}
fn get(&self) -> &'static [pyo3::class::PyMethodDefType] {
self.methods
fn get(&'static self) -> &'static [pyo3::class::PyMethodDefType] {
&self.methods
}
}
impl pyo3::class::methods::HasMethodsInventory for MyClass {
Expand Down
17 changes: 5 additions & 12 deletions pyo3-derive-backend/src/from_pyobject.rs
Original file line number Diff line number Diff line change
Expand Up @@ -133,7 +133,9 @@ impl<'a> Container<'a> {
"Cannot derive FromPyObject for empty structs and variants.",
));
}
let transparent = attrs.iter().any(ContainerAttribute::transparent);
let transparent = attrs
.iter()
.any(|attr| *attr == ContainerAttribute::Transparent);
if transparent {
Self::check_transparent_len(fields)?;
}
Expand Down Expand Up @@ -182,7 +184,6 @@ impl<'a> Container<'a> {
let err_name = attrs
.iter()
.find_map(|a| a.annotation())
.cloned()
.unwrap_or_else(|| path.segments.last().unwrap().ident.to_string());

let v = Container {
Expand Down Expand Up @@ -306,18 +307,10 @@ enum ContainerAttribute {
}

impl ContainerAttribute {
/// Return whether this attribute is `Transparent`
fn transparent(&self) -> bool {
match self {
ContainerAttribute::Transparent => true,
_ => false,
}
}

/// Convenience method to access `ErrorAnnotation`.
fn annotation(&self) -> Option<&String> {
fn annotation(&self) -> Option<String> {
match self {
ContainerAttribute::ErrorAnnotation(s) => Some(s),
ContainerAttribute::ErrorAnnotation(s) => Some(s.to_string()),
_ => None,
}
}
Expand Down
13 changes: 11 additions & 2 deletions pyo3-derive-backend/src/module.rs
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,7 @@ pub fn add_fn_to_module(
doc,
};

let doc = &spec.doc;
let doc = syn::LitByteStr::new(spec.doc.value().as_bytes(), spec.doc.span());

let python_name = &spec.python_name;

Expand All @@ -212,7 +212,16 @@ pub fn add_fn_to_module(
fn #function_wrapper_ident<'a>(
args: impl Into<pyo3::derive_utils::PyFunctionArguments<'a>>
) -> pyo3::PyResult<&'a pyo3::types::PyCFunction> {
pyo3::types::PyCFunction::new_with_keywords(#wrapper_ident, stringify!(#python_name), #doc, args.into())
let name = concat!(stringify!(#python_name), "\0");
let name = std::ffi::CStr::from_bytes_with_nul(name.as_bytes()).unwrap();
let doc = std::ffi::CStr::from_bytes_with_nul(#doc).unwrap();
pyo3::types::PyCFunction::internal_new(
name,
doc,
pyo3::class::PyMethodType::PyCFunctionWithKeywords(#wrapper_ident),
pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
args.into(),
)
}
})
}
Expand Down
10 changes: 5 additions & 5 deletions pyo3-derive-backend/src/pyclass.rs
Original file line number Diff line number Diff line change
Expand Up @@ -215,14 +215,14 @@ fn impl_methods_inventory(cls: &syn::Ident) -> TokenStream {
quote! {
#[doc(hidden)]
pub struct #inventory_cls {
methods: &'static [pyo3::class::PyMethodDefType],
methods: Vec<pyo3::class::PyMethodDefType>,
}
impl pyo3::class::methods::PyMethodsInventory for #inventory_cls {
fn new(methods: &'static [pyo3::class::PyMethodDefType]) -> Self {
fn new(methods: Vec<pyo3::class::PyMethodDefType>) -> Self {
Self { methods }
}
fn get(&self) -> &'static [pyo3::class::PyMethodDefType] {
self.methods
fn get(&'static self) -> &'static [pyo3::class::PyMethodDefType] {
&self.methods
}
}

Expand Down Expand Up @@ -483,7 +483,7 @@ fn impl_descriptors(
pyo3::inventory::submit! {
#![crate = pyo3] {
type Inventory = <#cls as pyo3::class::methods::HasMethodsInventory>::Methods;
<Inventory as pyo3::class::methods::PyMethodsInventory>::new(&[#(#py_methods),*])
<Inventory as pyo3::class::methods::PyMethodsInventory>::new(vec![#(#py_methods),*])
}
}
})
Expand Down
2 changes: 1 addition & 1 deletion pyo3-derive-backend/src/pyimpl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ pub fn impl_methods(ty: &syn::Type, impls: &mut Vec<syn::ImplItem>) -> syn::Resu
pyo3::inventory::submit! {
#![crate = pyo3] {
type Inventory = <#ty as pyo3::class::methods::HasMethodsInventory>::Methods;
<Inventory as pyo3::class::methods::PyMethodsInventory>::new(&[#(
<Inventory as pyo3::class::methods::PyMethodsInventory>::new(vec![#(
#(#cfg_attributes)*
#methods
),*])
Expand Down
87 changes: 33 additions & 54 deletions pyo3-derive-backend/src/pymethod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -570,25 +570,24 @@ pub fn impl_py_method_def(spec: &FnSpec, wrapper: &TokenStream) -> TokenStream {
pyo3::class::PyMethodDefType::Method({
#wrapper

pyo3::class::PyMethodDef {
ml_name: stringify!(#python_name),
ml_meth: pyo3::class::PyMethodType::PyCFunction(__wrap),
ml_flags: pyo3::ffi::METH_NOARGS,
ml_doc: #doc,
}
pyo3::class::PyMethodDef::cfunction(
concat!(stringify!(#python_name), "\0"),
__wrap,
#doc
)
})
}
} else {
quote! {
pyo3::class::PyMethodDefType::Method({
#wrapper

pyo3::class::PyMethodDef {
ml_name: stringify!(#python_name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
ml_doc: #doc,
}
pyo3::class::PyMethodDef::cfunction_with_keywords(
concat!(stringify!(#python_name), "\0"),
__wrap,
0,
#doc
)
})
}
}
Expand All @@ -601,12 +600,7 @@ pub fn impl_py_method_def_new(spec: &FnSpec, wrapper: &TokenStream) -> TokenStre
pyo3::class::PyMethodDefType::New({
#wrapper

pyo3::class::PyMethodDef {
ml_name: stringify!(#python_name),
ml_meth: pyo3::class::PyMethodType::PyNewFunc(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
ml_doc: #doc,
}
pyo3::class::PyMethodDef::new_func(concat!(stringify!(#python_name), "\0"), __wrap, #doc)
})
}
}
Expand All @@ -618,13 +612,12 @@ pub fn impl_py_method_def_class(spec: &FnSpec, wrapper: &TokenStream) -> TokenSt
pyo3::class::PyMethodDefType::Class({
#wrapper

pyo3::class::PyMethodDef {
ml_name: stringify!(#python_name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS |
pyo3::class::PyMethodDef::cfunction_with_keywords(
concat!(stringify!(#python_name), "\0"),
__wrap,
pyo3::ffi::METH_CLASS,
ml_doc: #doc,
}
#doc
)
})
}
}
Expand All @@ -636,12 +629,12 @@ pub fn impl_py_method_def_static(spec: &FnSpec, wrapper: &TokenStream) -> TokenS
pyo3::class::PyMethodDefType::Static({
#wrapper

pyo3::class::PyMethodDef {
ml_name: stringify!(#python_name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS | pyo3::ffi::METH_STATIC,
ml_doc: #doc,
}
pyo3::class::PyMethodDef::cfunction_with_keywords(
concat!(stringify!(#python_name), "\0"),
__wrap,
pyo3::ffi::METH_STATIC,
#doc
)
})
}
}
Expand All @@ -652,10 +645,7 @@ pub fn impl_py_method_class_attribute(spec: &FnSpec<'_>, wrapper: &TokenStream)
pyo3::class::PyMethodDefType::ClassAttribute({
#wrapper

pyo3::class::PyClassAttributeDef {
name: stringify!(#python_name),
meth: __wrap,
}
pyo3::class::PyClassAttributeDef::new(concat!(stringify!(#python_name), "\0"), __wrap)
})
}
}
Expand All @@ -666,10 +656,7 @@ pub fn impl_py_const_class_attribute(spec: &ConstSpec, wrapper: &TokenStream) ->
pyo3::class::PyMethodDefType::ClassAttribute({
#wrapper

pyo3::class::PyClassAttributeDef {
name: stringify!(#python_name),
meth: __wrap,
}
pyo3::class::PyClassAttributeDef::new(concat!(stringify!(#python_name), "\0"), __wrap)
})
}
}
Expand All @@ -681,12 +668,12 @@ pub fn impl_py_method_def_call(spec: &FnSpec, wrapper: &TokenStream) -> TokenStr
pyo3::class::PyMethodDefType::Call({
#wrapper

pyo3::class::PyMethodDef {
ml_name: stringify!(#python_name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS,
ml_doc: #doc,
}
pyo3::class::PyMethodDef::cfunction_with_keywords(
concat!(stringify!(#python_name), "\0"),
__wrap,
pyo3::ffi::METH_STATIC,
#doc
)
})
}
}
Expand All @@ -700,11 +687,7 @@ pub(crate) fn impl_py_setter_def(
pyo3::class::PyMethodDefType::Setter({
#wrapper

pyo3::class::PySetterDef {
name: stringify!(#python_name),
meth: __wrap,
doc: #doc,
}
pyo3::class::PySetterDef::new(concat!(stringify!(#python_name), "\0"), __wrap, #doc)
})
}
}
Expand All @@ -718,11 +701,7 @@ pub(crate) fn impl_py_getter_def(
pyo3::class::PyMethodDefType::Getter({
#wrapper

pyo3::class::PyGetterDef {
name: stringify!(#python_name),
meth: __wrap,
doc: #doc,
}
pyo3::class::PyGetterDef::new(concat!(stringify!(#python_name), "\0"), __wrap, #doc)
})
}
}
Expand Down
14 changes: 7 additions & 7 deletions pyo3-derive-backend/src/pyproto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,12 @@ fn impl_proto_impl(
py_methods.push(quote! {
pyo3::class::PyMethodDefType::Method({
#method
pyo3::class::PyMethodDef {
ml_name: stringify!(#name),
ml_meth: pyo3::class::PyMethodType::PyCFunctionWithKeywords(__wrap),
ml_flags: pyo3::ffi::METH_VARARGS | pyo3::ffi::METH_KEYWORDS | #coexist,
ml_doc: ""
}
pyo3::class::PyMethodDef::cfunction_with_keywords(
concat!(stringify!(#name), "\0"),
__wrap,
#coexist,
"\0"
)
})
});
}
Expand All @@ -123,7 +123,7 @@ fn inventory_submission(py_methods: Vec<TokenStream>, ty: &syn::Type) -> TokenSt
pyo3::inventory::submit! {
#![crate = pyo3] {
type Inventory = <#ty as pyo3::class::methods::HasMethodsInventory>::Methods;
<Inventory as pyo3::class::methods::PyMethodsInventory>::new(&[#(#py_methods),*])
<Inventory as pyo3::class::methods::PyMethodsInventory>::new(vec![#(#py_methods),*])
}
}
}
Expand Down
10 changes: 2 additions & 8 deletions src/buffer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -132,18 +132,12 @@ fn standard_element_type_from_type_char(type_char: u8) -> ElementType {

#[cfg(target_endian = "little")]
fn is_matching_endian(c: u8) -> bool {
match c {
b'@' | b'=' | b'<' => true,
_ => false,
}
c == b'@' || c == b'=' || c == b'>'
}

#[cfg(target_endian = "big")]
fn is_matching_endian(c: u8) -> bool {
match c {
b'@' | b'=' | b'>' | b'!' => true,
_ => false,
}
c == b'@' || c == b'=' || c == b'>' || c == b'!'
}

/// Trait implemented for possible element types of `PyBuffer`.
Expand Down
Loading

0 comments on commit cb90c51

Please sign in to comment.