mirror of
https://github.com/thp/pyotherside.git
synced 2025-01-17 23:22:53 +08:00
Merge pull request #54 from xealits/importNames
Import names from module
This commit is contained in:
commit
066fbb5a51
@ -62,6 +62,8 @@ QPython::QPython(QObject *parent, int api_version_major, int api_version_minor)
|
||||
|
||||
QObject::connect(this, SIGNAL(import(QString,QJSValue *)),
|
||||
worker, SLOT(import(QString,QJSValue *)));
|
||||
QObject::connect(this, SIGNAL(import_names(QString, QVariant, QJSValue *)),
|
||||
worker, SLOT(import_names(QString, QVariant, QJSValue *)));
|
||||
QObject::connect(worker, SIGNAL(imported(bool,QJSValue *)),
|
||||
this, SLOT(imported(bool,QJSValue *)));
|
||||
|
||||
@ -126,6 +128,67 @@ QPython::addImportPath(QString path)
|
||||
PyList_Insert(sys_path, 0, cwd.borrow());
|
||||
}
|
||||
|
||||
void
|
||||
QPython::importNames(QString name, QVariant args, QJSValue callback)
|
||||
{
|
||||
QJSValue *cb = 0;
|
||||
if (!callback.isNull() && !callback.isUndefined() && callback.isCallable()) {
|
||||
cb = new QJSValue(callback);
|
||||
}
|
||||
emit import_names(name, args, cb);
|
||||
}
|
||||
|
||||
bool
|
||||
QPython::importNames_sync(QString module_name, QVariant args)
|
||||
{
|
||||
// The plan is to "from module_name import a, b, c". And args is the list with a, b, c.
|
||||
// The module_name can be a packaged module "x.y.z" -- "from x.y.z import a, b, c".
|
||||
// Thus:
|
||||
// - import the module, given by module_name,
|
||||
// - get the objects from the module, given by names in args,
|
||||
// - put the objects into globals of priv
|
||||
|
||||
QByteArray utf8bytes = module_name.toUtf8();
|
||||
const char *moduleName = utf8bytes.constData();
|
||||
|
||||
ENSURE_GIL_STATE;
|
||||
|
||||
// PyOtherSide API 1.2 behavior: "import x.y.z" -- where the module 'z' is needed
|
||||
PyObjectRef module = PyObjectRef(PyImport_ImportModule(moduleName), true);
|
||||
|
||||
if (!module) {
|
||||
emitError(QString("Cannot import module: %1 (%2)").arg(module_name).arg(priv->formatExc()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// at this point the module with the target objects is in PyObjectRef module,
|
||||
// it should be well imported in Python
|
||||
|
||||
// Get the names of functions/objects to import
|
||||
QVariantList vl = args.toList();
|
||||
|
||||
QString obj_name; // object name to import
|
||||
PyObjectRef result; // the object, obtained from globals_temp
|
||||
|
||||
// for each object name try to get it from the module
|
||||
// - on success put it into priv.globals
|
||||
// - on failure emit the error and continue
|
||||
for (QVariantList::const_iterator obj = vl.begin(); obj != vl.end(); ++obj)
|
||||
{
|
||||
obj_name = obj->toString();
|
||||
utf8bytes = obj_name.toUtf8();
|
||||
PyObject *res = PyObject_GetAttrString(module.borrow(), utf8bytes);
|
||||
result = PyObjectRef(res, true);
|
||||
if (!result) {
|
||||
emitError(QString("Object '%1' is not found in '%2': (%3)").arg(obj_name).arg(module_name).arg(priv->formatExc()));
|
||||
continue;
|
||||
}
|
||||
PyDict_SetItemString(priv->globals.borrow(), utf8bytes.constData(), result.borrow());
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
QPython::importModule(QString name, QJSValue callback)
|
||||
{
|
||||
|
@ -130,6 +130,65 @@ class QPython : public QObject {
|
||||
Q_INVOKABLE QVariant
|
||||
evaluate(QString expr);
|
||||
|
||||
/**
|
||||
* \brief Asynchronously import objects from Python module
|
||||
*
|
||||
* Imports objects, given by list of names, from Python module asynchronously.
|
||||
* The function will return immediately. If the module is successfully imported,
|
||||
* the supplied \a callback will be called. Only then will the
|
||||
* imported module be available:
|
||||
*
|
||||
* \code
|
||||
* Python {
|
||||
* Component.onCompleted: {
|
||||
* importNames('os', ['path'], function (success) {
|
||||
* if (success) {
|
||||
* // You can use the "path" submodule here
|
||||
* } else {
|
||||
* console.log('Importing failed')
|
||||
* }
|
||||
* });
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* If an error occurs while trying to import, the signal error()
|
||||
* will be emitted with detailed information about the error.
|
||||
*
|
||||
* \arg name The name of the Python module to import from
|
||||
* \arg args The name of Python objects to import from the module
|
||||
* \arg callback The JS callback to be called when the module is
|
||||
* successfully imported
|
||||
**/
|
||||
Q_INVOKABLE void
|
||||
importNames(QString name, QVariant args, QJSValue callback);
|
||||
|
||||
/**
|
||||
* \brief Synchronously import objects from Python module
|
||||
*
|
||||
* Imports objects, given by list of names, from Python module synchronously.
|
||||
* This function will block until the objects are imported and available.
|
||||
* In general, you should use importNames() instead of this function
|
||||
* to avoid blocking the QML UI thread. Example use:
|
||||
*
|
||||
* \code
|
||||
* Python {
|
||||
* Component.onCompleted: {
|
||||
* var success = importNames_sync('os', ['path']);
|
||||
* if (success) {
|
||||
* // You can use the "path" submodule here
|
||||
* }
|
||||
* }
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* \arg name The name of the Python module to import from
|
||||
* \arg args The name of Python objects to import from the module
|
||||
* \result \c true if the import was successful, \c false otherwise
|
||||
**/
|
||||
Q_INVOKABLE bool
|
||||
importNames_sync(QString name, QVariant args);
|
||||
|
||||
/**
|
||||
* \brief Asynchronously import a Python module
|
||||
*
|
||||
@ -304,6 +363,7 @@ class QPython : public QObject {
|
||||
/* For internal use only */
|
||||
void process(QVariant func, QVariant args, QJSValue *callback);
|
||||
void import(QString name, QJSValue *callback);
|
||||
void import_names(QString name, QVariant args, QJSValue *callback);
|
||||
|
||||
private slots:
|
||||
void receive(QVariant data);
|
||||
|
@ -48,3 +48,12 @@ QPythonWorker::import(QString name, QJSValue *callback)
|
||||
emit imported(result, callback);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
QPythonWorker::import_names(QString name, QVariant args, QJSValue *callback)
|
||||
{
|
||||
bool result = qpython->importNames_sync(name, args);
|
||||
if (callback) {
|
||||
emit imported(result, callback); // using the same imported signal at the end
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ class QPythonWorker : public QObject {
|
||||
public slots:
|
||||
void process(QVariant func, QVariant args, QJSValue *callback);
|
||||
void import(QString func, QJSValue *callback);
|
||||
void import_names(QString func, QVariant args, QJSValue *callback);
|
||||
|
||||
signals:
|
||||
void finished(QVariant result, QJSValue *callback);
|
||||
|
Loading…
x
Reference in New Issue
Block a user