Skip to content

Commit

Permalink
Export MandatoryValidator to Python. Refs #4399
Browse files Browse the repository at this point in the history
In doing so the isEmpty check has been moved to be easier
to extend for additional types.
  • Loading branch information
martyngigg committed Apr 17, 2012
1 parent 5411139 commit 5846a2a
Show file tree
Hide file tree
Showing 9 changed files with 156 additions and 75 deletions.
1 change: 1 addition & 0 deletions Code/Mantid/Framework/Kernel/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ set ( SRC_FILES
src/LogParser.cpp
src/Logger.cpp
src/MagneticIon.cpp
src/MandatoryValidator.cpp
src/MantidVersion.cpp
src/MaskedProperty.cpp
src/Matrix.cpp
Expand Down
3 changes: 3 additions & 0 deletions Code/Mantid/Framework/Kernel/inc/MantidKernel/EmptyValues.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,9 @@ namespace Mantid
/// Returns what we consider an "empty" integer
DLLExport int EMPTY_INT();

/// Returns what we consider an "empty" long
DLLExport long EMPTY_LONG();

/// Return what we consider to be an empty double
DLLExport double EMPTY_DBL();

Expand Down
75 changes: 31 additions & 44 deletions Code/Mantid/Framework/Kernel/inc/MantidKernel/MandatoryValidator.h
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,41 @@
// Includes
//----------------------------------------------------------------------
#include "MantidKernel/TypedValidator.h"
#include "MantidKernel/EmptyValues.h"
#include <vector>

namespace Mantid
{
namespace Kernel
{
namespace Detail
{
/// Forward declare checking function
template<typename T>
bool checkIsEmpty(const T &);

/// Specialization for any vector type
template<typename T>
bool checkIsEmpty(const std::vector<T> & value)
{
return value.empty();
}

/// Defines the concept of emptiness
template<typename T>
struct IsEmpty
{
/**
* Returns true if the value is considered empty
* @param The value to check
* @return
*/
static bool check(const T & value)
{
return checkIsEmpty(value);
}
};
}

/** @class MandatoryValidator MandatoryValidator.h Kernel/MandatoryValidator.h
Validator to check that a property is not left empty.
Expand Down Expand Up @@ -54,51 +83,9 @@ class DLLExport MandatoryValidator : public TypedValidator<TYPE>
*/
std::string checkValidity(const TYPE& value) const
{
if ( isEmpty(value) ) return "A value must be entered for this parameter";
if(Detail::IsEmpty<TYPE>::check(value)) return "A value must be entered for this parameter";
else return "";
}

/**
* Checks if a vector is empty
* @param value :: A vector of possible values
* @returns True if the vector is empty
*/
template <typename T>
bool isEmpty(const std::vector<T> & values) const
{
return values.empty();
}

/**
* Checks if a string is empty
* @param value :: A test string
* @returns True if the vector is empty
*/
bool isEmpty(const std::string & value) const
{
return value.empty();
}

/**
* Checks if an integer is empty
* @param value :: A value to test
* @returns True if the value is considered empty
*/
bool isEmpty(const int & value) const
{
return (value == Mantid::EMPTY_INT());
}
/**
* Checks if a double is empty
* @param value :: A vector of possible values
* @returns True if the value is considered empty
*/
bool isEmpty(const double & value) const
{
if( std::abs(value - Mantid::EMPTY_DBL()) < 1e-08 ) return true;
else return false;
}

};

} // namespace Kernel
Expand Down
11 changes: 10 additions & 1 deletion Code/Mantid/Framework/Kernel/src/EmptyValues.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,22 @@ namespace Mantid
return INT_MAX;
}

/**
* Returns what we consider an "empty" long within a property
* @returns An flag value
*/
long EMPTY_LONG()
{
return LONG_MAX;
}

/**
* Returns what we consider an "empty" double within a property
* @returns An flag value
*/
double EMPTY_DBL()
{
return DBL_MAX/2;
return DBL_MAX/2;
}

} // namespace Mantid
78 changes: 48 additions & 30 deletions Code/Mantid/Framework/Kernel/src/MandatoryValidator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,38 +4,56 @@
#include "MantidKernel/MandatoryValidator.h"
#include "MantidKernel/EmptyValues.h"
#include <cmath>
#include <string>

namespace Mantid
{
namespace Kernel
{

///** Checks if the integer it is passed equals the flag value
// * Mantid::EMPTY_DBL(), which implies that it wasn't set by the user
// * @param value :: the value to test
// * @return "A value must be entered for this parameter" if empty or ""
// */
//template<>
//std::string MandatoryValidator<int>::checkValidity(const int& value) const
//{
// if ( value == Mantid::EMPTY_INT() ) return "A value must be entered for this parameter";
// else return "";
//}
//
///** Checks if the double it is passed is within 10 parts per billon of flag
// * value Mantid::EMPTY_DBL(), which implies that it wasn't set by the user
// * @param value :: the value to test
// * @return "A value must be entered for this parameter" if empty or ""
// */
//template<>
//std::string MandatoryValidator<double>::checkValidity(const double& value) const
//{
// if( std::abs(value - Mantid::EMPTY_DBL()) < 1e-08 )
// {
// return "A value must be entered for this parameter";
// }
// else return "";
//}
namespace Kernel
{
namespace Detail
{
/**
* Specialization of checkIsEmpty for string
* @param value :: A string object
* @return True if the string is considered empty
*/
template<>
bool checkIsEmpty(const std::string & value)
{
return value.empty();
}
/**
* Specialization of checkIsEmpty for double values
* @param value :: A double
* @return True if the value is considered empty, see EmptyValues.h
*/
template<>
bool checkIsEmpty(const double & value)
{
if( std::fabs(value - Mantid::EMPTY_DBL()) < 1e-08 ) return true;
else return false;
}
/**
* Specialization of checkIsEmpty for int
* @param value :: A int value
* @return True if the value is considered empty, see EmptyValues.h
*/
template<>
bool checkIsEmpty(const int & value)
{
return (value == Mantid::EMPTY_INT());
}
/**
* Specialization of checkIsEmpty for long
* @param value :: A long value
* @return True if the value is considered empty, see EmptyValues.h
*/
template<>
bool checkIsEmpty(const long & value)
{
return (value == Mantid::EMPTY_LONG());
}

}
}
}
}
1 change: 1 addition & 0 deletions Code/Mantid/Framework/PythonInterface/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ set ( TEST_PY_FILES
test/python/ListValidatorTest.py
test/python/LoggerTest.py
test/python/MatrixWorkspaceTest.py
test/python/MandatoryValidatorTest.py
test/python/MDHistoWorkspaceTest.py
test/python/NullValidatorTest.py
test/python/OrientedLatticeTest.py
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ set ( EXPORT_FILES
src/Exports/ListValidator.cpp
src/Exports/ArrayLengthValidator.cpp
src/Exports/ArrayBoundedValidator.cpp
src/Exports/MandatoryValidator.cpp
)

set ( SRC_FILES
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
#include "MantidKernel/MandatoryValidator.h"
#include <boost/python/class.hpp>
#include <string>

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

namespace
{
/// A macro for generating exports for each type
#define EXPORT_MANDATORYVALIDATOR(ElementType, prefix) \
class_<MandatoryValidator<ElementType>, bases<IValidator>, \
boost::noncopyable>(#prefix"MandatoryValidator") \
;
}

void export_MandatoryValidator()
{
EXPORT_MANDATORYVALIDATOR(double, Float);
EXPORT_MANDATORYVALIDATOR(long, Int);
EXPORT_MANDATORYVALIDATOR(std::string, String);

// Array types
EXPORT_MANDATORYVALIDATOR(std::vector<double>, FloatArray);
EXPORT_MANDATORYVALIDATOR(std::vector<long>, IntArray);
EXPORT_MANDATORYVALIDATOR(std::vector<std::string>, StringArray);
}


Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import unittest
import testhelpers
from mantid import (FloatArrayProperty, StringMandatoryValidator, FloatArrayMandatoryValidator,
PythonAlgorithm)

class MandatoryValidatorTest(unittest.TestCase):

def test_constructor_does_not_raise_error(self):
testhelpers.assertRaisesNothing(self, StringMandatoryValidator)

def test_validator_restricts_property_values_to_non_empty(self):
class TestAlgorithm(PythonAlgorithm):

def PyInit(self):
self.declareProperty("StringInput", "", StringMandatoryValidator())
self.declareProperty(FloatArrayProperty("ArrayInput", FloatArrayMandatoryValidator()))

def PyExec(self):
pass

alg = TestAlgorithm()
alg.initialize()

self.assertRaises(ValueError, alg.setProperty, "StringInput", "")
testhelpers.assertRaisesNothing(self, alg.setProperty, "StringInput", "value")

self.assertRaises(ValueError, alg.setProperty, "ArrayInput", [])
testhelpers.assertRaisesNothing(self, alg.setProperty, "ArrayInput", [1.2,3.4])

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

0 comments on commit 5846a2a

Please sign in to comment.