bool Property::isCollection() const /* override */ { // Get the attribute PyScript::ScriptErrorPrint errorHandler; PyScript::ScriptObject attribute = impl_->pythonObject_.getAttribute(impl_->key_.c_str(), errorHandler); assert(attribute.exists()); if (!attribute.exists()) { return false; } return PythonType::scriptTypeToTypeId(attribute) == TypeId::getType<Collection>(); }
bool Property::isMethod() const /* override */ { // Get the attribute PyScript::ScriptErrorPrint errorHandler; PyScript::ScriptObject attribute = impl_->pythonObject_.getAttribute(impl_->key_.c_str(), errorHandler); assert(attribute.exists()); if (!attribute.exists()) { return false; } // Checks if the attribute is "callable", it may be: // - an instance with a __call__ attribute // or // - a type with a tp_call member, such as // -- a method on a class // -- a function/lambda type return attribute.isCallable(); }
Variant Property::invoke(const ObjectHandle& object, const IDefinitionManager& definitionManager, const ReflectedMethodParameters& parameters) /* override */ { const bool callable = this->isMethod(); assert(callable); if (!callable) { return Variant(); } auto pTypeConverters = impl_->get<PythonType::Converters>(); assert(pTypeConverters != nullptr); // Parse arguments auto tuple = PyScript::ScriptTuple::create(parameters.size()); size_t i = 0; for (auto itr = parameters.cbegin(); (i < parameters.size()) && (itr != parameters.cend()); ++i, ++itr) { auto parameter = (*itr); PyScript::ScriptObject scriptObject; const bool success = pTypeConverters->toScriptType(parameter, scriptObject); assert(success); tuple.setItem(i, scriptObject); } PyScript::ScriptArgs args = PyScript::ScriptArgs(tuple.get(), PyScript::ScriptObject::FROM_BORROWED_REFERENCE); // Call method PyScript::ScriptErrorPrint errorHandler; const bool allowNullMethod = false; PyScript::ScriptObject returnValue = impl_->pythonObject_.callMethod(impl_->key_.c_str(), args, errorHandler, allowNullMethod); // Return value Variant result; if (returnValue.exists()) { const bool success = pTypeConverters->toVariant(returnValue, result, object, impl_->key_); assert(success); } return result; }
size_t Property::parameterCount() const /* override */ { PyScript::ScriptObject attribute = impl_->pythonObject_.getAttribute(impl_->key_.c_str(), PyScript::ScriptErrorPrint()); assert(attribute.exists()); if (!attribute.exists()) { return 0; } if (!attribute.isCallable()) { return 0; } // -- Old-style class instance.__call__(self) if (PyScript::ScriptInstance::check(attribute)) { auto callObject = attribute.getAttribute("__call__", PyScript::ScriptErrorClear()); if (!callObject.exists()) { return 0; } // Convert __call__(self) method object to a function() auto methodObject = PyScript::ScriptMethod::create(callObject); assert(methodObject.exists()); auto functionObject = methodObject.function(); assert(functionObject.exists()); // Convert function to code and get arg count auto codeObject = functionObject.code(); assert(codeObject.exists()); const auto argCount = codeObject.argCount(); // Methods subtract 1 argument for "self". const int selfArg = 1; assert(argCount > 0); return (argCount - selfArg); } // -- Old-style class constructor instance(self) if (PyScript::ScriptClass::check(attribute)) { auto initObject = attribute.getAttribute("__init__", PyScript::ScriptErrorClear()); if (!initObject.exists()) { // Default __init__(self) return 0; } // Convert __init__(self) method object to a function() auto methodObject = PyScript::ScriptMethod::create(initObject); assert(methodObject.exists()); auto functionObject = methodObject.function(); assert(functionObject.exists()); // Convert function to code and get arg count auto codeObject = functionObject.code(); assert(codeObject.exists()); const auto argCount = codeObject.argCount(); // Methods subtract 1 argument for "self". const int selfArg = 1; assert(argCount > 0); return (argCount - selfArg); } // -- Method like self.function(self) auto methodObject = PyScript::ScriptMethod::create(attribute); if (methodObject.exists()) { // Convert self.function() method object to a function() auto functionObject = methodObject.function(); assert(functionObject.exists()); // Convert function to code and get arg count auto codeObject = functionObject.code(); assert(codeObject.exists()); const auto argCount = codeObject.argCount(); // Methods subtract 1 argument for "self". const int selfArg = 1; assert(argCount > 0); return (argCount - selfArg); } // -- Plain function or lambda type auto functionObject = PyScript::ScriptFunction::create(attribute); if (functionObject.exists()) { auto codeObject = functionObject.code(); assert(codeObject.exists()); return codeObject.argCount(); } // -- New-style class instance.__call__(self) auto callObject = attribute.getAttribute("__call__", PyScript::ScriptErrorClear()); // Convert __call__(self) method object to a function() methodObject = PyScript::ScriptMethod::create(callObject); if (methodObject.exists()) { // Convert function to code and get arg count functionObject = methodObject.function(); assert(functionObject.exists()); auto codeObject = functionObject.code(); assert(codeObject.exists()); const auto argCount = codeObject.argCount(); // Methods subtract 1 argument for "self". const int selfArg = 1; assert(argCount > 0); return (argCount - selfArg); } // -- New-style class constructor instance.__init__(self) auto initObject = attribute.getAttribute("__init__", PyScript::ScriptErrorClear()); // Convert __init__(self) method object to a function() methodObject = PyScript::ScriptMethod::create(initObject); if (methodObject.exists()) { // Convert function to code and get arg count functionObject = methodObject.function(); assert(functionObject.exists()); auto codeObject = functionObject.code(); assert(codeObject.exists()); const auto argCount = codeObject.argCount(); // Methods subtract 1 argument for "self". const int selfArg = 1; assert(argCount > 0); return (argCount - selfArg); } // Default __init__(self) return 0; }