Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/feature/8947_propertysettings_to…
Browse files Browse the repository at this point in the history
…_python'
  • Loading branch information
jmborr committed Mar 4, 2014
2 parents 7970a77 + afc25ad commit 229ac25
Show file tree
Hide file tree
Showing 11 changed files with 205 additions and 5 deletions.
Expand Up @@ -13,6 +13,9 @@ set ( EXPORT_FILES
src/Exports/IPropertyManager.cpp
src/Exports/Property.cpp
src/Exports/IValidator.cpp
src/Exports/IPropertySettings.cpp
src/Exports/EnabledWhenProperty.cpp
src/Exports/VisibleWhenProperty.cpp
src/Exports/PropertyWithValue.cpp
src/Exports/ArrayProperty.cpp
src/Exports/Quat.cpp
Expand Down
@@ -0,0 +1,33 @@
#include "MantidKernel/EnabledWhenProperty.h"
#include <boost/python/class.hpp>
#include <boost/python/enum.hpp>

using namespace Mantid::Kernel;
using namespace boost::python;

void export_EnabledWhenProperty()
{
// State enumeration
enum_<ePropertyCriterion>("PropertyCriterion")
.value("IsDefault", IS_DEFAULT)
.value("IsNotDefault", IS_NOT_DEFAULT)
.value("IsEqualTo", IS_EQUAL_TO)
.value("IsNotEqualTo", IS_NOT_EQUAL_TO)
.value("IsMoreOrEqual", IS_MORE_OR_EQ)
;

class_<EnabledWhenProperty, bases<IPropertySettings>,
boost::noncopyable>("EnabledWhenProperty", no_init) // no default constructor

.def(init<std::string, ePropertyCriterion, std::string>(
(arg("otherPropName"), arg("when"), arg("value")),
"Enabled otherPropName property when value criterion meets that given by the 'when' argument")
)

.def(init<std::string, ePropertyCriterion>(
(arg("otherPropName"), arg("when")),
"Enabled otherPropName property when criterion does not require a value, i.e isDefault")
)
;
}

Expand Up @@ -6,7 +6,7 @@
#include <boost/python/register_ptr_to_python.hpp>
#include <boost/python/copy_const_reference.hpp>

using Mantid::Kernel::IPropertyManager;
using namespace Mantid::Kernel;
namespace Registry = Mantid::PythonInterface::Registry;
using namespace boost::python;

Expand All @@ -21,7 +21,7 @@ namespace
* @param value :: The value of the property as a bpl object
*/
void setProperty(IPropertyManager &self, const std::string & name,
boost::python::object value)
const boost::python::object & value)
{
if( PyString_Check(value.ptr()) ) // String values can be set directly
{
Expand All @@ -40,6 +40,19 @@ namespace
}
}
}

/**
* Clones the given settingsManager and passes it on to the calling object as it takes ownership
* of the IPropertySettings object
* @param self The calling object
* @param propName A property name that will pick up the settings manager
* @param settingsManager The actual settings object
*/
void setPropertySettings(IPropertyManager &self, const std::string & propName,
IPropertySettings *settingsManager)
{
self.setPropertySettings(propName, settingsManager->clone());
}
}

void export_IPropertyManager()
Expand All @@ -48,19 +61,30 @@ void export_IPropertyManager()

class_<IPropertyManager, boost::noncopyable>("IPropertyManager", no_init)
.def("propertyCount", &IPropertyManager::propertyCount, "Returns the number of properties being managed")

.def("getProperty", &IPropertyManager::getPointerToProperty, return_value_policy<return_by_value>(),
"Returns the property of the given name. Use .value to give the value")

.def("getPropertyValue", &IPropertyManager::getPropertyValue,
"Returns a string representation of the named property's value")

.def("getProperties", &IPropertyManager::getProperties, return_value_policy<copy_const_reference>(),
"Returns the list of properties managed by this object")

.def("setPropertyValue", &IPropertyManager::setPropertyValue,
"Set the value of the named property via a string")

.def("setProperty", &setProperty, "Set the value of the named property")

.def("setPropertySettings", &setPropertySettings,
"Assign the given IPropertySettings object to the named property")

.def("setPropertyGroup", &IPropertyManager::setPropertyGroup, "Set the group for a given property")

.def("existsProperty", &IPropertyManager::existsProperty,
"Returns whether a property exists")
// Special methods so that IPropertyManager acts like a dictionary

// Special methods so that IPropertyManager acts like a dictionary
.def("__len__", &IPropertyManager::propertyCount)
.def("__contains__", &IPropertyManager::existsProperty)
.def("__getitem__", &IPropertyManager::getProperty)
Expand Down
@@ -0,0 +1,21 @@
#include "MantidKernel/IPropertySettings.h"
#include "MantidKernel/IPropertyManager.h"
#include <boost/python/class.hpp>
#include <boost/python/register_ptr_to_python.hpp>

using Mantid::Kernel::IPropertySettings;
using namespace boost::python;

void export_IPropertySettings()
{
register_ptr_to_python<IPropertySettings*>();

class_<IPropertySettings,boost::noncopyable>("IPropertySettings", no_init)
.def("isEnabled", &IPropertySettings::isEnabled,
"Is the property to be shown as enabled in the GUI. Default true.")

.def("isVisible", &IPropertySettings::isVisible,
"Is the property to be shown in the GUI? Default true.")
;
}

@@ -1,4 +1,5 @@
#include "MantidKernel/Property.h"
#include "MantidKernel/IPropertySettings.h"
#include "MantidPythonInterface/kernel/StlExportDefinitions.h"

