Commit Graph

20 Commits

Author SHA1 Message Date
Wenzel Jakob
bd560acf40 smart pointer refcount fix by @dean0x7d with slight modifications (fixes #471) 2016-11-03 11:53:35 +01:00
Jason Rhinelander
6873c202b3 Prevent overwriting previous declarations
Currently pybind11 doesn't check when you define a new object (e.g. a
class, function, or exception) that overwrites an existing one.  If the
thing being overwritten is a class, this leads to a segfault (because
pybind still thinks the type is defined, even though Python no longer
has the type).  In other cases this is harmless (e.g. replacing a
function with an exception), but even in that case it's most likely a
bug.

This code doesn't prevent you from actively doing something harmful,
like deliberately overwriting a previous definition, but detects
overwriting with a run-time error if it occurs in the standard
class/function/exception/def registration interfaces.

All of the additions are in non-template code; the result is actually a
tiny decrease in .so size compared to master without the new test code
(977304 to 977272 bytes), and about 4K higher with the new tests.
2016-10-24 22:45:51 -04:00
Dean Moldovan
5d28dd1194 Support std::shared_ptr holder type out of the box
With this there is no more need for manual user declarations like
`PYBIND11_DECLARE_HOLDER_TYPE(T, std::shared_ptr<T>)`. Existing ones
will still compile without error -- they will just be ignored silently.

