mirror of https://github.com/KLayout/klayout.git
WIP: further generation of Python module (kind of slow currently + dependent modules need to be loaded manually)
This commit is contained in:
parent
b2f18c612a
commit
3882f6a3b1
|
|
@ -106,7 +106,9 @@ ClassBase::add_child_class (const ClassBase *cls)
|
|||
// TODO: ugly const_cast hack
|
||||
ClassBase *non_const_cls = const_cast<ClassBase *> (cls);
|
||||
non_const_cls->set_parent (this);
|
||||
m_child_classes.push_back (const_cast <ClassBase *> (cls));
|
||||
// child classes inherit the module of their parent
|
||||
non_const_cls->set_module (module ());
|
||||
m_child_classes.push_back (non_const_cls);
|
||||
}
|
||||
|
||||
bool
|
||||
|
|
@ -497,7 +499,6 @@ ClassBase::merge_declarations ()
|
|||
mp_class_collection->push_back (non_const_decl);
|
||||
}
|
||||
mp_new_class_collection->clear ();
|
||||
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
|||
|
|
@ -58,25 +58,6 @@ class PYAObjectBase;
|
|||
|
||||
// --------------------------------------------------------------------------
|
||||
|
||||
#define PYA_TRY \
|
||||
{ \
|
||||
try {
|
||||
|
||||
#define PYA_CATCH(where) \
|
||||
} catch (tl::ExitException &ex) { \
|
||||
PyErr_SetObject (PyExc_SystemExit, c2python<int> (ex.status ())); \
|
||||
} catch (std::exception &ex) { \
|
||||
std::string msg = std::string(ex.what ()) + tl::to_string (QObject::tr (" in ")) + (where); \
|
||||
PyErr_SetString (PyExc_RuntimeError, msg.c_str ()); \
|
||||
} catch (tl::Exception &ex) { \
|
||||
std::string msg = ex.msg () + tl::to_string (QObject::tr (" in ")) + (where); \
|
||||
PyErr_SetString (PyExc_RuntimeError, msg.c_str ()); \
|
||||
} catch (...) { \
|
||||
std::string msg = tl::to_string (QObject::tr ("Unspecific exception in ")) + (where); \
|
||||
PyErr_SetString (PyExc_RuntimeError, msg.c_str ()); \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief The python interpreter instance
|
||||
*/
|
||||
|
|
@ -2265,6 +2246,18 @@ PythonModule::module ()
|
|||
return mp_module.get ();
|
||||
}
|
||||
|
||||
PyObject *
|
||||
PythonModule::take_module ()
|
||||
{
|
||||
return mp_module.release ();
|
||||
}
|
||||
|
||||
void
|
||||
PythonModule::delete_module ()
|
||||
{
|
||||
mp_module = PythonRef ();
|
||||
}
|
||||
|
||||
void
|
||||
PythonModule::init (const char *mod_name, const char *description)
|
||||
{
|
||||
|
|
@ -2359,6 +2352,18 @@ PythonModule::make_classes (const char *mod_name)
|
|||
{
|
||||
PyObject *module = mp_module.get ();
|
||||
|
||||
// Prepare an __all__ index for the module
|
||||
|
||||
PythonRef all_list;
|
||||
if (! PyObject_HasAttrString (module, "__all__")) {
|
||||
all_list = PythonRef (PyList_New (0));
|
||||
PyObject_SetAttrString (module, "__all__", all_list.get ());
|
||||
} else {
|
||||
all_list = PythonRef (PyObject_GetAttrString (module, "__all__"));
|
||||
}
|
||||
|
||||
PyObject_SetAttrString (module, "__doc__", PythonRef (c2python (m_mod_description)).get ());
|
||||
|
||||
// Create a (built-in) base class for all objects exposed by this module
|
||||
|
||||
m_base_class_name = m_mod_name + ".__Base";
|
||||
|
|
@ -2421,6 +2426,9 @@ PythonModule::make_classes (const char *mod_name)
|
|||
for (tl::weak_collection<gsi::ClassBase>::const_iterator cc = c->begin_child_classes (); cc != c->end_child_classes (); ++cc) {
|
||||
tl_assert (cc->declaration () != 0);
|
||||
if (m_rev_cls_map.find (cc->declaration ()) == m_rev_cls_map.end ()) {
|
||||
if (mod_name && cc->module () != mod_name) {
|
||||
throw tl::Exception (tl::sprintf (tl::to_string (QObject::tr ("Class %s from module %s depends on %s.%s (try 'import klayout.%s' before 'import klayout.%s')")), c->name (), mod_name, cc->module (), cc->name (), cc->module (), mod_name));
|
||||
}
|
||||
all_children_available = false;
|
||||
break;
|
||||
}
|
||||
|
|
@ -2432,6 +2440,9 @@ PythonModule::make_classes (const char *mod_name)
|
|||
}
|
||||
|
||||
if (c->base () && m_rev_cls_map.find (c->base ()) == m_rev_cls_map.end ()) {
|
||||
if (mod_name && c->base ()->module () != mod_name) {
|
||||
throw tl::Exception (tl::sprintf (tl::to_string (QObject::tr ("Class %s from module %s depends on %s.%s (try 'import klayout.%s' before 'import klayout.%s')")), c->name (), mod_name, c->base ()->module (), c->base ()->name (), c->base ()->module (), mod_name));
|
||||
}
|
||||
// can't produce this class yet. The base class needs to be handled first.
|
||||
more_classes = true;
|
||||
continue;
|
||||
|
|
@ -2464,6 +2475,7 @@ PythonModule::make_classes (const char *mod_name)
|
|||
PyTypeObject *type = (PyTypeObject *) PyObject_Call ((PyObject *) &PyType_Type, args.get (), NULL);
|
||||
tl_assert (type != NULL);
|
||||
|
||||
PyList_Append (all_list.get (), PythonRef (c2python (c->name ())).get ());
|
||||
PyModule_AddObject (module, c->name ().c_str (), (PyObject *) type);
|
||||
|
||||
m_cls_map.insert (std::make_pair (type, &*c));
|
||||
|
|
|
|||
|
|
@ -68,6 +68,42 @@ namespace pya
|
|||
throw; \
|
||||
}
|
||||
|
||||
/**
|
||||
* Two helper macros that translate C++ exceptions into Python errors
|
||||
*/
|
||||
|
||||
#define PYA_TRY \
|
||||
{ \
|
||||
try {
|
||||
|
||||
#define PYA_CATCH(where) \
|
||||
} catch (tl::ExitException &ex) { \
|
||||
PyErr_SetObject (PyExc_SystemExit, PyLong_FromLong (ex.status ())); \
|
||||
} catch (std::exception &ex) { \
|
||||
std::string msg = std::string(ex.what ()) + tl::to_string (QObject::tr (" in ")) + (where); \
|
||||
PyErr_SetString (PyExc_RuntimeError, msg.c_str ()); \
|
||||
} catch (tl::Exception &ex) { \
|
||||
std::string msg; \
|
||||
msg = ex.msg () + tl::to_string (QObject::tr (" in ")) + (where); \
|
||||
PyErr_SetString (PyExc_RuntimeError, msg.c_str ()); \
|
||||
} catch (...) { \
|
||||
std::string msg = tl::to_string (QObject::tr ("Unspecific exception in ")) + (where); \
|
||||
PyErr_SetString (PyExc_RuntimeError, msg.c_str ()); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define PYA_CATCH_ANYWHERE \
|
||||
} catch (tl::ExitException &ex) { \
|
||||
PyErr_SetObject (PyExc_SystemExit, PyLong_FromLong (ex.status ())); \
|
||||
} catch (std::exception &ex) { \
|
||||
PyErr_SetString (PyExc_RuntimeError, ex.what ()); \
|
||||
} catch (tl::Exception &ex) { \
|
||||
PyErr_SetString (PyExc_RuntimeError, ex.msg ().c_str ()); \
|
||||
} catch (...) { \
|
||||
PyErr_SetString (PyExc_RuntimeError, tl::to_string (QObject::tr ("Unspecific exception in ")).c_str ()); \
|
||||
} \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief A class encapsulating a python exception
|
||||
*/
|
||||
|
|
@ -143,10 +179,21 @@ public:
|
|||
static std::string python_doc (const gsi::MethodBase *method);
|
||||
|
||||
/**
|
||||
* @brief Gets the PyObject for the module
|
||||
* @brief Gets the PyModule object
|
||||
*/
|
||||
PyObject *module ();
|
||||
|
||||
/**
|
||||
* @brief Gets the PyModule object
|
||||
* This method will release the ownership over the PyObject
|
||||
*/
|
||||
PyObject *take_module ();
|
||||
|
||||
/**
|
||||
* @brief Deletes the PyModule object
|
||||
*/
|
||||
void delete_module ();
|
||||
|
||||
private:
|
||||
void add_python_doc (const gsi::ClassBase &cls, const MethodTable *mt, int mid, const std::string &doc);
|
||||
PyMethodDef *make_method_def ();
|
||||
|
|
|
|||
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
LIBDIR = $$OUT_PWD/../..
|
||||
DESTDIR = $$LIBDIR/pymod
|
||||
TARGET = QtCore
|
||||
|
||||
include($$PWD/../../lib.pri)
|
||||
|
||||
SOURCES = \
|
||||
QtCoreMain.cc \
|
||||
|
||||
HEADERS += \
|
||||
|
||||
INCLUDEPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC
|
||||
DEPENDPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC
|
||||
LIBS += $$PYTHONLIBFILE -L$$LIBDIR -lklayout_tl -lklayout_db -lklayout_gsi -lklayout_pya -lklayout_QtCore
|
||||
|
||||
# Python is somewhat sloppy and relies on the compiler initializing fields
|
||||
# of strucs to 0:
|
||||
QMAKE_CXXFLAGS_WARN_ON += \
|
||||
-Wno-missing-field-initializers
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "../pymodHelper.h"
|
||||
|
||||
DEFINE_PYMOD(QtCore, "QtCore", "KLayout/Qt module 'QtCore'")
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
|
||||
LIBDIR = $$OUT_PWD/../..
|
||||
DESTDIR = $$LIBDIR/pymod
|
||||
TARGET = QtGui
|
||||
|
||||
include($$PWD/../../lib.pri)
|
||||
|
||||
SOURCES = \
|
||||
QtGuiMain.cc \
|
||||
|
||||
HEADERS += \
|
||||
|
||||
INCLUDEPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC
|
||||
DEPENDPATH += $$PYTHONINCLUDE $$TL_INC $$GSI_INC $$PYA_INC
|
||||
LIBS += $$PYTHONLIBFILE -L$$LIBDIR -lklayout_tl -lklayout_db -lklayout_gsi -lklayout_pya -lklayout_QtGui -lklayout_QtCore
|
||||
|
||||
# Python is somewhat sloppy and relies on the compiler initializing fields
|
||||
# of strucs to 0:
|
||||
QMAKE_CXXFLAGS_WARN_ON += \
|
||||
-Wno-missing-field-initializers
|
||||
|
||||
|
|
@ -0,0 +1,25 @@
|
|||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
#include "../pymodHelper.h"
|
||||
|
||||
DEFINE_PYMOD(QtGui, "QtGui", "KLayout/Qt module 'QtGui'")
|
||||
|
|
@ -20,37 +20,6 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include "pya.h"
|
||||
#include "gsi.h"
|
||||
#include "gsiExpression.h"
|
||||
#include "../pymodHelper.h"
|
||||
|
||||
static PyObject *module_init ()
|
||||
{
|
||||
gsi::initialize ();
|
||||
|
||||
// required for the tiling processor for example
|
||||
gsi::initialize_expressions ();
|
||||
|
||||
static pya::PythonModule module;
|
||||
module.init ("klayout.db", "KLayout core module (db)");
|
||||
module.make_classes ("db");
|
||||
|
||||
return module.module ();
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
PyMODINIT_FUNC
|
||||
DEF_INSIDE_PUBLIC
|
||||
initdb ()
|
||||
{
|
||||
module_init ();
|
||||
}
|
||||
#else
|
||||
PyMODINIT_FUNC
|
||||
DEF_INSIDE_PUBLIC
|
||||
PyInit_db ()
|
||||
{
|
||||
return module_init();
|
||||
}
|
||||
#endif
|
||||
DEFINE_PYMOD(db, "db", "KLayout core module 'db'")
|
||||
|
|
|
|||
|
|
@ -20,37 +20,6 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include "pya.h"
|
||||
#include "gsi.h"
|
||||
#include "gsiExpression.h"
|
||||
#include "../pymodHelper.h"
|
||||
|
||||
static PyObject *module_init ()
|
||||
{
|
||||
gsi::initialize ();
|
||||
|
||||
// required for the tiling processor for example
|
||||
gsi::initialize_expressions ();
|
||||
|
||||
static pya::PythonModule module;
|
||||
module.init ("klayout.lay", "KLayout core module (lay)");
|
||||
module.make_classes ("lay");
|
||||
|
||||
return module.module ();
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
PyMODINIT_FUNC
|
||||
DEF_INSIDE_PUBLIC
|
||||
initlay ()
|
||||
{
|
||||
module_init ();
|
||||
}
|
||||
#else
|
||||
PyMODINIT_FUNC
|
||||
DEF_INSIDE_PUBLIC
|
||||
PyInit_lay ()
|
||||
{
|
||||
return module_init();
|
||||
}
|
||||
#endif
|
||||
DEFINE_PYMOD(lay, "lay", "KLayout core module 'lay'")
|
||||
|
|
|
|||
|
|
@ -4,4 +4,6 @@ SUBDIRS = \
|
|||
db \
|
||||
tl \
|
||||
lay \
|
||||
QtGui \
|
||||
QtCore \
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,84 @@
|
|||
|
||||
|
||||
/*
|
||||
|
||||
KLayout Layout Viewer
|
||||
Copyright (C) 2006-2018 Matthias Koefferlein
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
GNU General Public License for more details.
|
||||
|
||||
You should have received a copy of the GNU General Public License
|
||||
along with this program; if not, write to the Free Software
|
||||
Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
||||
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief A helper include file to implement the Python modules
|
||||
*
|
||||
* Use this helper file this way:
|
||||
*
|
||||
* #include "pymodHelper.h"
|
||||
* DEFINE_PYMOD(mymod, "mymod", "KLayout Test module klayout.mymod")
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include "pya.h"
|
||||
#include "gsi.h"
|
||||
#include "gsiExpression.h"
|
||||
|
||||
static PyObject *
|
||||
module_init (const char *mod_name, const char *mod_description)
|
||||
{
|
||||
static pya::PythonModule module;
|
||||
std::string mod_qname (std::string ("klayout.") + mod_name);
|
||||
std::string import_text ("'import " + mod_qname + "'");
|
||||
|
||||
PYA_TRY
|
||||
|
||||
gsi::initialize ();
|
||||
|
||||
// required for the tiling processor for example
|
||||
gsi::initialize_expressions ();
|
||||
|
||||
module.init (mod_qname.c_str (), mod_description);
|
||||
module.make_classes (mod_name);
|
||||
|
||||
return module.take_module ();
|
||||
|
||||
PYA_CATCH_ANYWHERE
|
||||
|
||||
module.delete_module ();
|
||||
return 0;
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
|
||||
#define DEFINE_PYMOD(__name__, __name_str__, __description__) \
|
||||
PyMODINIT_FUNC \
|
||||
DEF_INSIDE_PUBLIC \
|
||||
init##__name__ () \
|
||||
{ \
|
||||
module_init (__name_str__, __description__); \
|
||||
} \
|
||||
|
||||
#else
|
||||
|
||||
#define DEFINE_PYMOD(__name__, __name_str__, __description__) \
|
||||
PyMODINIT_FUNC \
|
||||
DEF_INSIDE_PUBLIC \
|
||||
PyInit_##__name__ () \
|
||||
{ \
|
||||
return module_init (__name_str__, __description__); \
|
||||
} \
|
||||
|
||||
#endif
|
||||
|
||||
|
|
@ -20,37 +20,6 @@
|
|||
|
||||
*/
|
||||
|
||||
#include <Python.h>
|
||||
#include "pya.h"
|
||||
#include "gsi.h"
|
||||
#include "gsiExpression.h"
|
||||
#include "../pymodHelper.h"
|
||||
|
||||
static PyObject *module_init ()
|
||||
{
|
||||
gsi::initialize ();
|
||||
|
||||
// required for the tiling processor for example
|
||||
gsi::initialize_expressions ();
|
||||
|
||||
static pya::PythonModule module;
|
||||
module.init ("klayout.tl", "KLayout core module (tl)");
|
||||
module.make_classes ("tl");
|
||||
|
||||
return module.module ();
|
||||
}
|
||||
|
||||
#if PY_MAJOR_VERSION < 3
|
||||
PyMODINIT_FUNC
|
||||
DEF_INSIDE_PUBLIC
|
||||
inittl ()
|
||||
{
|
||||
module_init ();
|
||||
}
|
||||
#else
|
||||
PyMODINIT_FUNC
|
||||
DEF_INSIDE_PUBLIC
|
||||
PyInit_tl ()
|
||||
{
|
||||
return module_init();
|
||||
}
|
||||
#endif
|
||||
DEFINE_PYMOD(tl, "tl", "KLayout core module 'tl'")
|
||||
|
|
|
|||
Loading…
Reference in New Issue