Bug #1559

Restore intensitydata.py functional test

Added by pospelov over 4 years ago. Updated over 4 years ago.

Status:RejectedStart date:02 Aug 2016
Priority:NormalDue date:
Assignee:-% Done:


Target version:Sprint32


After I have fixed Simulation::getIntensityData ownership within #1558, and the returned Histogram2D object started to be governed by Python,
following snippet has stopped to work in intensitydata.py functional test

def get_axis():
    simulation = GISASSimulation()
    simulation.setDetectorParameters(10, -1.0, 1.0, 100, 0.0, 2.0)
    data = simulation.getIntensityData()
    axis = data.getXaxis()
    return axis

def test_axis_ownership(self):
    axis0 = get_axis()
    self.assertEqual(10, axis0.getSize())

Meaning, that swig doesn't know that time of life of 'data' should be coupled with time of life of 'axis'. So Python deletes 'data' and 'axis' points to nowhere.

In Py++ such situation was handled by following instructions

    cl = mb.class_("IHistogram")
    cl.member_function("getXaxis").call_policies = call_policies.return_internal_reference()
    cl.member_function("getYaxis").call_policies = call_policies.return_internal_reference()

    cl = mb.class_("OutputData<double>")
    fun = cl.member_functions("getAxis").call_policies = call_policies.return_internal_reference()

Although given case is not used in user examples (seems to be), it was used in my private scripts and one have to be ready that similar case sooner or later will be discovered by some advanced user.

Within this item:
  • learn how to couple time of life of objects
  • uncomment text_axes_ownership subtest in intensitydata.py


#1 Updated by jmfisher over 4 years ago

Note that this is the expected behaviour in C++. getXaxis() returns a raw pointer to the axis, which is owned by the intensity data object. When data goes out of scope, the destructor deletes the axis and any remaining pointers become dangling. The Python bindings are simply wrapping this correct behaviour. The desired behaviour could be achieved by promoting raw pointers to shared pointers (which I suspect is how things were done internally within the old boost::python bindings), but it is probably not worth doing.

#2 Updated by pospelov over 4 years ago

  • Status changed from Sprint to Rejected

You are right. I was able to do this in boost-python binding only because, as you've explained, he was silently providing me with shared_ptr. Thanks! Rejecting...

Also available in: Atom PDF