Resolves #446.
2016-10-20 16:19:58 +02:00
Wenzel Jakob
b212f6c416 parameterize iterators by return value policy (fixes #388) 2016-09-10 17:16:16 +09:00
Wenzel Jakob
1f2e417d8c Merge pull request #403 from jagerman/alias-initialization
Implement py::init_alias<>() constructors
2016-09-10 16:12:19 +09:00
Wenzel Jakob
382484ae56 operators should return NotImplemented given unsupported input (fixes #393) 2016-09-10 15:34:26 +09:00
Jason Rhinelander
ec62d977c4 Implement py::init_alias<>() constructors
This commit adds support for forcing alias type initialization by
defining constructors with `py::init_alias<arg1, arg2>()` instead of
`py::init<arg1, arg2>()`.  Currently py::init<> only results in Alias
initialization if the type is extended in python, or the given
arguments can't be used to construct the base type, but can be used to
construct the alias.  py::init_alias<>, in contrast, always invokes the
constructor of the alias type.

It looks like this was already the intention of
`py::detail::init_alias`, which was forward-declared in
86d825f330, but was apparently never
finished: despite the existance of a .def method accepting it, the
`detail::init_alias` class isn't actually defined anywhere.

This commit completes the feature (or possibly repurposes it), allowing
declaration of classes that will always initialize the trampoline which
is (as I argued in #397) sometimes useful.
2016-09-09 03:04:09 -04:00
Jason Rhinelander
9c6859ee6e Fix type alias initialization
Type alias for alias classes with members didn't work properly: space
was only allocated for sizeof(type), but if we want to be able to put a
type_alias instance there, we need sizeof(type_alias), but
sizeof(type_alias) > sizeof(type) whenever type_alias has members.
2016-09-08 11:10:18 -04:00
Jason Rhinelander
c03db9bad9 Fail static_assert when trying to reference non-referencable types
The previous commit to address #392 triggers a compiler warning about
returning a reference to a local variable, which is *not* a false alarm:
the following:

    py::cast<int &>(o)

(which happens internally in an overload declaration) really is
returning a reference to a local, because the cast operators for the
type_caster for numeric types returns a reference to its own member.

This commit adds a static_assert to make that a compilation failure
rather than returning a reference into about-to-be-freed memory.

Incidentally, this is also a fix for #219, which is exactly the same
issue: we can't reference numeric primitives that are cast from
wrappers around python numeric types.
2016-09-07 16:07:59 -04:00
Jason Rhinelander
56f717756b Fix type caster for heap reference types
Need to use the intrinsic type, not the raw type.

Fixes #392.
2016-09-07 14:14:11 -04:00
Wenzel Jakob
6fd3132e81 Merge pull request #385 from jagerman/relax-class-arguments
Allow arbitrary class_ template option ordering
2016-09-07 23:49:00 +09:00
Jason Rhinelander
6b52c838d7 Allow passing base types as a template parameter
This allows a slightly cleaner base type specification of:

    py::class_<Type, Base>("Type")

as an alternative to

    py::class_<Type>("Type", py::base<Base>())

As with the other template parameters, the order relative to the holder
or trampoline types doesn't matter.

This also includes a compile-time assertion failure if attempting to
specify more than one base class (but is easily extendible to support
multiple inheritance, someday, by updating the class_selector::set_bases
function to set multiple bases).
2016-09-06 20:34:24 -04:00
Dean Moldovan
81511be341 Replace std::cout with py::print in tests
With this change both C++ and Python write to sys.stdout which resolves
the capture issues noted in #351. Therefore, the related workarounds are
removed.
2016-09-07 01:25:27 +02:00
Jason Rhinelander
5fffe200e3 Allow arbitrary class_ template option ordering
The current pybind11::class_<Type, Holder, Trampoline> fixed template
ordering results in a requirement to repeat the Holder with its default
value (std::unique_ptr<Type>) argument, which is a little bit annoying:
it needs to be specified not because we want to override the default,
but rather because we need to specify the third argument.

This commit removes this limitation by making the class_ template take
the type name plus a parameter pack of options.  It then extracts the
first valid holder type and the first subclass type for holder_type and
trampoline type_alias, respectively.  (If unfound, both fall back to
their current defaults, `std::unique_ptr<type>` and `type`,
respectively).  If any unmatched template arguments are provided, a
static assertion fails.

What this means is that you can specify or omit the arguments in any
order:

    py::class_<A, PyA> c1(m, "A");
    py::class_<B, PyB, std::shared_ptr<B>> c2(m, "B");
    py::class_<C, std::shared_ptr<C>, PyB> c3(m, "C");

It also allows future class attributes (such as base types in the next
commit) to be passed as class template types rather than needing to use
a py::base<> wrapper.
2016-09-06 12:22:13 -04:00
Wenzel Jakob
c84b37b577 fix bogus return value policy fallbacks (fixes #389) 2016-09-07 00:47:17 +09:00
Wenzel Jakob
85f07e18cc minor code style checker update 2016-09-04 23:00:49 +09:00
Jason Rhinelander
52f4be8946 Make test initialization self-registering
Adding or removing tests is a little bit cumbersome currently: the test
needs to be added to CMakeLists.txt, the init function needs to be
predeclared in pybind11_tests.cpp, then called in the plugin
initialization.  While this isn't a big deal for tests that are being
committed, it's more of a hassle when working on some new feature or
test code for which I temporarily only care about building and linking
the test being worked on rather than the entire test suite.

This commit changes tests to self-register their initialization by
having each test initialize a local object (which stores the
initialization function in a static variable).  This makes changing the
set of tests being build easy: one only needs to add or comment out
test names in tests/CMakeLists.txt.

A couple other minor changes that go along with this:

- test_eigen.cpp is now included in the test list, then removed if eigen
  isn't available.  This lets you disable the eigen tests by commenting
  it out, just like all the other tests, but keeps the build working
  without eigen eigen isn't available.  (Also, if it's commented out, we
  don't even bother looking for and reporting the building with/without
  eigen status message).

- pytest is now invoked with all the built test names (with .cpp changed
  to .py) so that it doesn't try to run tests that weren't built.
2016-09-03 17:34:41 -04:00
Dean Moldovan
99dbdc16e5 Simplify more tests by replacing capture with assert 2016-08-19 16:31:48 +02:00
Dean Moldovan
665e8804f3 Simplify tests by replacing output capture with asserts where possible
The C++ part of the test code is modified to achieve this. As a result,
this kind of test:

```python
with capture:
    kw_func1(5, y=10)
assert capture == "kw_func(x=5, y=10)"
```

can be replaced with a simple:

`assert kw_func1(5, y=10) == "x=5, y=10"`
2016-08-19 13:19:38 +02:00
Dean Moldovan
a0c1ccf0a9 Port tests to pytest
Use simple asserts and pytest's powerful introspection to make testing
simpler. This merges the old .py/.ref file pairs into simple .py files
where the expected values are right next to the code being tested.

This commit does not touch the C++ part of the code and replicates the
Python tests exactly like the old .ref-file-based approach.
2016-08-19 13:19:38 +02:00