CreateRepositoryFromUrl results in TypeError in 2023
-
Hi. I have some troubles with the example code on GitHub - PluginCafe that shows how to create a Repository using Python.
The code itself runs fine in R26 (R26.012 and R26.110), but results in an error in 2023.1.3.
Did something change from R26 to 2023 how a repository has to be created using
CreateRepositoryFromUrl
or is that a problem with the python API? If it is a problem with the API is there a way around that?The code:
def CreateRepositories(): """Creates repositories for all user databases. Doing this is usually not necessary for performing light- to medium-sized asset operations, and the user preferences repository can then be used instead. Only when there is a substantial amount of assets that must be processed, a repository should be constructed to limit the search space for search operations. The method CreateRepositoryFromUrl() used in this example can also be used to create a repository and its underlying database from scratch when the provided URL points to location where no database has been established yet. """ # Wait for all asset databases to be loaded, abort when this is not possible. if not maxon.AssetDataBasesInterface.WaitForDatabaseLoading(): return RuntimeError("Could not load asset databases.") # Get the default language of Cinema 4D (en-US) for retrieving the repository names. defaultLanguage = maxon.Resource.GetDefaultLanguage() # Iterate over all currently mounted databases and create an asset repository for each of them. # Doing this is usually not necessary as user asset databases are automatically part of the # the user preferences repository which is easier to retrieve. Creating a repository for a # specific user asset database can be useful to speed up asset searches. for database in maxon.AssetDataBasesInterface.GetDatabases(): # Create a unique identifier for the repository. rid = maxon.AssetInterface.MakeUuid(str(database._dbUrl), True) # Repositories can be composed out of other repositories which are called bases. In this # case no bases are used to construct the repository. But with bases a repository for all # user databases could be constructed for example. bases = maxon.BaseArray(maxon.AssetRepositoryRef) # Create a writable and persistent repository for the database URL. If #_dbUrl would point # to a location where no database has been yet stored, the necessary data would be created. repository = maxon.AssetInterface.CreateRepositoryFromUrl( rid, bases, database._dbUrl, True, False, False) if not repository: raise RuntimeError("Repository construction failed.") # Access some properties of the newly created repository. repoId = repository.GetId() isWriteable = repository.IsWritable() name = repository.GetRepositoryName(defaultLanguage) print(f"{repository} ({name}): id - {repoId}, writeable: {isWriteable}")
Error message I receive in C4D 2023:
Traceback (most recent call last): File "scriptmanager", line 558, in <module> File "scriptmanager", line 234, in CreateRepositories File "C:\Program Files\Maxon Cinema 4D 2023\resource\modules\python\libs\python39\maxon\decorators.py", line 383, in Auto ExecStaticMethod(*args) TypeError: unable to convert builtins.NativePyData to @net.maxon.interface.class-cR
-
I just figured out that the API changed in 2023 from:
static MAXON_METHOD Result<UpdatableAssetRepositoryRef> CreateRepositoryFromUrl(const Id& rid, const Block<const AssetRepositoryRef>& bases, const Url& url, Bool writable, Bool derivedInPrefs, Bool tempRepository);
to:
static MAXON_METHOD Result<UpdatableAssetRepositoryRef> CreateRepositoryFromUrl(const Id& rid, const Class<AssetRepositoryRef>& repoType, const Block<const AssetRepositoryRef>& bases, const Url& url, Bool writable, Bool derivedInPrefs, Bool tempRepository, const BackgroundEntryTuple& backgroundJob = {});
In the c++ section of GitHub - PluginCafe there is an updated version:
maxon::UpdatableAssetRepositoryRef repository = maxon::AssetInterface::CreateRepositoryFromUrl( uuid, maxon::AssetRepositoryTypes::AssetDatabase(), bases, database._dbUrl, true, true, true) iferr_return;
I however don't know how to translate that to Python.
In particular, what should I use for
maxon::AssetRepositoryTypes::AssetDatabase()
, andBackgroundEntryTuple
? -
Hi @till-niese you are indeed right, the method was updated in C++ but not in Python although the dynamic handling of the python Maxon API make it possible to use it but the
maxon.AssetRepositoryTypes.AssetDatabase
was not exposed. I will fix it for the next version and properly make theBackgroundEntryTuple
optional.In the meantime you can use the script bellow.
GetRepositoryName
also changed and is now taking 2 arguments.#coding: utf-8 import c4d import maxon # The command id for the Asset Browser. CID_ASSET_BROWSER = 1054225 @maxon.MAXON_REGISTRY("net.maxon.registry.assetrepositorytypes") class AssetRepositoryTypes(maxon.Registry): AssetDatabase = maxon.MAXON_DECLARATION("net.maxon.assets.repositorytype.database") def CreateRepositories(): """Creates repositories for all user databases. Doing this is usually not necessary for performing light- to medium-sized asset operations, and the user preferences repository can then be used instead. Only when there is a substantial amount of assets that must be processed, a repository should be constructed to limit the search space for search operations. The method CreateRepositoryFromUrl() used in this example can also be used to create a repository and its underlying database from scratch when the provided URL points to location where no database has been established yet. """ # Wait for all asset databases to be loaded, abort when this is not possible. if not maxon.AssetDataBasesInterface.WaitForDatabaseLoading(): return RuntimeError("Could not load asset databases.") # Get the default language of Cinema 4D (en-US) for retrieving the repository names. defaultLanguage = maxon.Resource.GetDefaultLanguage() # Iterate over all currently mounted databases and create an asset repository for each of them. # Doing this is usually not necessary as user asset databases are automatically part of the # the user preferences repository which is easier to retrieve. Creating a repository for a # specific user asset database can be useful to speed up asset searches. for database in maxon.AssetDataBasesInterface.GetDatabases(): # Create a unique identifier for the repository. rid = maxon.AssetInterface.MakeUuid(str(database._dbUrl), True) # Repositories can be composed out of other repositories which are called bases. In this # case no bases are used to construct the repository. But with bases a repository for all # user databases could be constructed for example. bases = maxon.BaseArray(maxon.AssetRepositoryRef) # Create a writable and persistent repository for the database URL. If #_dbUrl would point # to a location where no database has been yet stored, the necessary data would be created. assetDb = AssetRepositoryTypes.AssetDatabase assetDb = maxon.RegistryInterface.FindEntryValue(assetDb._registry, assetDb._ids) repository = maxon.AssetInterface.CreateRepositoryFromUrl( rid, assetDb, bases, database._dbUrl, True, False, False, None) if not repository: raise RuntimeError("Repository construction failed.") # Access some properties of the newly created repository. repoId = repository.GetId() isWriteable = repository.IsWritable() name = repository.GetRepositoryName(defaultLanguage, True) print(f"{repository} ({name}): id - {repoId}, writeable: {isWriteable}") if __name__ == "__main__": CreateRepositories() c4d.EventAdd()
Cheers,
Maxime. -
Hi @m_adam, this works perfectly. Thank you for your fast response.