Skip to content

core ¤

Core schema definitions.

Contains class definitions for all common nendo objects.

NendoBlob ¤

Bases: NendoBlobBase

Class representing a blob object in Nendo.

Used to store binary data, e.g. large numpy matrices in the nendo library. Not used for storing waveforms, as they are considered native NendoResources.

NendoCollection ¤

NendoCollection(**kwargs: Any)

Bases: NendoCollectionBase

Basic class representing a nendo collection.

Source code in src/nendo/schema/core.py
930
931
932
def __init__(self, **kwargs: Any) -> None:  # noqa: D107
    super().__init__(**kwargs)
    self.nendo_instance = Nendo()
add_related_collection(
    track_ids: List[Union[str, UUID]],
    name: str,
    description: str = "",
    user_id: Optional[Union[str, UUID]] = None,
    relationship_type: str = "relationship",
    meta: Optional[Dict[str, Any]] = None,
) -> NendoCollection

Create a new collection with a relationship to the current collection.

Parameters:

Name Type Description Default
track_ids List[Union[str, UUID]]

List of track ids.

required
name str

Name of the new related collection.

required
description str

Description of the new related collection.

''
user_id UUID

The ID of the user adding the collection.

None
relationship_type str

Type of the relationship.

'relationship'
meta Dict[str, Any]

Meta of the new related collection.

None

Returns:

Type Description
NendoCollection

The newly added NendoCollection object.

Source code in src/nendo/schema/core.py
1130
1131
1132
1133
1134
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
1151
1152
1153
1154
1155
1156
1157
1158
1159
1160
1161
1162
def add_related_collection(
    self,
    track_ids: List[Union[str, uuid.UUID]],
    name: str,
    description: str = "",
    user_id: Optional[Union[str, uuid.UUID]] = None,
    relationship_type: str = "relationship",
    meta: Optional[Dict[str, Any]] = None,
) -> NendoCollection:
    """Create a new collection with a relationship to the current collection.

    Args:
        track_ids (List[Union[str, uuid.UUID]]): List of track ids.
        name (str): Name of the new related collection.
        description (str): Description of the new related collection.
        user_id (UUID, optional): The ID of the user adding the collection.
        relationship_type (str): Type of the relationship.
        meta (Dict[str, Any]): Meta of the new related collection.

    Returns:
        schema.NendoCollection: The newly added NendoCollection object.
    """
    self.nendo_instance.library.add_related_collection(
        track_ids=track_ids,
        collection_id=self.id,
        name=name,
        description=description,
        user_id=user_id,
        relationship_type=relationship_type,
        meta=meta,
    )
    self.refresh()
    return self

add_track ¤

add_track(
    track_id: Union[str, UUID],
    position: Optional[int] = None,
    meta: Optional[Dict[str, Any]] = None,
) -> NendoCollection

Creates a relationship from the track to the collection.

Parameters:

Name Type Description Default
track_id Union[str, UUID]

ID of the track to add.

required
position int

Target position of the track inside the collection.

None
meta Dict[str, Any]

Metadata of the relationship.

None

Returns:

Type Description
NendoCollection

The collection itself.

Source code in src/nendo/schema/core.py
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098
1099
1100
1101
1102
1103
1104
1105
1106
1107
1108
def add_track(
    self,
    track_id: Union[str, uuid.UUID],
    position: Optional[int] = None,
    meta: Optional[Dict[str, Any]] = None,
) -> NendoCollection:
    """Creates a relationship from the track to the collection.

    Args:
        track_id (Union[str, uuid.UUID]): ID of the track to add.
        position (int, optional): Target position of the track inside
            the collection.
        meta (Dict[str, Any]): Metadata of the relationship.

    Returns:
        NendoCollection: The collection itself.
    """
    updated_collection = self.nendo_instance.library.add_track_to_collection(
        track_id=track_id,
        collection_id=self.id,
        position=position,
        meta=meta,
    )
    self.related_tracks = updated_collection.related_tracks
    return self

delete ¤

delete(
    remove_relationships: bool = False,
) -> NendoCollection

Deletes the collection from the nendo library.

Parameters:

Name Type Description Default
remove_relationships bool

If False prevent deletion if related tracks exist, if True delete relationships together with the object. Defaults to False.

False

Returns:

Type Description
NendoCollection

The collection itself.

Source code in src/nendo/schema/core.py
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
def delete(
    self,
    remove_relationships: bool = False,
) -> NendoCollection:
    """Deletes the collection from the nendo library.

    Args:
        remove_relationships (bool, optional):
            If False prevent deletion if related tracks exist,
            if True delete relationships together with the object.
            Defaults to False.

    Returns:
        NendoCollection: The collection itself.
    """
    self.nendo_instance.library.remove_collection(
        collection_id=self.id,
        remove_relationships=remove_relationships,
    )
    return self

export ¤

export(
    export_path: str,
    filename_suffix: str = "nendo",
    file_format: str = "wav",
) -> NendoCollection

Export the collection to a directory.

Parameters:

Name Type Description Default
export_path str

Path to a directory into which the collection's tracks should be exported.

required
filename_suffix str

The suffix which should be appended to each exported track's filename.

'nendo'
file_format str

Format of the exported track. Ignored if file_path is a full file path. Defaults to "wav".

'wav'

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265
1266
1267
1268
1269
1270
1271
1272
1273
1274
1275
1276
1277
1278
1279
1280
def export(
    self,
    export_path: str,
    filename_suffix: str = "nendo",
    file_format: str = "wav",
) -> NendoCollection:
    """Export the collection to a directory.

    Args:
        export_path (str): Path to a directory into which the collection's tracks
            should be exported.
        filename_suffix (str): The suffix which should be appended to each
            exported track's filename.
        file_format (str, optional): Format of the exported track. Ignored if
            file_path is a full file path. Defaults to "wav".

    Returns:
        NendoTrack: The track itself.
    """
    self.nendo_instance.library.export_collection(
        collection_id=self.id,
        export_path=export_path,
        filename_suffix=filename_suffix,
        file_format=file_format,
    )
    return self

get_meta ¤

get_meta(key: str) -> Dict[str, Any]

Get the meta entry for the given key.

Parameters:

Name Type Description Default
key str

The key to get metadata for.

required

Returns:

Type Description
Dict[str, Any]

Meta entry for given key.

Source code in src/nendo/schema/core.py
1225
1226
1227
1228
1229
1230
1231
1232
1233
1234
1235
1236
1237
def get_meta(self, key: str) -> Dict[str, Any]:
    """Get the meta entry for the given key.

    Args:
        key (str): The key to get metadata for.

    Returns:
        Dict[str, Any]: Meta entry for given key.
    """
    if not self.has_meta(key):
        logger.warning("Key not found in meta: %s", key)
        return None
    return self.meta[key]
get_related_collections(
    direction: str = "to",
    user_id: Optional[Union[str, UUID]] = None,
    order_by: Optional[str] = None,
    order: Optional[str] = "asc",
    limit: Optional[int] = None,
    offset: Optional[int] = None,
) -> List[NendoCollection]

Get all collections to which the current collection has a relationship.

Parameters:

Name Type Description Default
direction str

The relationship direction. Can be either one of "to", "from", or "both". Defaults to "to".

'to'
user_id Union[str, UUID]

The user ID to filter for.

None
order_by Optional[str]

Key used for ordering the results.

None
order Optional[str]

Order in which to retrieve results ("asc" or "desc").

'asc'
limit Optional[int]

Limit the number of returned results.

None
offset Optional[int]

Offset into the paginated results (requires limit).

None

Returns:

Type Description
List[NendoCollection]

List containting all related NendoCollections

Source code in src/nendo/schema/core.py
1180
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205
1206
1207
1208
1209
1210
1211
1212
def get_related_collections(
    self,
    direction: str = "to",
    user_id: Optional[Union[str, uuid.UUID]] = None,
    order_by: Optional[str] = None,
    order: Optional[str] = "asc",
    limit: Optional[int] = None,
    offset: Optional[int] = None,
) -> List[NendoCollection]:
    """Get all collections to which the current collection has a relationship.

    Args:
        direction (str, optional): The relationship direction.
            Can be either one of "to", "from", or "both".
            Defaults to "to".
        user_id (Union[str, UUID], optional): The user ID to filter for.
        order_by (Optional[str]): Key used for ordering the results.
        order (Optional[str]): Order in which to retrieve results ("asc" or "desc").
        limit (Optional[int]): Limit the number of returned results.
        offset (Optional[int]): Offset into the paginated results (requires limit).

    Returns:
        List[NendoCollection]: List containting all related NendoCollections
    """
    return self.nendo_instance.library.get_related_collections(
        collection_id=self.id,
        direction=direction,
        user_id=user_id,
        order_by=order_by,
        order=order,
        limit=limit,
        offset=offset,
    )

has_meta ¤

has_meta(key: str) -> bool

Check if a given collection has the given key in its meta dict.

Parameters:

Name Type Description Default
key str

The key to check for.

required

Returns:

Type Description
bool

True if the key exists, False otherwise.

