@@ -49,14 +49,36 @@ class SourceInterface;
4949namespace SourceXPy {
5050
5151/* *
52- * Wrap the required context for a sourcextractor++ run
52+ * @brief Wrap the required context for a sourcextractor++ run
53+ * @details
54+ * A context includes factory methods, configuration manager, etc.
5355 */
5456class Context {
5557public:
58+ /* *
59+ * Constructor
60+ * @param global_config
61+ * Global configuration (i.e., detection, background), equivalent to the content from a `.conf` file
62+ * @param measurement_config
63+ * Measurement configuration (an instance of sourcextractor.config.measurement_config.MeasurementConfig)
64+ * If None, `global_measurement_config` will be used as usual, but this prevents multiple contexts
65+ * from being useful.
66+ */
5667 Context (const boost::python::dict& global_config, const boost::python::object& measurement_config);
68+
69+ /* *
70+ * Non copyable
71+ */
5772 Context (const Context&) = delete ;
58- Context (Context&&) = default ;
5973
74+ /* *
75+ * Movable
76+ */
77+ Context (Context&&) = default ;
78+
79+ /* *
80+ * @return A dictionary where they key is the property name, and the value a list of output columns / attributes
81+ */
6082 boost::python::dict get_properties () const ;
6183
6284 std::shared_ptr<Euclid::Configuration::ConfigManager> m_config_manager;
@@ -74,21 +96,49 @@ class Context {
7496 std::shared_ptr<SourceXtractor::OutputFactory> m_output_factory;
7597 std::function<Euclid::Table::Row(const SourceXtractor::SourceInterface&)> m_source_to_row;
7698
77- static void enter (const std::shared_ptr<Context>&);
78- static void exit (const std::shared_ptr<Context>&, const boost::python::object& exc_type,
79- const boost::python::object& exc_value, const boost::python::object& traceback);
99+ /* *
100+ * Set `context` as the default context when instantiating pipeline stages.
101+ * @see https://docs.python.org/3/reference/datamodel.html#object.__enter__
102+ */
103+ static void enter (const std::shared_ptr<Context>& context);
104+
105+ /* *
106+ * Clear the default context
107+ * @see https://docs.python.org/3/reference/datamodel.html#object.__exit__
108+ */
109+ static void exit (const std::shared_ptr<Context>& context, const boost::python::object& exc_type,
110+ const boost::python::object& exc_value, const boost::python::object& traceback);
111+
112+ /* *
113+ * @return The active default context
114+ */
80115 static const std::shared_ptr<Context>& get_global_context ();
81116
82117private:
118+ /* *
119+ * One default context per thread
120+ */
83121 static thread_local std::shared_ptr<Context> s_context;
84122};
85123
124+ /* *
125+ * Helper class that uses the thread default context when we get a None from Python
126+ */
86127class ContextPtr {
87128public:
129+ /* *
130+ * Constructor
131+ * @param ptr The Context to use. If None (nullptr), use the thread default.
132+ * @throw boost::python::error_already_set if both the parameter and the default context are null
133+ */
88134 ContextPtr (std::shared_ptr<Context> ptr) : m_ptr(std::move(ptr)) { // NOLINT: Allow implicit conversion
89135 if (!m_ptr) {
90136 m_ptr = Context::get_global_context ();
91137 }
138+ if (!m_ptr) {
139+ PyErr_SetString (PyExc_ValueError, " Missing Context" );
140+ boost::python::throw_error_already_set ();
141+ }
92142 }
93143
94144 Context* operator ->() const {
0 commit comments