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(); }
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; }