Source code in src/nendo/schema/core.py
1214
1215
1216
1217
1218
1219
1220
1221
1222
1223
def has_meta(self, key: str) -> bool:
    """Check if a given collection has the given key in its meta dict.

    Args:
        key (str): The key to check for.

    Returns:
        bool: True if the key exists, False otherwise.
    """
    return any(k == key for k in self.meta)
has_related_collection(
    collection_id: Union[str, UUID]
) -> bool

Check if the collection has a relationship to the specified collection ID.

Parameters:

Name Type Description Default
collection_id Union[str, UUID]

The target collection ID for which to check if it is related to the current collection.

required

Returns:

Type Description
bool

True if the collection has a relationship either from or to the collection with the given collection_id. False otherwise.

Source code in src/nendo/schema/core.py
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
def has_related_collection(
    self,
    collection_id: Union[str, uuid.UUID],
) -> bool:
    """Check if the collection has a relationship to the specified collection ID.

    Args:
        collection_id (Union[str, uuid.UUID]): The target collection ID for which
            to check if it is related to the current collection.

    Returns:
        bool: True if the collection has a relationship either from or to the
            collection with the given `collection_id`. False otherwise.
    """
    collection_id = ensure_uuid(collection_id)
    related_collections = self.get_related_collections(
        direction="both",
    )
    return any(rt.id == collection_id for rt in related_collections)

has_relationship ¤

has_relationship(
    relationship_type: str = "relationship",
) -> bool

Check if the collection has the specified relationship type.

Parameters:

Name Type Description Default
relationship_type str

Type of the relationship to check for. Defaults to "relationship".

'relationship'

Returns:

Type Description
bool

True if a relationship of the given type exists, False otherwise.

Source code in src/nendo/schema/core.py
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
def has_relationship(self, relationship_type: str = "relationship") -> bool:
    """Check if the collection has the specified relationship type.

    Args:
        relationship_type (str): Type of the relationship to check for.
            Defaults to "relationship".

    Returns:
        bool: True if a relationship of the given type exists, False otherwise.
    """
    if self.related_collections is None:
        return False

    return any(
        r.relationship_type == relationship_type for r in self.related_collections
    )

process ¤

process(plugin: str, **kwargs: Any) -> NendoCollection

Process the collection with the specified plugin.

Parameters:

Name Type Description Default
plugin str

Name of the plugin to run on the collection.

required

Returns:

Type Description
NendoCollection

The collection that was created by the plugin.

Source code in src/nendo/schema/core.py
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
def process(self, plugin: str, **kwargs: Any) -> NendoCollection:
    """Process the collection with the specified plugin.

    Args:
        plugin (str): Name of the plugin to run on the collection.

    Returns:
        NendoCollection: The collection that was created by the plugin.
    """
    registered_plugin: RegisteredNendoPlugin = getattr(
        self.nendo_instance.plugins,
        plugin,
    )
    wrapped_method = get_wrapped_methods(registered_plugin.plugin_instance)

    if len(wrapped_method) > 1:
        raise NendoError(
            "Plugin has more than one wrapped method. Please use `nd.plugins.<plugin_name>.<method_name>` instead.",
        )
    return getattr(self.nendo_instance.plugins, plugin)(collection=self, **kwargs)

refresh ¤

refresh() -> NendoCollection

Refreshes the collection with the latest values from the library.

Returns:

Type Description
NendoCollection

The collection itself.

Source code in src/nendo/schema/core.py
 994
 995
 996
 997
 998
 999
1000
1001
1002
1003
def refresh(self) -> NendoCollection:
    """Refreshes the collection with the latest values from the library.

    Returns:
        NendoCollection: The collection itself.
    """
    refreshed_collection = self.nendo_instance.library.get_collection(self.id)
    for attr in vars(refreshed_collection):
        setattr(self, attr, getattr(refreshed_collection, attr))
    return self

remove_meta ¤

remove_meta(key: str) -> NendoCollection

Remove the meta entry for the given key.

Parameters:

Name Type Description Default
key str

The key to remove metadata for.

required

Returns:

Type Description
NendoCollection

The track itself.

Source code in src/nendo/schema/core.py
1239
1240
1241
1242
1243
1244
1245
1246
1247
1248
1249
1250
1251
1252
1253
def remove_meta(self, key: str) -> NendoCollection:
    """Remove the meta entry for the given key.

    Args:
        key (str): The key to remove metadata for.

    Returns:
        NendoCollection: The track itself.
    """
    if not self.has_meta(key):
        logger.error("Key not found in meta: %s", key)
        return None
    _ = self.meta.pop(key, None)
    self.nendo_instance.library.update_collection(collection=self)
    return self

remove_track ¤

remove_track(track_id: Union[str, UUID]) -> NendoCollection

Removes the track from the collection.

Parameters:

Name Type Description Default
track_id Union[str, UUID]

ID of the track to remove from the collection.

required

Returns:

Type Description
NendoCollection

The collection itself.

Source code in src/nendo/schema/core.py
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123
1124
1125
1126
1127
1128
def remove_track(
    self,
    track_id: Union[str, uuid.UUID],
) -> NendoCollection:
    """Removes the track from the collection.

    Args:
        track_id (Union[str, uuid.UUID]): ID of the track to remove
            from the collection.

    Returns:
        NendoCollection: The collection itself.
    """
    self.nendo_instance.library.remove_track_from_collection(
        track_id=track_id,
        collection_id=self.id,
    )
    self.refresh()
    return self

save ¤

save() -> NendoCollection

Save the collection to the nendo library.

Returns:

Type Description
NendoCollection

The collection itself.

Source code in src/nendo/schema/core.py
985
986
987
988
989
990
991
992
def save(self) -> NendoCollection:
    """Save the collection to the nendo library.

    Returns:
        NendoCollection: The collection itself.
    """
    self.nendo_instance.library.update_collection(collection=self)
    return self

set_meta ¤

set_meta(meta: Dict[str, Any]) -> NendoCollection

Set metadata of collection.

Parameters:

Name Type Description Default
meta Dict[str, Any]

Dictionary containing the metadata to be set.

required

Returns:

Type Description
NendoCollection

The collection itself.

Source code in src/nendo/schema/core.py
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
def set_meta(self, meta: Dict[str, Any]) -> NendoCollection:
    """Set metadata of collection.

    Args:
        meta (Dict[str, Any]): Dictionary containing the metadata to be set.

    Returns:
        NendoCollection: The collection itself.
    """
    try:
        self.meta.update(meta)
        self.nendo_instance.library.update_collection(collection=self)
    except NendoError as e:
        logger.exception("Error updating meta: %s", e)
    return self

tracks ¤

tracks() -> List[NendoTrack]

Return all tracks listed in the collection.

Collection will be loaded from the DB if not already loaded.

Returns:

Type Description
List[NendoTrack]

List of tracks.

Source code in src/nendo/schema/core.py
971
972
973
974
975
976
977
978
979
980
981
982
983
def tracks(self) -> List[NendoTrack]:
    """Return all tracks listed in the collection.

    Collection will be loaded from the DB if not already loaded.

    Returns:
        List[NendoTrack]: List of tracks.
    """
    ts = self.__dict__.get("loaded_tracks")
    if ts is None:
        ts = self.nendo_instance.library.get_collection_tracks(self.id)
        self.__dict__["loaded_tracks"] = ts
    return ts

NendoCollectionCollectionRelationship ¤

Bases: NendoRelationship

Class representing a relationship between two NendoCollections.

NendoEmbedding ¤

Bases: NendoEmbeddingBase

Class representing an embedding of a NendoTrack into a vector space.

NendoPlugin ¤

Bases: BaseModel, ABC

Base class for all nendo plugins.

plugin_type property ¤

plugin_type: str

Return type of plugin.

batch_process staticmethod ¤

batch_process(func)

Decorator to run functions multithreaded in batches.

This decorator function transforms the given function to run in multiple threads. It expects that the first argument to the function is a list of items, which will be processed in parallel, in batches of a given size.