#include <boost/python/class.hpp>
Expand Down Expand Up @@ -59,7 +60,9 @@ void export_Property()
.add_property("allowedValues", &Property::allowedValues, "A list of allowed values")

.add_property("getGroup", make_function(&Property::getGroup, return_value_policy<copy_const_reference>()),
"Return the 'group' of the property, that is, the header in the algorithm's list of properties.")
"Return the 'group' of the property, that is, the header in the algorithm's list of properties.")

.add_property("settings", make_function(&Property::getSettings, return_value_policy<return_by_value>()),
"Return the object managing this property's settings")
;
}
@@ -0,0 +1,22 @@
#include "MantidKernel/VisibleWhenProperty.h"
#include <boost/python/class.hpp>

using namespace Mantid::Kernel;
using namespace boost::python;

void export_VisibleWhenProperty()
{
class_<VisibleWhenProperty, bases<EnabledWhenProperty>,
boost::noncopyable>("VisibleWhenProperty", no_init)
.def(init<std::string, ePropertyCriterion, std::string>(
(arg("otherPropName"), arg("when"), arg("value")),
"Enabled otherPropName property when value criterion meets that given by the 'when' argument")
)

.def(init<std::string, ePropertyCriterion>(
(arg("otherPropName"), arg("when")),
"Enabled otherPropName property when criterion does not require a value, i.e isDefault")
)
;
}

Expand Up @@ -112,6 +112,29 @@ def PyExec(self):
withdoc = alg.getProperty("WithDocString")
self.assertTrue(isinstance(withdoc, FileProperty))
self.assertEquals(alg._testdocstring, withdoc.documentation)



def test_passing_settings_object_connects_to_correct_object(self):
from mantid.kernel import EnabledWhenProperty, PropertyCriterion

class DummyAlg(PythonAlgorithm):

def PyInit(self):
self.declareProperty("BasicProp1",1)
self.declareProperty("BasicProp2",1)
self.setPropertySettings("BasicProp2", EnabledWhenProperty("BasicProp1", PropertyCriterion.IsDefault))

def PyExec(self):
pass
##
alg = DummyAlg()
alg.initialize()
settings = alg.getProperty("BasicProp2").settings
self.assertTrue(settings is not None)
self.assertTrue(settings.isEnabled(alg))
alg.setProperty("BasicProp1", 2) # not default
self.assertTrue(not settings.isEnabled(alg))


if __name__ == '__main__':
unittest.main()
Expand Up @@ -10,9 +10,11 @@ set ( TEST_PY_FILES
ConfigServiceTest.py
DateAndTimeTest.py
DeltaEModeTest.py
EnabledWhenPropertyTest.py
FacilityInfoTest.py
FilteredTimeSeriesPropertyTest.py
InstrumentInfoTest.py
IPropertySettingsTest.py
ListValidatorTest.py
LogFilterTest.py
LoggerTest.py
Expand All @@ -29,6 +31,7 @@ set ( TEST_PY_FILES
UnitFactoryTest.py
UnitsTest.py
V3DTest.py
VisibleWhenPropertyTest.py
VMDTest.py
)

Expand Down
@@ -0,0 +1,30 @@
import unittest
from mantid.kernel import EnabledWhenProperty, PropertyCriterion

class EnabledWhenPropertyTest(unittest.TestCase):

def test_construction_with_name_criterion_only_succeeds(self):
p = EnabledWhenProperty("OtherProperty", PropertyCriterion.IsDefault)

def test_construction_with_name_criterion_value_succeeds(self):
p = EnabledWhenProperty("OtherProperty", PropertyCriterion.IsEqualTo, "value")

def test_Property_Criterion_Has_Expected_Attrs(self):
attrs = ["IsNotDefault", "IsEqualTo", "IsNotEqualTo", "IsMoreOrEqual"]
for att in attrs:
self.assertTrue(hasattr(PropertyCriterion, att))

#------------ Failure cases ------------------

def test_default_construction_raises_error(self):
try:
EnabledWhenProperty()
self.fail("Expected default constructor to raise an error")
except Exception, e:
# boost.python.ArgumentError are not catchable
if "Python argument types in" not in str(e):
raise RuntimeError("Unexpected exception type raised")


if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,14 @@
import unittest
from mantid.kernel import IPropertySettings

class IPropertySettingsTest(unittest.TestCase):

def test_construction_raises_an_exception(self):
self.assertRaises(RuntimeError, IPropertySettings)

def test_interface_has_expected_attrs(self):
self.assertTrue(hasattr(IPropertySettings, "isEnabled"))
self.assertTrue(hasattr(IPropertySettings, "isVisible"))

if __name__ == '__main__':
unittest.main()
@@ -0,0 +1,24 @@
import unittest
from mantid.kernel import VisibleWhenProperty, PropertyCriterion

class VisibleWhenPropertyTest(unittest.TestCase):

def test_construction_with_name_criterion_only_succeeds(self):
p = VisibleWhenProperty("OtherProperty", PropertyCriterion.IsDefault)

def test_construction_with_name_criterion_value_succeeds(self):
p = VisibleWhenProperty("OtherProperty", PropertyCriterion.IsEqualTo, "value")

#------------ Failure cases ------------------

def test_default_construction_raises_error(self):
try:
VisibleWhenProperty()
self.fail("Expected default constructor to raise an error")
except Exception, e:
# boost.python.ArgumentError are not catchable
if "Python argument types in" not in str(e):
raise RuntimeError("Unexpected exception type raised")

if __name__ == '__main__':
unittest.main()

0 comments on commit 229ac25

Please sign in to comment.