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>(); }
PropertyIterator(IComponentContext& context, const PyScript::ScriptObject& pythonObject, const PyScript::ScriptDict& metaDataDict) : context_(context), object_(pythonObject), metaDataDict_(metaDataDict) { if (object_.get() == nullptr) { return; } // Get a list of strings appropriate for object arguments PyScript::ScriptObject dir = object_.getDir(PyScript::ScriptErrorPrint()); if (dir.get() != nullptr) { iterator_ = dir.getIter(PyScript::ScriptErrorPrint()); } }
std::string DefinitionDetails::generateName( const PyScript::ScriptObject & object ) { PyScript::ScriptErrorPrint errorHandler; std::string typeName; if (PyScript::ScriptType::check( object )) { // Type type // type.__module__ + type.__name__ + id( object ) PyScript::ScriptType scriptType( reinterpret_cast<PyTypeObject*>( object.get() ), PyScript::ScriptObject::FROM_BORROWED_REFERENCE ); scriptType.getAttribute( "__module__", typeName, errorHandler ); typeName += '.'; typeName += scriptType.name(); } else { // Class or None type // __module__ + __name__ + id( object ) typeName = object.str( errorHandler ).c_str(); } // Add an address in case there are multiple classes/types with the same // name in the same file. // E.g. // # module "Test" // class A( object ): // class InnerClass( object ): // pass // pass // class B( object ): // class InnerClass( object ): # different type with the name "Test.InnerClass" // pass // pass typeName += " at "; typeName += std::to_string( object.id().asUnsignedLongLong( PyScript::ScriptErrorRetain() ) ); // Check for overflow assert( !PyScript::Script::hasError() ); #if defined( _DEBUG ) PyScript::Script::clearError(); #endif // defined( _DEBUG ) return typeName; }
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; }
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(); }
bool NoneConverter::toVariant(const PyScript::ScriptObject& inObject, Variant& outVariant) /* override */ { // Check for types.NoneType if (!inObject.isNone()) { return false; } outVariant = Variant(nullptr); return true; }
DefinitionDetails::DefinitionDetails(IComponentContext& context, const PyScript::ScriptObject& pythonObject) : context_(context), name_(DefinitionDetails::generateName(pythonObject)), pythonObject_(pythonObject), metaData_(MetaNone()) { assert(!name_.empty()); // Assume that _metaData is not modified after creation const char* metaDataName = "_metaData"; const auto metaDataAttribute = pythonObject.getAttribute(metaDataName, PyScript::ScriptErrorClear()); metaDataDict_ = PyScript::ScriptDict::create(metaDataAttribute); attachListenerHooks(pythonObject_); }
bool PrimitiveConverter< T >::toVariant( const PyScript::ScriptObject & inObject, Variant & outVariant ) /* override */ { T value; const bool result = inObject.convertTo( value, PyScript::ScriptErrorClear() ); if (!result) { return false; } outVariant = Variant( value ); return true; }
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; }