Source code in src/nendo/schema/core.py
1324
1325
1326
1327
1328
1329
1330
1331
1332
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343
1344
1345
1346
1347
1348
1349
1350
1351
1352
1353
1354
1355
1356
1357
1358
1359
1360
1361
1362
1363
1364
1365
1366
1367
1368
1369
1370
1371
1372
1373
1374
1375
1376
1377
1378
1379
1380
1381
1382
1383
1384
1385
1386
1387
1388
1389
1390
1391
1392
1393
1394
1395
1396
1397
1398
1399
1400
1401
1402
1403
1404
1405
1406
1407
1408
1409
1410
1411
1412
1413
@staticmethod
def batch_process(func):
    """Decorator to run functions multithreaded in batches.

    This decorator function transforms the given function to run
    in multiple threads. It expects that the first argument to the function
    is a list of items, which will be processed in parallel,
    in batches of a given size.
    """

    @functools.wraps(func)
    def wrapper(self, track=None, file_paths=None, *args, **kwargs):
        target = track or file_paths
        if isinstance(target, NendoTrack):
            return func(self, track=target, **kwargs)
        elif isinstance(target, list):  # noqa: RET505
            max_threads = self.config.max_threads
            batch_size = self.config.batch_size
            total = len(target)
            batches = [
                target[i : i + batch_size] for i in range(0, total, batch_size)
            ]
            start_time = time.time()
            futures = []

            def run_batch(batch_index, batch):
                try:
                    batch_start_time = time.time()
                    results = []
                    if track:
                        for _, item in enumerate(batch):
                            result = func(
                                self,
                                track=item,
                                *args,  # noqa: B026
                                **kwargs,
                            )
                            results.extend(result)
                    elif file_paths:
                        result = func(
                            self,
                            file_paths=batch,
                            *args,  # noqa: B026
                            **kwargs,
                        )
                        results.extend(result)
                    batch_end_time = time.time()
                    batch_time = time.strftime(
                        "%H:%M:%S",
                        time.gmtime(batch_end_time - batch_start_time),
                    )
                    total_elapsed_time = batch_end_time - start_time
                    average_time_per_batch = total_elapsed_time / (batch_index + 1)
                    estimated_total_time = average_time_per_batch * len(batches)
                    estimated_total_time_print = time.strftime(
                        "%H:%M:%S",
                        time.gmtime(estimated_total_time),
                    )
                    remaining_time = time.strftime(
                        "%H:%M:%S",
                        time.gmtime(estimated_total_time - total_elapsed_time),
                    )
                    logger.info(
                        f"Finished batch {batch_index + 1}/{len(batches)}.\n"
                        f"Time taken for this batch: {batch_time} - "
                        f"Estimated total time: {estimated_total_time_print} - "
                        f"Estimated remaining time: {remaining_time}\n",
                    )
                    return results
                except NendoError as e:
                    logger.exception(
                        "Error processing batch %d: %s",
                        batch_index,
                        e,
                    )

            with ThreadPoolExecutor(max_workers=max_threads) as executor:
                for batch_index, batch in enumerate(batches):
                    futures.append(executor.submit(run_batch, batch_index, batch))

            all_results = []
            for future in as_completed(futures):
                result = future.result()
                if result:
                    all_results.extend(future.result())
            return all_results
        else:
            raise TypeError("Expected NendoTrack or list of NendoTracks")

    return wrapper

stream_output staticmethod ¤

stream_output(func)

Decorator to turn on streaming mode for functions.

The requirement for this decorator to work on a function is that it would normally return a list.

Source code in src/nendo/schema/core.py
1303
1304
1305
1306
1307
1308
1309
1310
1311
1312
1313
1314
1315
1316
1317
1318
1319
1320
1321
1322
@staticmethod
def stream_output(func):
    """Decorator to turn on streaming mode for functions.

    The requirement for this decorator to work on a function is that it would
    normally return a list.
    """

    @functools.wraps(func)
    def wrapper(self, *args, **kwargs):
        result = func(self, *args, **kwargs)
        if self.config.stream_mode:
            return result
        # function is yielding single tracks if stream_chunk_size == 1
        elif self.config.stream_chunk_size > 1:  # noqa: RET505
            return [track for chunk in result for track in chunk]
        else:
            return list(result)

    return wrapper

NendoPluginData ¤

Bases: NendoPluginDataBase

Class representing basic plugin data attached to a track.

NendoPluginRegistry ¤

Class for registering and managing of nendo plugins.

add ¤

add(
    plugin_name: str,
    version: str,
    plugin_instance: NendoPlugin,
) -> RegisteredNendoPlugin

Add a Registered plugin to the plugin registry.

Parameters:

Name Type Description Default
plugin_name str

Name of the plugin.

required
version str

Version of the plugin.

required
plugin_instance NendoPlugin

Instantiated plugin class.

required

Returns:

Type Description
RegisteredNendoPlugin

The registered nendo plugin.

Source code in src/nendo/schema/core.py
1933
1934
1935
1936
1937
1938
1939
1940
1941
1942
1943
1944
1945
1946
1947
1948
1949
1950
1951
1952
1953
def add(
    self,
    plugin_name: str,
    version: str,
    plugin_instance: NendoPlugin,
) -> RegisteredNendoPlugin:
    """Add a Registered plugin to the plugin registry.

    Args:
        plugin_name (str): Name of the plugin.
        version (str): Version of the plugin.
        plugin_instance (schema.NendoPlugin): Instantiated plugin class.

    Returns:
        RegisteredNendoPlugin: The registered nendo plugin.
    """
    self._plugins[plugin_name] = RegisteredNendoPlugin(
        name=plugin_name,
        version=version,
        plugin_instance=plugin_instance,
    )

all_names ¤

all_names() -> List[str]

Return all plugins that are registered as a list of their names.

Returns:

Type Description
List[str]

List containing all plugin names.

Source code in src/nendo/schema/core.py
1925
1926
1927
1928
1929
1930
1931
def all_names(self) -> List[str]:
    """Return all plugins that are registered as a list of their names.

    Returns:
        List[str]: List containing all plugin names.
    """
    return [k for k, v in self._plugins.items()]

remove ¤

remove(plugin_name: str) -> None

Remove a plugin from the plugin registry.

Parameters:

Name Type Description Default
plugin_name str

Name of the plugin to remove.

required
Source code in src/nendo/schema/core.py
1955
1956
1957
1958
1959
1960
1961
def remove(self, plugin_name: str) -> None:
    """Remove a plugin from the plugin registry.

    Args:
        plugin_name (str): Name of the plugin to remove.
    """
    del self._plugins[plugin_name]

NendoRelationship ¤

Bases: NendoRelationshipBase

Base class for Nendo Core relationships.

All relationship classes representing relationships between specific types of Nendo Core objects inherit from this class.

NendoRelationshipBase ¤

Bases: BaseModel, ABC

Base class representing a relationship between two Nendo Core objects.

NendoResource ¤

Bases: BaseModel, ABC

Basic class representing a resource in Nendo.

For example, every NendoTrack has at least one associated NendoResource, namely the file containing its waveform. But it can also have other associated resources in the form of images, etc.

NendoStorage ¤

Bases: BaseModel, ABC

Basic class representing a Nendo storage driver.

as_local abstractmethod ¤

as_local(
    file_path: str, location: ResourceLocation, user_id: str
) -> str

Get a local handle to the file.

Return a file given as file_path as a locally accessible file, even if it originally resides in a remote storage location

Parameters:

Name Type Description Default
file_path str

Name of the file to obtain a local copy of.

required
location ResourceLocation

Location of the file, as provided by the corresponding NendoResource.

required
user_id str

User ID

required

Returns:

Type Description
str

Local path to the original file (if it was local) or to a temporary copy (if it was remote)

Source code in src/nendo/schema/core.py
1578
1579
1580
1581
1582
1583
1584
1585
1586
1587
1588
1589
1590
1591
1592
1593
1594
1595
@abstractmethod
def as_local(self, file_path: str, location: ResourceLocation, user_id: str) -> str:
    """Get a local handle to the file.

    Return a file given as `file_path` as a locally accessible file,
    even if it originally resides in a remote storage location

    Args:
        file_path (str): Name of the file to obtain a local copy of.
        location (ResourceLocation): Location of the file, as provided by the
            corresponding NendoResource.
        user_id (str): User ID

    Returns:
        str: Local path to the original file (if it was local) or to a
            temporary copy (if it was remote)
    """
    raise NotImplementedError

file_exists abstractmethod ¤

file_exists(file_name: str, user_id: str) -> bool

Check if the given file_name exists in the storage.

Parameters:

Name Type Description Default
file_name str

Name of the file for which to check existence

required
user_id str

User ID

required

Returns:

Type Description
bool

True if it exists, false otherwise

Source code in src/nendo/schema/core.py
1565
1566
1567
1568
1569
1570
1571
1572
1573
1574
1575
1576
@abstractmethod
def file_exists(self, file_name: str, user_id: str) -> bool:
    """Check if the given file_name exists in the storage.

    Args:
        file_name (str): Name of the file for which to check existence
        user_id (str): User ID

    Returns:
        bool: True if it exists, false otherwise
    """
    raise NotImplementedError

generate_filename abstractmethod ¤

generate_filename(filetype: str, user_id: str) -> str

Generate a collision-free new filename.

Parameters:

Name Type Description Default
filetype str

The filetype to append (without the dot).

required
user_id str

The ID of the user requesting the file.

required

Returns:

Type Description
str

The generated filename.

Source code in src/nendo/schema/core.py
1552
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563
@abstractmethod
def generate_filename(self, filetype: str, user_id: str) -> str:
    """Generate a collision-free new filename.

    Args:
        filetype (str): The filetype to append (without the dot).
        user_id (str): The ID of the user requesting the file.

    Returns:
        str: The generated filename.
    """
    raise NotImplementedError

get_bytes abstractmethod ¤

get_bytes(file_name: str, user_id: str) -> Any

Load the data bytes from the storage.

Loading includes unpickling the file given as file_name.

Parameters:

Name Type Description Default
file_name str

Name of the target file to load.

required
user_id str

The ID of the user writing the file.

required

Returns:

Type Description
Any

The deserialized data bytes

Source code in src/nendo/schema/core.py
1710
1711
1712
1713
1714
1715
1716
1717
1718
1719
1720
1721
1722
1723
@abstractmethod
def get_bytes(self, file_name: str, user_id: str) -> Any:
    """Load the data bytes from the storage.

    Loading includes unpickling the file given as `file_name`.

    Args:
        file_name (str): Name of the target file to load.
        user_id (str): The ID of the user writing the file.

    Returns:
        The deserialized data bytes
    """
    raise NotImplementedError

