Solved 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(), and BackgroundEntryTuple?

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 the BackgroundEntryTuple 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.