@@ -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 {
136160namespace  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
0 commit comments