get_checksum abstractmethod ¤

get_checksum(file_name: str, user_id: str) -> str

Compute the checksum for the given file and user_id.

Parameters:

Name Type Description Default
file_name str

The name of the file in the library for which to compute the checksum.

required
user_id str

The ID of the user requesting the checksum.

required

Returns:

Type Description
str

The checksum of the target file.

Source code in src/nendo/schema/core.py
1725
1726
1727
1728
1729
1730
1731
1732
1733
1734
1735
1736
1737
@abstractmethod
def get_checksum(self, file_name: str, user_id: str) -> str:
    """Compute the checksum for the given file and user_id.

    Args:
        file_name (str): The name of the file in the library for which
            to compute the checksum.
        user_id (str): The ID of the user requesting the checksum.

    Returns:
        str: The checksum of the target file.
    """
    raise NotImplementedError

get_driver_location abstractmethod ¤

get_driver_location() -> str

Get the default resource location of the storage driver.

e.g. "original", "local", "gcs", "s3", etc.

Returns:

Type Description
str

Location type.

Source code in src/nendo/schema/core.py
1739
1740
1741
1742
1743
1744
1745
1746
1747
@abstractmethod
def get_driver_location(self) -> str:
    """Get the default resource location of the storage driver.

    e.g. "original", "local", "gcs", "s3", etc.

    Returns:
        str: Location type.
    """

get_file abstractmethod ¤

get_file(file_name: str, user_id: str) -> str

Obtains the full path to the file by the name of file_name from storage.

Parameters:

Name Type Description Default
file_name str

The name of the target file.

required
user_id str

The ID of the user requesting the file.

required

Returns:

Type Description
str

The full path to the file.

Source code in src/nendo/schema/core.py
1685
1686
1687
1688
1689
1690
1691
1692
1693
1694
1695
1696
@abstractmethod
def get_file(self, file_name: str, user_id: str) -> str:
    """Obtains the full path to the file by the name of file_name from storage.

    Args:
        file_name (str): The name of the target file.
        user_id (str): The ID of the user requesting the file.

    Returns:
        str: The full path to the file.
    """
    raise NotImplementedError

get_file_name abstractmethod ¤

get_file_name(src: str, user_id: str) -> str

Returns the filename of a resource.

Parameters:

Name Type Description Default
src str

The full path to the resource.

required
user_id str

The ID of the user requesting the path.

required

Returns:

Type Description
str

The resource file name, minus the path.

Source code in src/nendo/schema/core.py
1672
1673
1674
1675
1676
1677
1678
1679
1680
1681
1682
1683
@abstractmethod
def get_file_name(self, src: str, user_id: str) -> str:
    """Returns the filename of a resource.

    Args:
        src (str): The full path to the resource.
        user_id (str): The ID of the user requesting the path.

    Returns:
        str: The resource file name, minus the path.
    """
    raise NotImplementedError

get_file_path abstractmethod ¤

get_file_path(src: str, user_id: str) -> str

Returns the path of a resource.

Parameters:

Name Type Description Default
src str

The full path to the resource.

required
user_id str

The ID of the user requesting the path.

required

Returns:

Type Description
str

The resource path, minus the file name.

Source code in src/nendo/schema/core.py
1659
1660
1661
1662
1663
1664
1665
1666
1667
1668
1669
1670
@abstractmethod
def get_file_path(self, src: str, user_id: str) -> str:
    """Returns the path of a resource.

    Args:
        src (str): The full path to the resource.
        user_id (str): The ID of the user requesting the path.

    Returns:
        str: The resource path, minus the file name.
    """
    raise NotImplementedError

init_storage_for_user abstractmethod ¤

init_storage_for_user(user_id: str) -> Any

Initializes the storage location for the given user.

Parameters:

Name Type Description Default
user_id str

ID of the user for whom the storage is to be initialized.

required

Returns:

Type Description
Any

Storage object

Source code in src/nendo/schema/core.py
1540
1541
1542
1543
1544
1545
1546
1547
1548
1549
1550
@abstractmethod
def init_storage_for_user(self, user_id: str) -> Any:
    """Initializes the storage location for the given user.

    Args:
        user_id (str): ID of the user for whom the storage is to be initialized.

    Returns:
        Any: Storage object
    """
    raise NotImplementedError

list_files abstractmethod ¤

list_files(user_id: str) -> List[str]

Lists all files found in the user's library.

Parameters:

Name Type Description Default
user_id str

The ID of the user.

required

Returns:

Type Description
List[str]

List of paths to files.

Source code in src/nendo/schema/core.py
1698
1699
1700
1701
1702
1703
1704
1705
1706
1707
1708
@abstractmethod
def list_files(self, user_id: str) -> List[str]:
    """Lists all files found in the user's library.

    Args:
        user_id (str): The ID of the user.

    Returns:
        List[str]: List of paths to files.
    """
    raise NotImplementedError

remove_file abstractmethod ¤

remove_file(file_name: str, user_id: str) -> bool

Remove the file given by file_name and user_id from the storage.

Parameters:

Name Type Description Default
file_name str

Name of the file to remove.

required
user_id str

ID of the user requesting the removal.

required

Returns:

Type Description
bool

True if deletion was successful, False otherwise.

Source code in src/nendo/schema/core.py
1646
1647
1648
1649
1650
1651
1652
1653
1654
1655
1656
1657
@abstractmethod
def remove_file(self, file_name: str, user_id: str) -> bool:
    """Remove the file given by file_name and user_id from the storage.

    Args:
        file_name (str): Name of the file to remove.
        user_id (str): ID of the user requesting the removal.

    Returns:
        bool: True if deletion was successful, False otherwise.
    """
    raise NotImplementedError

save_bytes abstractmethod ¤

save_bytes(
    file_name: str, data: bytes, user_id: str
) -> str

Save a data given as bytes to the FS by pickling them first.

Parameters:

Name Type Description Default
file_name str

Name of the target file to save the data to.

required
data ndarray

The data to write to file in pickled form.

required
user_id str

The ID of the user writing the file.

required

Returns:

Type Description
str

The full path to the saved file resource.

Source code in src/nendo/schema/core.py
1632
1633
1634
1635
1636
1637
1638
1639
1640
1641
1642
1643
1644
@abstractmethod
def save_bytes(self, file_name: str, data: bytes, user_id: str) -> str:
    """Save a data given as bytes to the FS by pickling them first.

    Args:
        file_name (str): Name of the target file to save the data to.
        data (np.ndarray): The data to write to file in pickled form.
        user_id (str): The ID of the user writing the file.

    Returns:
        str: The full path to the saved file resource.
    """
    raise NotImplementedError

save_file abstractmethod ¤

save_file(
    file_name: str, file_path: str, user_id: str
) -> str

Saves the file with the given file_name to the path specified by file_path.

Parameters:

Name Type Description Default
file_name str

The name of the target file.

required
file_path str

The path to the target file.

required
user_id str

The ID of the user requesting the file.

required

Returns:

Type Description
str

The full path to the saved file resource.

Source code in src/nendo/schema/core.py
1597
1598
1599
1600
1601
1602
1603
1604
1605
1606
1607
1608
1609
@abstractmethod
def save_file(self, file_name: str, file_path: str, user_id: str) -> str:
    """Saves the file with the given file_name to the path specified by file_path.

    Args:
        file_name (str): The name of the target file.
        file_path (str): The path to the target file.
        user_id (str): The ID of the user requesting the file.

    Returns:
        str: The full path to the saved file resource.
    """
    raise NotImplementedError

save_signal abstractmethod ¤

save_signal(
    file_name: str, signal: ndarray, sr: int, user_id: str
) -> str

Save a signal given as a numpy array to storage.

Parameters:

Name Type Description Default
file_name str

Name of the target file to save the signal to.

required
signal ndarray

The signal to write as a numpy array.

required
sr int

The sample rate of the signal.

required
user_id str

The ID of the user writing the file.

required

Returns:

Type Description
str

The full path to the saved file resource.

Source code in src/nendo/schema/core.py
1611
1612
1613
1614
1615
1616
1617
1618
1619
1620
1621
1622
1623
1624
1625
1626
1627
1628
1629
1630
@abstractmethod
def save_signal(
    self,
    file_name: str,
    signal: np.ndarray,
    sr: int,
    user_id: str,
) -> str:
    """Save a signal given as a numpy array to storage.

    Args:
        file_name (str): Name of the target file to save the signal to.
        signal (np.ndarray): The signal to write as a numpy array.
        sr (int): The sample rate of the signal.
        user_id (str): The ID of the user writing the file.

    Returns:
        str: The full path to the saved file resource.
    """
    raise NotImplementedError

NendoStorageLocalFS ¤

NendoStorageLocalFS(
    library_path: str, user_id: str, **kwargs: Any
)

Bases: NendoStorage

Implementation of the base storage driver for local filesystem access.

Source code in src/nendo/schema/core.py
1755
1756
1757
1758
1759
1760
1761
1762
1763
def __init__(  # noqa: D107
    self,
    library_path: str,
    user_id: str,
    **kwargs: Any,
):
    super().__init__(**kwargs)
    self.library_path = library_path
    self.init_storage_for_user(user_id=user_id)

