Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make the accessor interface more complete #425

Merged
merged 5 commits into from
Sep 26, 2016
Merged

Conversation

dean0x7d
Copy link
Member

@dean0x7d dean0x7d commented Sep 23, 2016

As discussed in #265, this PR completes the accessor interface to match object. (This does not include the more drastic changes of object/handle mentioned there. This PR only affects accessors.)

With the more complete accessors in this PR there is no need for an additional cast to object when working with attributes and items:

// before
obj.attr("foo").cast<object>().attr("bar").cast<object>();
// after
obj.attr("foo").attr("bar");

All accessor support the full interface, so any kind of chain can be made without intermediate casts:

auto var = obj.attr("a")[key].attr("b").attr("method")(1, 2, 3)

Breaking change

This is a breaking change for handle::attr and handle::operator[]. They will throw error_aleady_set with the original Python error message instead of returning nullptr. This may not be too bad as the previous behavior was not documented as far as I can see. It's also possible to do this without a breaking change, but it would require checking for errors in 3 places instead of 1 and reconstructing the Python's error messages from scratch.

Extra

The first two commits here actually reduce the binary size of the test module by ~3%, which is nice. The last 3 commits then increase the size but that's because of the new tests.

This also adds the `hasattr` and `getattr` functions which are needed
with the new attribute behavior. The new functions behave exactly like
their Python counterparts.

Similarly `object` gets a `contains` method which calls `__contains__`,
i.e. it's the same as the `in` keyword in Python.
`auto var = l[0]` has a strange quirk: `var` is actually an accessor and
not an object, so any later assignment of `var = ...` would modify l[0]
instead of `var`. This is surprising compared to the non-auto assignment
`py::object var = l[0]; var = ...`.

By overloading `operator=` on lvalue/rvalue, the expected behavior is
restored even for `auto` variables.
@wjakob
Copy link
Member

wjakob commented Sep 23, 2016

Cool -- it's nice that some of the awkwardness of the accessor objects can be eliminated using rvalues. This looks good to me.

I'll wait a bit before merging to give others a chance to comment.

@wjakob wjakob merged commit 0a014e9 into pybind:master Sep 26, 2016
@wjakob
Copy link
Member

wjakob commented Sep 26, 2016

merged, thank you!

@aldanor
Copy link
Member

aldanor commented Sep 27, 2016

I've only had a chance to look at it now, but this is great, makes accessor API super ergonomic.

👍

@dean0x7d dean0x7d deleted the accessors branch September 29, 2016 09:30
jagerman added a commit to jagerman/pybind11 that referenced this pull request Oct 2, 2016
PR pybind#425 removed the bool operator from attribute accessors.  This was
quite useful, and it was the only way in 1.8 to check for the existance
of an attribute, via:

    if (obj.attr("foo")) { ... }

which was both quite useful and most likely in use by pybind11 users.
Since nothing in the PR pybind#425 dicussion or commit messages indicates that
this was intentionally removed, I assume the removal was an oversight.
jagerman added a commit to jagerman/pybind11 that referenced this pull request Oct 2, 2016
PR pybind#425 removed the bool operator from attribute accessors.  This was
quite useful, and moreover it was the only way before pybind#425 added the
`hasattr` function to check for the existence of an attribute, via:

    if (obj.attr("foo")) { ... }

and as such is probably in use by more pybind11 users than just me.
Since nothing in the PR pybind#425 discussion or commit messages indicates
that this was intentionally removed, I assume the removal was an
oversight.
jagerman added a commit to jagerman/pybind11 that referenced this pull request Oct 2, 2016
PR pybind#425 removed the bool operator from attribute accessors.  This is
likely in use by existing code as it was the only way before pybind#425 added
the `hasattr` function to check for the existence of an attribute, via:

    if (obj.attr("foo")) { ... }

This commit adds it back in for attr and item accessors, but with a
deprecation warning to use `hasattr(obj, ...)` or `obj.contains(...)`
instead.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants