Skip to content

Commit 58e52fb

Browse files
Create PythonObjectProperty -- ornl-next (#39951)
Sister to PR #39880 Co-authored-by: martyngigg <martyn.gigg@stfc.ac.uk>
1 parent c422197 commit 58e52fb

File tree

16 files changed

+1096
-2
lines changed

16 files changed

+1096
-2
lines changed

Framework/PythonInterface/core/CMakeLists.txt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,8 @@ set(SRC_FILES
77
src/ErrorHandling.cpp
88
src/GlobalInterpreterLock.cpp
99
src/NDArray.cpp
10+
src/PythonObjectProperty.cpp
11+
src/PythonObjectTypeValidator.cpp
1012
src/ReleaseGlobalInterpreterLock.cpp
1113
src/UninstallTrace.cpp
1214
src/PythonLoggingChannel.cpp
@@ -36,6 +38,8 @@ set(INC_FILES
3638
inc/MantidPythonInterface/core/PropertyWithValueExporter.h
3739
inc/MantidPythonInterface/core/PythonLoggingChannel.h
3840
inc/MantidPythonInterface/core/PythonObjectInstantiator.h
41+
inc/MantidPythonInterface/core/PythonObjectProperty.h
42+
inc/MantidPythonInterface/core/PythonObjectTypeValidator.h
3943
inc/MantidPythonInterface/core/PythonStdoutChannel.h
4044
inc/MantidPythonInterface/core/ReleaseGlobalInterpreterLock.h
4145
inc/MantidPythonInterface/core/StlExportDefinitions.h

Framework/PythonInterface/core/inc/MantidPythonInterface/core/PropertyWithValueExporter.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
// Call the dtype helper function
2020
template <typename HeldType> std::string dtype(Mantid::Kernel::PropertyWithValue<HeldType> &self) {
2121
// Check for the special case of a string
22-
if (std::is_same<HeldType, std::string>::value) {
22+
if constexpr (std::is_same<HeldType, std::string>::value) {
2323
std::stringstream ss;
2424
std::string val = self.value();
2525
ss << "S" << val.size();
Lines changed: 123 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,123 @@
1+
// Mantid Repository : https://github.com/mantidproject/mantid
2+
//
3+
// Copyright &copy; 2007 ISIS Rutherford Appleton Laboratory UKRI,
4+
// NScD Oak Ridge National Laboratory, European Spallation Source,
5+
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6+
// SPDX - License - Identifier: GPL - 3.0 +
7+
#pragma once
8+
9+
//----------------------------------------------------------------------
10+
// Includes
11+
//----------------------------------------------------------------------
12+
#include "MantidPythonInterface/core/DllConfig.h"
13+
14+
#include "MantidKernel/IValidator.h"
15+
#include "MantidKernel/NullValidator.h"
16+
#include "MantidKernel/PropertyWithValue.h"
17+
18+
#include <boost/python/object.hpp>
19+
20+
// forward declare
21+
namespace Json {
22+
class Value;
23+
}
24+
25+
namespace Mantid::Kernel {
26+
using PythonObject = boost::python::object;
27+
28+
#ifndef __APPLE__
29+
/** NOTE:
30+
* For Linux builds (and maybe Windows), it is necessary that the below DLL export occur here.
31+
* This declaration normally lives in Framework/Kernel/PropertyWithValue.cpp. However, because the boost library is
32+
* not linked in Kernel, this declaration can only occur inside the PythonInterface layer
33+
* For Linux builds, this MUST be instantiated BEFORE the declaration of PythonObjectProperty
34+
*/
35+
// Instantiate a copy of the class with our template type so we generate the symbols for the methods in the hxx header.
36+
template class MANTID_PYTHONINTERFACE_CORE_DLL PropertyWithValue<PythonObject>;
37+
#endif
38+
} // namespace Mantid::Kernel
39+
40+
namespace Mantid::PythonInterface {
41+
42+
using Mantid::Kernel::Direction;
43+
using Mantid::Kernel::IValidator_sptr;
44+
using Mantid::Kernel::NullValidator;
45+
using Mantid::Kernel::PythonObject;
46+
47+
class MANTID_PYTHONINTERFACE_CORE_DLL PythonObjectProperty : public Mantid::Kernel::PropertyWithValue<PythonObject> {
48+
public:
49+
// Convenience typedefs
50+
using ValueType = PythonObject;
51+
using BaseClass = Mantid::Kernel::PropertyWithValue<ValueType>;
52+
53+
/** No default constructor */
54+
PythonObjectProperty() = delete;
55+
56+
/** Constructor
57+
* @param name :: The name to assign to the property
58+
* @param defaultValue :: The default python object to assign to the property
59+
* @param validator :: The validator to use for this property, if required.
60+
* @param direction :: The direction (Input/Output/InOut) of this property
61+
*/
62+
PythonObjectProperty(std::string const &name, PythonObject const &defaultValue,
63+
IValidator_sptr const &validator = std::make_shared<NullValidator>(),
64+
unsigned int const direction = Direction::Input)
65+
: BaseClass(name, defaultValue, validator, direction) {}
66+
67+
/** Constructor that's useful for output properties or inputs with non-None default and no validator.
68+
* @param name :: The name to assign to the property
69+
* @param defaultValue :: The default python object to assign to the property
70+
* @param direction :: The direction (Input/Output/InOut) of this property
71+
*/
72+
PythonObjectProperty(std::string const &name, PythonObject const &defaultValue,
73+
unsigned int const direction = Direction::Input)
74+
: BaseClass(name, defaultValue, std::make_shared<NullValidator>(), direction) {}
75+
76+
/** Constructor
77+
* Will lead to the property having default value of None
78+
* @param name :: The name to assign to the property
79+
* @param validator :: The validator to use for this property, if required
80+
* @param direction :: The direction (Input/Output/InOut) of this property
81+
*/
82+
PythonObjectProperty(std::string const &name, IValidator_sptr const &validator,
83+
unsigned int const direction = Direction::Input)
84+
: BaseClass(name, PythonObject(), validator, direction) {}
85+
86+
/** Constructor that's useful for output properties or inputs with default value None and no validator.
87+
* Will lead to the property having a default initial value of None and no validator
88+
* @param name :: The name to assign to the property
89+
* @param direction :: The direction (Input/Output/InOut) of this property
90+
*/
91+
PythonObjectProperty(std::string const &name, unsigned int const direction = Direction::Input)
92+
: BaseClass(name, PythonObject(), std::make_shared<NullValidator>(), direction) {}
93+
94+
/** Constructor from which you can set the property's values through a string:
95+
* @param name :: The name to assign to the property
96+
* @param strvalue :: A string which will set the property being stored
97+
* @param validator :: The validator to use for this property, if required
98+
* @param direction :: The direction (Input/Output/InOut) of this property
99+
* @throw std::invalid_argument if the string passed is not compatible with a python object
100+
*/
101+
PythonObjectProperty(std::string const &name, std::string const &strvalue,
102+
IValidator_sptr const &validator = std::make_shared<NullValidator>(),
103+
unsigned int const direction = Direction::Input)
104+
: BaseClass(name, PythonObject(), strvalue, validator, direction) {}
105+
106+
/** Copy constructor */
107+
PythonObjectProperty(PythonObjectProperty const &other) : BaseClass(other) {}
108+
109+
/** This is required by Property interface */
110+
PythonObjectProperty *clone() const override { return new PythonObjectProperty(*this); }
111+
112+
// Unhide the base class assignment operator
113+
using BaseClass::operator=;
114+
115+
std::string getDefault() const override;
116+
std::string setValue(PythonObject const &obj);
117+
std::string setValue(std::string const &value) override;
118+
std::string setValueFromJson(Json::Value const &value) override;
119+
std::string setDataItem(std::shared_ptr<Kernel::DataItem> const &value) override;
120+
bool isDefault() const override;
121+
};
122+
123+
} // namespace Mantid::PythonInterface
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
// Mantid Repository : https://github.com/mantidproject/mantid
2+
//
3+
// Copyright &copy; 2025 ISIS Rutherford Appleton Laboratory UKRI,
4+
// NScD Oak Ridge National Laboratory, European Spallation Source,
5+
// Institut Laue - Langevin & CSNS, Institute of High Energy Physics, CAS
6+
// SPDX - License - Identifier: GPL - 3.0 +
7+
#pragma once
8+
9+
//----------------------------------------------------------------------
10+
// Includes
11+
//----------------------------------------------------------------------
12+
#include "MantidPythonInterface/core/DllConfig.h"
13+
14+
#include "MantidKernel/IValidator.h"
15+
16+
#include <Python.h>
17+
#include <boost/python/extract.hpp>
18+
#include <boost/python/object.hpp>
19+
20+
// forward declare
21+
namespace Json {
22+
class Value;
23+
}
24+
25+
namespace {
26+
using namespace boost::python;
27+
static inline object const &validate_python_class(object const &pyclass) {
28+
if (PyType_Check(pyclass.ptr())) {
29+
return pyclass;
30+
} else {
31+
throw std::invalid_argument("Attempt to construct validator with an object instead of a class type");
32+
}
33+
}
34+
} // namespace
35+
36+
namespace Mantid::PythonInterface {
37+
38+
using namespace boost::python;
39+
using Mantid::Kernel::IValidator_sptr;
40+
41+
class MANTID_PYTHONINTERFACE_CORE_DLL PythonObjectTypeValidator : public Mantid::Kernel::IValidator {
42+
43+
public:
44+
PythonObjectTypeValidator() : pythonClass(object()) {};
45+
46+
PythonObjectTypeValidator(object const &pyclass) : pythonClass(validate_python_class(pyclass)) {}
47+
48+
~PythonObjectTypeValidator() override = default;
49+
50+
IValidator_sptr clone() const override { return std::make_shared<PythonObjectTypeValidator>(*this); };
51+
52+
private:
53+
object pythonClass;
54+
55+
std::string check(boost::any const &value) const override;
56+
};
57+
58+
} // namespace Mantid::PythonInterface

0 commit comments

Comments
 (0)