as_local ¤

as_local(
    file_path: str, location: ResourceLocation, user_id: str
) -> str

Get a local handle to the file.

Source code in src/nendo/schema/core.py
1783
1784
1785
1786
1787
def as_local(self, file_path: str, location: ResourceLocation, user_id: str) -> str:
    """Get a local handle to the file."""
    if location == self.get_driver_location():
        return self.get_file(os.path.basename(file_path), user_id)
    return file_path

file_exists ¤

file_exists(file_name: str, user_id: str) -> bool

Check if the given file exists.

Source code in src/nendo/schema/core.py
1779
1780
1781
def file_exists(self, file_name: str, user_id: str) -> bool:
    """Check if the given file exists."""
    return os.path.isfile(self.get_file(file_name, user_id))

generate_filename ¤

generate_filename(filetype: str, user_id: str) -> str

Generate a unique filename.

Source code in src/nendo/schema/core.py
1775
1776
1777
def generate_filename(self, filetype: str, user_id: str) -> str:  # noqa: ARG002
    """Generate a unique filename."""
    return f"{uuid.uuid4()!s}.{filetype}"

get_bytes ¤

get_bytes(file_name: str, user_id: str) -> Any

Get bytes from a stored file by unpickling it.

Source code in src/nendo/schema/core.py
1846
1847
1848
1849
1850
def get_bytes(self, file_name: str, user_id: str) -> Any:
    """Get bytes from a stored file by unpickling it."""
    target_file_path = self.get_file(file_name=file_name, user_id=user_id)
    with open(target_file_path, "rb") as target_file:
        return pickle.loads(target_file.read())  # noqa: S301

get_checksum ¤

get_checksum(file_name: str, user_id: str) -> str

Compute the MD5 checksum of the given file.

Source code in src/nendo/schema/core.py
1852
1853
1854
def get_checksum(self, file_name: str, user_id: str) -> str:
    """Compute the MD5 checksum of the given file."""
    return md5sum(self.get_file(file_name=file_name, user_id=user_id))

get_driver_location ¤

get_driver_location() -> ResourceLocation

Get the default resource location of the storage driver.

Source code in src/nendo/schema/core.py
1856
1857
1858
def get_driver_location(self) -> ResourceLocation:
    """Get the default resource location of the storage driver."""
    return ResourceLocation.local

get_file ¤

get_file(file_name: str, user_id: str) -> str

Get the full path to the file.

Source code in src/nendo/schema/core.py
1837
1838
1839
def get_file(self, file_name: str, user_id: str) -> str:
    """Get the full path to the file."""
    return os.path.join(self.library_path, user_id, file_name)

get_file_name ¤

get_file_name(src: str, user_id: str) -> str

Get the file name (without the path).

Source code in src/nendo/schema/core.py
1833
1834
1835
def get_file_name(self, src: str, user_id: str) -> str:  # noqa: ARG002
    """Get the file name (without the path)."""
    return os.path.basename(src)

get_file_path ¤

get_file_path(src: str, user_id: str) -> str

Get the path to the file (without the file name).

Source code in src/nendo/schema/core.py
1829
1830
1831
def get_file_path(self, src: str, user_id: str) -> str:  # noqa: ARG002
    """Get the path to the file (without the file name)."""
    return os.path.dirname(src)

init_storage_for_user ¤

init_storage_for_user(user_id: str) -> str

Initialize local storage for user.

Source code in src/nendo/schema/core.py
1765
1766
1767
1768
1769
1770
1771
1772
1773
def init_storage_for_user(self, user_id: str) -> str:
    """Initialize local storage for user."""
    user_lib_path = os.path.join(self.library_path, user_id)
    if not os.path.isdir(user_lib_path):
        logger.info(
            f"Library path {user_lib_path} does not exist, creating now.",
        )
        os.makedirs(user_lib_path)
    return user_lib_path

list_files ¤

list_files(user_id: str) -> List[str]

List all files contained in the storage.

Source code in src/nendo/schema/core.py
1841
1842
1843
1844
def list_files(self, user_id: str) -> List[str]:
    """List all files contained in the storage."""
    with os.scandir(os.path.join(self.library_path, user_id)) as entries:
        return [entry.name for entry in entries if entry.is_file()]

remove_file ¤

remove_file(file_name: str, user_id: str) -> bool

Remove the given file.

Source code in src/nendo/schema/core.py
1819
1820
1821
1822
1823
1824
1825
1826
1827
def remove_file(self, file_name: str, user_id: str) -> bool:
    """Remove the given file."""
    target_file = self.get_file(file_name=file_name, user_id=user_id)
    try:
        os.remove(target_file)
        return True
    except OSError as e:
        logger.error("Removing file %s failed: %s", target_file, e)
        return False

save_bytes ¤

save_bytes(
    file_name: str, data: bytes, user_id: str
) -> str

Save the given bytes to storage.

Source code in src/nendo/schema/core.py
1807
1808
1809
1810
1811
1812
1813
1814
1815
1816
1817
def save_bytes(
    self,
    file_name: str,
    data: bytes,
    user_id: str,
) -> str:
    """Save the given bytes to storage."""
    target_file_path = self.get_file(file_name=file_name, user_id=user_id)
    with open(target_file_path, "wb") as target_file:
        pickle.dump(data, target_file)
    return target_file_path

save_file ¤

save_file(
    file_name: str, file_path: str, user_id: str
) -> str

Copy the source file given by file_path to the library.

Source code in src/nendo/schema/core.py
1789
1790
1791
1792
1793
def save_file(self, file_name: str, file_path: str, user_id: str) -> str:
    """Copy the source file given by file_path to the library."""
    target_file = self.get_file(file_name=file_name, user_id=user_id)
    shutil.copy2(file_path, target_file)
    return target_file

save_signal ¤

save_signal(
    file_name: str, signal: ndarray, sr: int, user_id: str
) -> str

Save the given signal to storage.

Source code in src/nendo/schema/core.py
1795
1796
1797
1798
1799
1800
1801
1802
1803
1804
1805
def save_signal(
    self,
    file_name: str,
    signal: np.ndarray,
    sr: int,
    user_id: str,
) -> str:
    """Save the given signal to storage."""
    target_file_path = self.get_file(file_name=file_name, user_id=user_id)
    sf.write(target_file_path, signal, sr, subtype="PCM_16")
    return target_file_path

NendoTrack ¤

NendoTrack(**kwargs: Any)

Bases: NendoTrackBase

Basic class representing a nendo track.

Source code in src/nendo/schema/core.py
267
268
269
def __init__(self, **kwargs: Any) -> None:  # noqa: D107
    super().__init__(**kwargs)
    self.nendo_instance = Nendo()

signal property ¤

signal: ndarray

Lazy-load the signal from the track using librosa.

Returns:

Type Description
ndarray

The signal of the track.

sr property ¤

sr: int

Lazy-load the sample rate of the track.

Returns:

Type Description
int

The sample rate of the track.

add_plugin_data ¤

add_plugin_data(
    key: str,
    value: str,
    plugin_name: str,
    plugin_version: Optional[str] = None,
    user_id: Optional[Union[str, UUID]] = None,
    replace: Optional[bool] = None,
) -> NendoTrack

Add plugin data to a NendoTrack and persist changes into the DB.

Parameters:

Name Type Description Default
key str

Key under which to save the data.

required
value Any

Data to save.

required
plugin_name str

Name of the plugin.

required
plugin_version str

Version of the plugin. If none is given, the currently loaded version of the plugin given by plugin_name will be used.

None
user_id Union[str, UUID]

ID of user adding the plugin data.

None
replace bool

Flag that determines whether the last existing data point for the given plugin name and -version is overwritten or not. If undefined, the nendo configuration's replace_plugin_data value will be used.

None

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
def add_plugin_data(
    self,
    key: str,
    value: str,
    plugin_name: str,
    plugin_version: Optional[str] = None,
    user_id: Optional[Union[str, uuid.UUID]] = None,
    replace: Optional[bool] = None,
) -> NendoTrack:
    """Add plugin data to a NendoTrack and persist changes into the DB.

    Args:
        key (str): Key under which to save the data.
        value (Any): Data to save.
        plugin_name (str): Name of the plugin.
        plugin_version (str): Version of the plugin. If none is given,
            the currently loaded version of the plugin given by `plugin_name`
            will be used.
        user_id (Union[str, UUID], optional): ID of user adding the plugin data.
        replace (bool, optional): Flag that determines whether
            the last existing data point for the given plugin name and -version
            is overwritten or not. If undefined, the nendo configuration's
            `replace_plugin_data` value will be used.

    Returns:
        NendoTrack: The track itself.
    """
    pd = self.nendo_instance.library.add_plugin_data(
        track_id=self.id,
        plugin_name=plugin_name,
        plugin_version=plugin_version,
        key=key,
        value=value,
        user_id=user_id,
        replace=replace,
    )
    self.plugin_data.append(pd)
    return self
