Skip to content

Commit e065292

Browse files
committed
Now one can import gompy.types.OGF as OGF
(we'll see what CI says ...)
1 parent c1975c1 commit e065292

File tree

6 files changed

+55
-7
lines changed

6 files changed

+55
-7
lines changed

lib/programming_examples/Python/gompy_example.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
# To be run outside Graphite (after gompy is installed)
22

3-
import gompy
4-
OGF = gompy.interpreter().meta_types.OGF
3+
import gompy.types.OGF as OGF
54

65
S = OGF.MeshGrob()
76
S.I.Shapes.create_sphere()

plugins/OGF/gompy/interpreter/py_graphite_object.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -130,7 +130,7 @@ namespace OGF {
130130
return Py_hash_t(object);
131131
}
132132

133-
static PyObject* graphite_Object_getattro(
133+
PyObject* graphite_Object_getattro(
134134
PyObject* self, PyObject* name_in
135135
) {
136136
geo_debug_assert(PyGraphite_Check(self));

plugins/OGF/gompy/interpreter/py_graphite_object.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,9 @@ namespace OGF {
130130
PyObject* self, PyObject* args, PyObject* keywords
131131
);
132132

133+
PyObject* graphite_Object_getattro(
134+
PyObject* self, PyObject* name_in
135+
);
133136
}
134137
}
135138

plugins/OGF/gompy/interpreter/python_interpreter.cpp

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,13 +70,37 @@ namespace {
7070
return result;
7171
}
7272

73+
PyObject* graphite_module_get_attro(PyObject* self, PyObject* name_in) {
74+
geo_argused(self);
75+
// - We need this getattro override that returns something
76+
// when "__path__" is looked up, else Python runtime does not
77+
// see our module as a package (from which gompy.xxx can be imported).
78+
// - import gompy.xxx as yyy does not invoke get_attro(), it uses instead
79+
// the system-wide module dictionary, populated with what we want to be
80+
// able to import in PythonInterpreter::PythonInterpreter().
81+
std::string name = python_to_string(name_in);
82+
if(name == "__path__") {
83+
return string_to_python("");
84+
}
85+
// Positioning this exception indicates that attribute lookup fallsback
86+
// to default behavior.
87+
PyErr_SetObject(PyExc_AttributeError, name_in);
88+
return nullptr;
89+
}
90+
7391
PyMethodDef graphite_module_methods[] = {
7492
{
7593
"interpreter",
7694
graphite_interpreter,
7795
METH_NOARGS,
7896
"gets the interpreter"
7997
},
98+
{
99+
"__getattr__",
100+
graphite_module_get_attro,
101+
METH_O,
102+
"gets an attribute from the interpreter"
103+
},
80104
{
81105
nullptr, /* ml_name */
82106
nullptr, /* ml_meth */
@@ -87,7 +111,7 @@ namespace {
87111

88112
static struct PyModuleDef graphite_moduledef = {
89113
PyModuleDef_HEAD_INIT,
90-
"gompy", /* m_name */
114+
"gompy", /* m_name */
91115
"Graphite Object Model", /* m_doc */
92116
-1, /* m_size */
93117
graphite_module_methods, /* m_methods */
@@ -136,9 +160,26 @@ namespace {
136160
namespace OGF {
137161

138162
PythonInterpreter::PythonInterpreter() : main_module_(nullptr) {
163+
// Tests whether Python is running in Graphite (true) or not (false)
139164
use_embedded_interpreter_ = (Py_IsInitialized() == 0);
140165

141166
if(!use_embedded_interpreter_) {
167+
// Shortcuts that one can import ... as ...
168+
// gompy.interpreter().meta_types -> gompy.types
169+
// gompy.interpreter().meta_types.OGF -> gompy.types.OGF
170+
171+
PyObject *sys_modules = PySys_GetObject("modules");
172+
Scope* meta_types = get_meta_types();
173+
Scope* OGF = nullptr;
174+
meta_types->resolve("OGF").get_value(OGF);
175+
geo_assert(OGF != nullptr);
176+
177+
PyObject* py_meta_types = PyGraphiteObject_New(meta_types);
178+
PyObject* py_OGF = PyGraphiteObject_New(OGF);
179+
180+
// Note: PyDict_SetItemString() increases refconut
181+
PyDict_SetItemString(sys_modules, "gompy.types", py_meta_types);
182+
PyDict_SetItemString(sys_modules, "gompy.types.OGF", py_OGF);
142183
return;
143184
}
144185

src/lib/OGF/gom/interpreter/interpreter.cpp

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1116,13 +1116,16 @@ namespace OGF {
11161116
return args;
11171117
}
11181118

1119-
void Interpreter::search(const std::string& needle_in, const std::string& path_in) {
1119+
void Interpreter::search(
1120+
const std::string& needle_in, const std::string& path_in
1121+
) {
11201122
std::string needle = needle_in;
11211123
if(needle == "") {
11221124
Logger::err("GOM") << "Search: empty string specified" << std::endl;
11231125
}
11241126

1125-
// "*" to display all meta-information available in the system (takes a while !!)
1127+
// "*" to display all meta-information available in the system
1128+
// (takes a while !!)
11261129
if(needle == "*") {
11271130
needle = "";
11281131
}

src/lib/OGF/gom/reflection/meta_class.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -446,7 +446,9 @@ namespace OGF {
446446
/**
447447
* \copydoc Object::search()
448448
*/
449-
void search(const std::string& needle, const std::string& path = "") override;
449+
void search(
450+
const std::string& needle, const std::string& path = ""
451+
) override;
450452

451453
/**
452454
* \copydoc Object::get_doc()

0 commit comments

Comments
 (0)