@@ -14,7 +14,7 @@ namespace cadabra {
1414 // /
1515 // / Helper class to ensure that all Python property objects derive from the
1616 // / same base class.
17- class BaseProperty {
17+ class BoundPropertyBase {
1818 };
1919
2020 // / \ingroup pythoncore
@@ -42,10 +42,14 @@ namespace cadabra {
4242 // / The question is now what we do when Python keeps a pointer to these
4343 // / objects, and let that pointer escape local scope (e.g. by returning
4444 // / the Python property object). How do we keep it in scope?
45- template <class T >
46- class Property : public std ::enable_shared_from_this<Property<T>>, public BaseProperty {
45+ template <typename PropT, typename ... ParentTs>
46+ class BoundProperty
47+ : public std::enable_shared_from_this<BoundProperty<PropT>>
48+ , public BoundPropertyBase
49+ , public BoundProperty<ParentTs>... {
4750 public:
48- Property (std::shared_ptr<cadabra::Ex> obj, std::shared_ptr<cadabra::Ex> params = 0 );
51+ BoundProperty ();
52+ BoundProperty (Ex_ptr obj, Ex_ptr params = 0 );
4953
5054 // / Human-readable form in text, i.e. no special formatting.
5155 std::string str_ () const ;
@@ -56,90 +60,37 @@ namespace cadabra {
5660 // / Python-parseable form. FIXME: not correct right now.
5761 std::string repr_ () const ;
5862
63+ static BoundProperty get_from_it (Ex::iterator ex, bool ignore_parent_rel);
64+ static BoundProperty get_from_ex (Ex_ptr ex, bool ignore_parent_rel);
65+ static BoundProperty get_from_exnode (ExNode exnode, bool ignore_parent_rel);
5966
60- private:
6167 // We keep a pointer to the C++ property, so it is possible to
6268 // query properties using the Python interface. However, this C++
6369 // object is owned by the C++ kernel and does not get destroyed
6470 // when the Python object goes out of scope.
6571
6672 // When the Python object survives the local scope, results are
6773 // undefined.
68- T *prop;
74+ const PropT *prop;
6975
7076 // We also keep a shared pointer to the expression for which we
7177 // have defined this property, so that we can print sensible
7278 // information.
73- std::shared_ptr<cadabra::Ex> for_obj;
79+ Ex_ptr for_obj;
7480 };
7581
82+ template <typename PropT, typename ... ParentTs>
83+ using PyProperty = pybind11::class_<
84+ BoundProperty<PropT>, // C++ type
85+ std::shared_ptr<BoundProperty<PropT>>, // Holder type
86+ BoundPropertyBase, BoundProperty<ParentTs>... // Parent classes
87+ >;
7688
77- template <class Prop >
78- Property<Prop>::Property(std::shared_ptr<Ex> ex, std::shared_ptr<Ex> param)
79- {
80- for_obj = ex;
81- Kernel *kernel = get_kernel_from_scope ();
82- prop = new Prop (); // we keep a pointer, but the kernel owns it.
83- // std::cerr << "Declaring property " << prop->name() << " in kernel " << kernel << std::endl;
84- kernel->inject_property (prop, ex, param);
85- }
86-
87- template <class Prop >
88- std::string Property<Prop>::str_() const
89- {
90- std::ostringstream str;
91- str << " Attached property " ;
92- prop->latex (str); // FIXME: this should call 'str' on the property, which does not exist yet
93- str << " to " + Ex_as_str (for_obj) + " ." ;
94- return str.str ();
95- }
96-
97- template <class Prop >
98- std::string Property<Prop>::latex_() const
99- {
100- std::ostringstream str;
101-
102- // HERE: this text should go away, property should just print itself in a python form,
103- // the decorating text should be printed in a separate place.
104-
105- str << " \\ text{Attached property " ;
106- prop->latex (str);
107- std::string bare = Ex_as_latex (for_obj);
108- str << " to~}" + bare + " ." ;
109- return str.str ();
110- }
111-
112- template <>
113- std::string Property<LaTeXForm>::latex_() const ;
114-
115- template <class Prop >
116- std::string Property<Prop>::repr_() const
117- {
118- // FIXME: this needs work, it does not output things which can be fed back into python.
119- return " Property::repr: " + prop->name ();
120- }
121-
122- template <class P >
123- void def_prop (pybind11::module & m, const char * docstring = " " )
124- {
125- using namespace pybind11 ;
126-
127- class_<Property<P>, std::shared_ptr<Property<P>>, BaseProperty>(m, std::make_shared<P>()->name ().c_str ())
128- .def (
129- init<std::shared_ptr<Ex>, std::shared_ptr<Ex>>(),
130- arg (" ex" ),
131- arg (" param" ),
132- docstring
133- )
134- .def (" __str__" , &Property<P>::str_)
135- .def (" __repr__" , &Property<P>::repr_)
136- .def (" _latex_" , &Property<P>::latex_);
137- }
138-
89+ template <typename PropT, typename ... ParentTs>
90+ PyProperty<PropT, ParentTs...> def_prop (pybind11::module & m, const char * docstring = " " );
13991
14092 pybind11::list list_properties ();
14193
142-
14394 void init_properties (pybind11::module & m);
14495
14596 }
0 commit comments