add_related_track(
    file_path: FilePath,
    track_type: str = "str",
    user_id: Optional[UUID] = None,
    track_meta: Optional[Dict[str, Any]] = None,
    relationship_type: str = "relationship",
    meta: Optional[Dict[str, Any]] = None,
) -> NendoTrack

Adds a new track with a relationship to the current one.

Parameters:

Name Type Description Default
file_path FilePath

Path to the file to add as track.

required
track_type str

Track type. Defaults to "track".

'str'
user_id Union[str, UUID]

ID of the user adding the track.

None
track_meta dict

Dictionary containing the track metadata.

None
relationship_type str

Type of the relationship. Defaults to "relationship".

'relationship'
meta dict

Dictionary containing metadata about the relationship. Defaults to {}.

None

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
def add_related_track(
    self,
    file_path: FilePath,
    track_type: str = "str",
    user_id: Optional[uuid.UUID] = None,
    track_meta: Optional[Dict[str, Any]] = None,
    relationship_type: str = "relationship",
    meta: Optional[Dict[str, Any]] = None,
) -> NendoTrack:
    """Adds a new track with a relationship to the current one.

    Args:
        file_path (FilePath): Path to the file to add as track.
        track_type (str): Track type. Defaults to "track".
        user_id (Union[str, UUID], optional): ID of the user adding the track.
        track_meta (dict, optional): Dictionary containing the track metadata.
        relationship_type (str): Type of the relationship.
            Defaults to "relationship".
        meta (dict): Dictionary containing metadata about
            the relationship. Defaults to {}.

    Returns:
        NendoTrack: The track itself.
    """
    self.nendo_instance.library.add_related_track(
        file_path=file_path,
        related_track_id=self.id,
        track_type=track_type,
        user_id=user_id,
        track_meta=track_meta,
        relationship_type=relationship_type,
        meta=meta,
    )
    self.refresh()
    return self
add_related_track_from_signal(
    signal: ndarray,
    sr: int,
    track_type: str = "track",
    user_id: Optional[UUID] = None,
    track_meta: Optional[Dict[str, Any]] = None,
    relationship_type: str = "relationship",
    meta: Optional[Dict[str, Any]] = None,
) -> NendoTrack

Adds a new track with a relationship to the current one.

Parameters:

Name Type Description Default
signal ndarray

Waveform of the track in numpy array form.

required
sr int

Sampling rate of the waveform.

required
track_type str

Track type. Defaults to "track".

'track'
user_id UUID

ID of the user adding the track.

None
track_meta (dict

Dictionary containing the track metadata.

None
relationship_type str

Type of the relationship. Defaults to "relationship".

'relationship'
meta dict

Dictionary containing metadata about the relationship. Defaults to {}.

None

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
def add_related_track_from_signal(
    self,
    signal: np.ndarray,
    sr: int,
    track_type: str = "track",
    user_id: Optional[uuid.UUID] = None,
    track_meta: Optional[Dict[str, Any]] = None,
    relationship_type: str = "relationship",
    meta: Optional[Dict[str, Any]] = None,
) -> NendoTrack:
    """Adds a new track with a relationship to the current one.

    Args:
        signal (np.ndarray): Waveform of the track in numpy array form.
        sr (int): Sampling rate of the waveform.
        track_type (str): Track type. Defaults to "track".
        user_id (UUID, optional): ID of the user adding the track.
        track_meta  (dict, optional): Dictionary containing the track metadata.
        relationship_type (str): Type of the relationship.
            Defaults to "relationship".
        meta (dict): Dictionary containing metadata about
            the relationship. Defaults to {}.

    Returns:
        NendoTrack: The track itself.
    """
    self.nendo_instance.library.add_related_track_from_signal(
        signal=signal,
        sr=sr,
        track_type=track_type,
        related_track_id=self.id,
        user_id=user_id,
        track_meta=track_meta,
        relationship_type=relationship_type,
        meta=meta,
    )
    self.refresh()
    return self

add_to_collection ¤

add_to_collection(
    collection_id: Union[str, UUID],
    position: Optional[int] = None,
    meta: Optional[Dict[str, Any]] = None,
) -> NendoTrack

Adds the track to the collection given as collection_id.

Parameters:

Name Type Description Default
collection_id Union[str, UUID]

ID of the collection to which to add the track.

required
position int

Target position of the track inside the collection.

None
meta Dict[str, Any]

Metadata of the relationship.

None

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
def add_to_collection(
    self,
    collection_id: Union[str, uuid.UUID],
    position: Optional[int] = None,
    meta: Optional[Dict[str, Any]] = None,
) -> NendoTrack:
    """Adds the track to the collection given as collection_id.

    Args:
        collection_id (Union[str, uuid.UUID]): ID of the collection to
            which to add the track.
        position (int, optional): Target position of the track inside
            the collection.
        meta (Dict[str, Any]): Metadata of the relationship.

    Returns:
        NendoTrack: The track itself.
    """
    self.nendo_instance.library.add_track_to_collection(
        track_id=self.id,
        collection_id=collection_id,
        position=position,
        meta=meta,
    )
    self.refresh()
    return self

delete ¤

delete(
    remove_relationships: bool = False,
    remove_plugin_data: bool = True,
    remove_resources: bool = True,
    user_id: Optional[Union[str, UUID]] = None,
) -> NendoTrack

Delete the track from the library.

Parameters:

Name Type Description Default
remove_relationships bool

If False prevent deletion if related tracks exist, if True delete relationships together with the object

False
remove_plugin_data bool

If False prevent deletion if related plugin data exist if True delete plugin data together with the object

True
remove_resources bool

If False, keep the related resources, e.g. files if True, delete the related resources

True
user_id Union[str, UUID]

The ID of the user owning the track.

None

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
def delete(
    self,
    remove_relationships: bool = False,
    remove_plugin_data: bool = True,
    remove_resources: bool = True,
    user_id: Optional[Union[str, uuid.UUID]] = None,
) -> NendoTrack:
    """Delete the track from the library.

    Args:
        remove_relationships (bool):
            If False prevent deletion if related tracks exist,
            if True delete relationships together with the object
        remove_plugin_data (bool):
            If False prevent deletion if related plugin data exist
            if True delete plugin data together with the object
        remove_resources (bool):
            If False, keep the related resources, e.g. files
            if True, delete the related resources
        user_id (Union[str, UUID], optional): The ID of the user owning the track.

    Returns:
        NendoTrack: The track itself.
    """
    self.nendo_instance.library.remove_track(
        track_id=self.id,
        remove_relationships=remove_relationships,
        remove_plugin_data=remove_plugin_data,
        remove_resources=remove_resources,
        user_id=user_id,
    )
    return self

export ¤

export(
    file_path: str, file_format: str = "wav"
) -> NendoTrack

Export the track to a file.

Parameters:

Name Type Description Default
file_path str

Path to the exported file. Can be either a full file path or a directory path. If a directory path is given, a filename will be automatically generated and the file will be exported to the format specified as file_format. If a full file path is given, the format will be deduced from the path and the file_format parameter will be ignored.

required
file_format str

Format of the exported track. Ignored if file_path is a full file path. Defaults to "wav".

'wav'

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
def export(self, file_path: str, file_format: str = "wav") -> NendoTrack:
    """Export the track to a file.

    Args:
        file_path (str): Path to the exported file. Can be either a full
            file path or a directory path. If a directory path is given,
            a filename will be automatically generated and the file will be
            exported to the format specified as file_format. If a full file
            path is given, the format will be deduced from the path and the
            file_format parameter will be ignored.
        file_format (str, optional): Format of the exported track. Ignored if
            file_path is a full file path. Defaults to "wav".

    Returns:
        NendoTrack: The track itself.
    """
    self.nendo_instance.library.export_track(
        track_id=self.id,
        file_path=file_path,
        file_format=file_format,
    )
    return self

get_meta ¤

get_meta(key: str) -> Dict[str, Any]

Get the meta entry for the given key.

Parameters:

Name Type Description Default
key str

The key to get metadata for.

required

Returns:

Type Description
Dict[str, Any]

Meta entry for given key.

Source code in src/nendo/schema/core.py
503
504
505
506
507
508
509
510
511
512
513
514
515
def get_meta(self, key: str) -> Dict[str, Any]:
    """Get the meta entry for the given key.

    Args:
        key (str): The key to get metadata for.

    Returns:
        Dict[str, Any]: Meta entry for given key.
    """
    if not self.has_meta(key):
        logger.error("Key not found in meta: %s", key)
        return None
    return self.meta[key]

get_plugin_data ¤

get_plugin_data(
    plugin_name: Optional[str] = None,
    plugin_version: Optional[str] = None,
    key: Optional[str] = None,
    user_id: Optional[Union[str, UUID]] = None,
) -> List[NendoPluginData]

Get all plugin data for a given plugin name, version, key and user_id.

Function behavior
  • If plugin_name, plugin_version and/or key are specified, the plugin data will be filtered w.r.t. them.
  • Certain kinds of plugin data are actually stored as blobs and the corresponding blob id is stored in the plugin data's value field. Those will be automatically loaded from the blob into memory and a NendoBlob object will be returned inside plugin_data.value.

Parameters:

Name Type Description Default
plugin_name str

The name of the plugin with respect to which the data is filtered.

None
plugin_version str

The version of the plugin with respect to which the data is filtered.

None
key str

The key to filter plugin data for.

None
user_id Union[str, UUID]

The user ID to filter the plugin data.

None

Returns:

Type Description
List[NendoPluginData]

List of nendo plugin data entries.

Source code in src/nendo/schema/core.py
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
def get_plugin_data(
    self,
    plugin_name: Optional[str] = None,
    plugin_version: Optional[str] = None,
    key: Optional[str] = None,
    user_id: Optional[Union[str, uuid.UUID]] = None,
) -> List[NendoPluginData]:
    """Get all plugin data for a given plugin name, version, key and user_id.

    Note: Function behavior
        - If plugin_name, plugin_version and/or key are specified, the
            plugin data will be filtered w.r.t. them.
        - Certain kinds of plugin data are actually stored as blobs
            and the corresponding blob id is stored in the plugin data's value
            field. Those will be automatically loaded from the blob into memory
            and a `NendoBlob` object will be returned inside `plugin_data.value`.

    Args:
        plugin_name (str, optional): The name of the plugin with respect to which
            the data is filtered.
        plugin_version (str, optional): The version of the plugin with respect to
            which the data is filtered.
        key (str, optional): The key to filter plugin data for.
        user_id (Union[str, uuid.UUID], optional): The user ID to filter the
            plugin data.

    Returns:
        List[NendoPluginData]: List of nendo plugin data entries.
    """
    uuid_pattern = re.compile(
        r"^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-"
        r"[89ab][0-9a-f]{3}-[0-9a-f]{12}\Z",
        re.I,
    )
    plugin_data = self.nendo_instance.library.get_plugin_data(
        track_id=self.id,
        user_id=user_id,
        plugin_name=plugin_name,
        plugin_version=plugin_version,
        key=key,
    )
    for pd in plugin_data:
        # if we have a UUID, load the corresponding blob
        if uuid_pattern.match(pd.value):
            loaded_blob = self.nendo_instance.library.load_blob(
                blob_id=uuid.UUID(pd.value),
            )
            pd.value = loaded_blob
    return plugin_data

get_plugin_value ¤

get_plugin_value(
    key: str, user_id: Optional[Union[str, UUID]] = None
) -> Optional[str]

Return the value for a specific plugin_data key.

Parameters:

Name Type Description Default
key str

The key for which the plugin data value should be returned.

required
user_id Union[str, UUID]

The user ID to filter the plugin data.

None

Returns:

Type Description
str

The plugin data value belonging to the given key. If multiple plugin_data entries exist for the given key, the first one is returned. If none exist, None is returned.

Source code in src/nendo/schema/core.py
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
def get_plugin_value(
    self,
    key: str,
    user_id: Optional[Union[str, uuid.UUID]] = None,
) -> Optional[str]:
    """Return the value for a specific plugin_data key.

    Args:
        key (str): The key for which the plugin data value should
            be returned.
        user_id (Union[str, uuid.UUID], optional): The user ID to filter the
            plugin data.

    Returns:
        str: The plugin data value belonging to the given key.
            If multiple plugin_data entries exist for the given key,
            the first one is returned. If none exist, None is returned.
    """
    pd = self.get_plugin_data(key=key, user_id=user_id)
    if len(pd) == 0:
        return None
    return pd[0].value
get_related_tracks(
    direction: str = "to",
    user_id: Optional[Union[str, UUID]] = None,
    order_by: Optional[str] = None,
    order: Optional[str] = "asc",
    limit: Optional[int] = None,
    offset: Optional[int] = None,
) -> List[NendoTrack]

Get all tracks to which the current track has a relationship.

Parameters:

Name Type Description Default
direction str

The relationship direction ("to", "from", "all").

'to'
user_id Union[str, UUID]

The user ID to filter for.

None
order_by Optional[str]

Key used for ordering the results.

None
order Optional[str]

Order in which to retrieve results ("asc" or "desc").

'asc'
limit Optional[int]

Limit the number of returned results.

None
offset Optional[int]

Offset into the paginated results (requires limit).

None

Returns:

Type Description
List[NendoTrack]

List containting all related NendoTracks

Source code in src/nendo/schema/core.py
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
def get_related_tracks(
    self,
    direction: str = "to",
    user_id: Optional[Union[str, uuid.UUID]] = None,
    order_by: Optional[str] = None,
    order: Optional[str] = "asc",
    limit: Optional[int] = None,
    offset: Optional[int] = None,
) -> List[NendoTrack]:
    """Get all tracks to which the current track has a relationship.

    Args:
        direction (str, optional): The relationship direction ("to", "from", "all").
        user_id (Union[str, UUID], optional): The user ID to filter for.
        order_by (Optional[str]): Key used for ordering the results.
        order (Optional[str]): Order in which to retrieve results ("asc" or "desc").
        limit (Optional[int]): Limit the number of returned results.
        offset (Optional[int]): Offset into the paginated results (requires limit).

    Returns:
        List[NendoTrack]: List containting all related NendoTracks
    """
    return self.nendo_instance.library.get_related_tracks(
        track_id=self.id,
        direction=direction,
        user_id=user_id,
        order_by=order_by,
        order=order,
        limit=limit,
        offset=offset,
    )

has_meta ¤

has_meta(key: str) -> bool

Check if a given track has the given key in its meta dict.

Parameters:

Name Type Description Default
key str

The key to check for.

required

Returns:

Type Description
bool

True if the key exists, False otherwise.

Source code in src/nendo/schema/core.py
492
493
494
495
496
497
498
499
500
501
def has_meta(self, key: str) -> bool:
    """Check if a given track has the given key in its meta dict.

    Args:
        key (str): The key to check for.

    Returns:
        bool: True if the key exists, False otherwise.
    """
    return any(k == key for k in self.meta)
has_related_track(
    track_id: Union[str, UUID], direction: str = "to"
) -> bool

Check if there is a related track with the given track_id.

Parameters:

Name Type Description Default
track_id Union[str, UUID]

ID of the potential related track.

required
direction str

The relationship direction. Can be either one of "to", "from", or "both". Defaults to "to".

'to'

Returns:

Type Description
bool

True if a related track with the given track_id and direction of relationship exists. False otherwise.

Source code in src/nendo/schema/core.py
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
def has_related_track(
    self,
    track_id: Union[str, uuid.UUID],
    direction: str = "to",
) -> bool:
    """Check if there is a related track with the given track_id.

    Args:
        track_id (Union[str, uuid.UUID]): ID of the potential related track.
        direction (str, optional): The relationship direction.
            Can be either one of "to", "from", or "both".
            Defaults to "to".

    Returns:
        bool: True if a related track with the given track_id and direction
            of relationship exists. False otherwise.
    """
    track_id = ensure_uuid(track_id)
    related_tracks = self.get_related_tracks(
        direction=direction,
    )
    return any(rt.id == track_id for rt in related_tracks)

has_relationship ¤

has_relationship(
    relationship_type: str = "relationship",
) -> bool

Check whether the track has any relationships of the specified type.

Parameters:

Name Type Description Default
relationship_type str

Type of the relationship to check for. Defaults to "relationship".

'relationship'

Returns:

Type Description
bool

True if a relationship of the given type exists, False otherwise.

Source code in src/nendo/schema/core.py
720
721
722
723
724
725
726
727
728
729
730
731
732
733
def has_relationship(self, relationship_type: str = "relationship") -> bool:
    """Check whether the track has any relationships of the specified type.

    Args:
        relationship_type (str): Type of the relationship to check for.
            Defaults to "relationship".

    Returns:
        bool: True if a relationship of the given type exists, False otherwise.
    """
    all_relationships = self.related_tracks + self.related_collections
    if len(all_relationships) == 0:
        return False
    return any(r.relationship_type == relationship_type for r in all_relationships)

local ¤

local(user_id: Optional[Union[str, UUID]] = None) -> str

Get a path to a local file handle on the track.

Source code in src/nendo/schema/core.py
358
359
360
361
362
363
364
365
366
367
368
def local(self, user_id: Optional[Union[str, uuid.UUID]] = None) -> str:
    """Get a path to a local file handle on the track."""
    return self.nendo_instance.library.storage_driver.as_local(
        file_path=self.resource.src,
        location=self.resource.location,
        user_id=(
            str(user_id)
            if user_id is not None
            else str(self.nendo_instance.config.user_id)
        ),
    )

loop ¤

loop()

Loop the track.

Source code in src/nendo/schema/core.py
902
903
904
def loop(self):
    """Loop the track."""
    play_signal(self.signal, self.sr, loop=True)

model_validate classmethod ¤

model_validate(*args, **kwargs)

Inject the nendo instance upon conversion from ORM.

Source code in src/nendo/schema/core.py
344
345
346
347
348
349
@classmethod
def model_validate(cls, *args, **kwargs):
    """Inject the nendo instance upon conversion from ORM."""
    instance = super().model_validate(*args, **kwargs)
    instance.nendo_instance = Nendo()
    return instance

overlay ¤

overlay(
    track: NendoTrack, gain_db: Optional[float] = 0
) -> NendoTrack

Overlay two tracks using gain control in decibels.

The gain gets applied to the second track. This function creates a new related track in the library.

Parameters:

Name Type Description Default
track NendoTrack

The track to overlay with.

required
gain_db Optional[float]

The gain to apply to the second track. Defaults to 0.

0

Returns:

Type Description
NendoTrack

The resulting mixed track.

Source code in src/nendo/schema/core.py
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
def overlay(self, track: NendoTrack, gain_db: Optional[float] = 0) -> NendoTrack:
    """Overlay two tracks using gain control in decibels.

    The gain gets applied to the second track.
    This function creates a new related track in the library.

    Args:
        track (NendoTrack): The track to overlay with.
        gain_db (Optional[float], optional): The gain to apply to the second track.
            Defaults to 0.

    Returns:
        NendoTrack: The resulting mixed track.
    """
    if self.sr > track.sr:
        self.resample(track.sr)
    elif self.sr < track.sr:
        track.resample(self.sr)

    if self.signal.shape[1] > track.signal.shape[1]:
        signal_one = self.signal[:, : track.signal.shape[1]]
        signal_two = track.signal
    else:
        signal_one = self.signal
        signal_two = track.signal[:, : self.signal.shape[1]]

    # Convert dB gain to linear gain factor
    gain_factor_during_overlay = 10 ** (gain_db / 20)

    new_signal = signal_one + (signal_two * gain_factor_during_overlay)
    return self.nendo_instance.library.add_related_track_from_signal(
        signal=new_signal,
        sr=self.sr,
        track_type="track",
        related_track_id=self.id,
        track_meta={"overlay_parameters": {"gain_db": gain_db}},
    )

play ¤

play()

Play the track.

Source code in src/nendo/schema/core.py
898
899
900
def play(self):
    """Play the track."""
    play_signal(self.signal, self.sr)

process ¤

process(
    plugin: str, **kwargs: Any
) -> Union[NendoTrack, NendoCollection]

Process the track with the specified plugin.

Parameters:

Name Type Description Default
plugin str

Name of the plugin to run on the track.

required

Returns:

Type Description
Union[NendoTrack, NendoCollection]

The resulting track or collection, depending on what the plugin returns.

Source code in src/nendo/schema/core.py
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
def process(self, plugin: str, **kwargs: Any) -> Union[NendoTrack, NendoCollection]:
    """Process the track with the specified plugin.

    Args:
        plugin (str): Name of the plugin to run on the track.

    Returns:
        Union[NendoTrack, NendoCollection]: The resulting track or collection,
            depending on what the plugin returns.
    """
    registered_plugin: RegisteredNendoPlugin = getattr(
        self.nendo_instance.plugins,
        plugin,
    )
    wrapped_method = get_wrapped_methods(registered_plugin.plugin_instance)

    if len(wrapped_method) > 1:
        raise NendoError(
            "Plugin has more than one wrapped method. Please use `nd.plugins.<plugin_name>.<method_name>` instead.",
        )
    return getattr(self.nendo_instance.plugins, plugin)(track=self, **kwargs)

refresh ¤

refresh() -> NendoTrack

Refreshes the track with the latest values from the library.

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
432
433
434
435
436
437
438
439
440
441
def refresh(self) -> NendoTrack:
    """Refreshes the track with the latest values from the library.

    Returns:
        NendoTrack: The track itself.
    """
    refreshed_track = self.nendo_instance.library.get_track(self.id)
    for attr in vars(refreshed_track):
        setattr(self, attr, getattr(refreshed_track, attr))
    return self

relate_to_track ¤

relate_to_track(
    track_id: Union[str, UUID],
    relationship_type: str = "relationship",
    meta: Optional[Dict[str, Any]] = None,
)

Add relationship to another track.

Source code in src/nendo/schema/core.py
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
def relate_to_track(
    self,
    track_id: Union[str, uuid.UUID],
    relationship_type: str = "relationship",
    meta: Optional[Dict[str, Any]] = None,
):
    """Add relationship to another track."""
    self.nendo_instance.library.add_track_relationship(
        track_one_id=self.id,
        track_two_id=track_id,
        relationship_type=relationship_type,
        meta=meta,
    )
    self.refresh()
    return self

remove_from_collection ¤

remove_from_collection(
    collection_id: Union[str, UUID]
) -> NendoTrack

Remove the track from the collection specified by collection_id.

Parameters:

Name Type Description Default
collection_id Union[str, UUID]

ID of the collection from which to remove the track.

required

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
def remove_from_collection(
    self,
    collection_id: Union[str, uuid.UUID],
) -> NendoTrack:
    """Remove the track from the collection specified by collection_id.

    Args:
        collection_id (Union[str, uuid.UUID]): ID of the collection from which
            to remove the track.

    Returns:
        NendoTrack: The track itself.
    """
    self.nendo_instance.library.remove_track_from_collection(
        track_id=self.id,
        collection_id=collection_id,
    )
    self.refresh()
    return self

remove_meta ¤

remove_meta(key: str) -> NendoTrack

Remove the meta entry for the given key.

Parameters:

Name Type Description Default
key str

The key to remove metadata for.

required

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
def remove_meta(self, key: str) -> NendoTrack:
    """Remove the meta entry for the given key.

    Args:
        key (str): The key to remove metadata for.

    Returns:
        NendoTrack: The track itself.
    """
    if not self.has_meta(key):
        logger.error("Key not found in meta: %s", key)
        return None
    _ = self.meta.pop(key, None)
    self.nendo_instance.library.update_track(track=self)
    return self

resample ¤

resample(rsr: int = 44100) -> ndarray

Resample track.

Source code in src/nendo/schema/core.py
351
352
353
354
355
356
def resample(self, rsr: int = 44100) -> np.ndarray:
    """Resample track."""
    new_signal = librosa.resample(self.signal, orig_sr=self.sr, target_sr=rsr)
    self.__dict__["signal"] = new_signal
    self.__dict__["sr"] = rsr
    return new_signal

save ¤

save() -> NendoTrack

Save the track to the library.

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
423
424
425
426
427
428
429
430
def save(self) -> NendoTrack:
    """Save the track to the library.

    Returns:
        NendoTrack: The track itself.
    """
    self.nendo_instance.library.update_track(track=self)
    return self

set_meta ¤

set_meta(meta: Dict[str, Any]) -> NendoTrack

Set metadata of track.

Parameters:

Name Type Description Default
meta Dict[str, Any]

Dictionary containing the metadata to be set.

required

Returns:

Type Description
NendoTrack

The track itself.

Source code in src/nendo/schema/core.py
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
def set_meta(self, meta: Dict[str, Any]) -> NendoTrack:
    """Set metadata of track.

    Args:
        meta (Dict[str, Any]): Dictionary containing the metadata to be set.

    Returns:
        NendoTrack: The track itself.
    """
    try:
        self.meta.update(meta)
        self.nendo_instance.library.update_track(track=self)
    except NendoError as e:
        logger.exception("Error updating meta: %s", e)
    return self

slice ¤

slice(end: float, start: Optional[float] = 0) -> ndarray

Slice a track.

Parameters:

Name Type Description Default
end float

End of the slice in seconds.

required
start Optional[float]

Start of the slice in seconds. Defaults to 0.

0

Returns:

Type Description
ndarray

The sliced track.

Source code in src/nendo/schema/core.py
408
409
410
411
412
413
414
415
416
417
418
419
420
421
def slice(self, end: float, start: Optional[float] = 0) -> np.ndarray:
    """Slice a track.

    Args:
        end (float): End of the slice in seconds.
        start (Optional[float], optional): Start of the slice in seconds.
            Defaults to 0.

    Returns:
        np.ndarray: The sliced track.
    """
    start_frame = int(start * self.sr)
    end_frame = int(end * self.sr)
    return self.signal[:, start_frame:end_frame]

NendoTrackBase ¤

NendoTrackBase(**kwargs: Any)

Bases: BaseModel

Base class for tracks in Nendo.

Source code in src/nendo/schema/core.py
267
268
269
def __init__(self, **kwargs: Any) -> None:  # noqa: D107
    super().__init__(**kwargs)
    self.nendo_instance = Nendo()

signal property ¤

signal: ndarray

Lazy-load the signal from the track using librosa.

Returns:

Type Description
ndarray

The signal of the track.

sr property ¤

sr: int

Lazy-load the sample rate of the track.

Returns:

Type Description
int

The sample rate of the track.

NendoTrackCollectionRelationship ¤

Bases: NendoRelationship

Class representing a relationship between a NendoTrack and a NendoCollection.

NendoTrackTrackRelationship ¤

Bases: NendoRelationship

Class representing a relationship between two NendoTracks.

NendoUser ¤

Bases: NendoUserBase

Basic class representing a Nendo user.

RegisteredNendoPlugin ¤

Bases: BaseModel

A registered NendoPlugin.

Used by the NendoPluginRegistry to manage NendoPlugins.

ResourceLocation ¤

Bases: str, Enum

Enum representing differnt types of resource locations.

(e.g. original filepath, local FS library path, S3 bucket, etc.)

ResourceType ¤

Bases: str, Enum

Enum representing different types of resources used in Nendo.

Visibility ¤

Bases: str, Enum

Enum representing different visibilities of information in the nendo Library.

Mostly relevant when sharing a nendo library between different users.