madam.core module

class madam.core.Asset(essence: IO, **metadata)[source]

Bases: object

Represents a digital asset.

An Asset is an immutable value object whose contents consist of essence and metadata. Essence represents the actual data of a media file, such as the color values of an image, whereas the metadata describes the essence.

Assets should not be instantiated directly. Instead, use read() to retrieve an Asset representing the content.

__init__(essence: IO, **metadata) → None[source]

Initializes a new Asset with the specified essence and metadata.

Parameters:
  • essence (IO) – The essence of the asset as a file-like object
  • **metadata – The metadata describing the essence
essence

Represents the actual content of the asset.

The essence of an MP3 file, for example, is only comprised of the actual audio data, whereas metadata such as ID3 tags are stored separately as metadata.

class madam.core.AssetStorage[source]

Bases: collections.abc.MutableMapping, typing.Generic

Represents an abstract base class for data stores of Asset objects.

All implementations of AssetStorage require a constructor.

The persistence guarantees for stored data may differ based on the respective storage implementation.

__init__() → None[source]

Initializes a new AssetStorage.

clear() → None. Remove all items from D.
filter(**kwargs) → Iterable[AssetKey][source]

Returns a sequence of asset keys whose assets match the criteria that are specified by the passed arguments.

Parameters:**kwargs – Criteria defined as keys and values
Returns:Sequence of asset keys
Return type:Iterable
filter_by_tags(*tags) → Iterable[AssetKey][source]

Returns a set of all asset keys in this storage that have at least the specified tags.

Parameters:*tags – Mandatory tags of an asset to be included in result
Returns:Keys of the assets whose tags are a superset of the specified tags
Return type:Iterable
get(k[, d]) → D[k] if k in D, else d. d defaults to None.
items() → a set-like object providing a view on D's items
keys() → a set-like object providing a view on D's keys
pop(k[, d]) → v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() → (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

setdefault(k[, d]) → D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) → None. Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values() → an object providing a view on D's values
class madam.core.InMemoryStorage[source]

Bases: madam.core.AssetStorage

Represents a non-persistent storage backend for Asset objects.

Assets are not serialized, but stored in memory.

__init__() → None[source]

Initializes a new, empty InMemoryStorage object.

clear() → None. Remove all items from D.
filter(**kwargs) → Iterable[AssetKey]

Returns a sequence of asset keys whose assets match the criteria that are specified by the passed arguments.

Parameters:**kwargs – Criteria defined as keys and values
Returns:Sequence of asset keys
Return type:Iterable
filter_by_tags(*tags) → Iterable[AssetKey]

Returns a set of all asset keys in this storage that have at least the specified tags.

Parameters:*tags – Mandatory tags of an asset to be included in result
Returns:Keys of the assets whose tags are a superset of the specified tags
Return type:Iterable
get(k[, d]) → D[k] if k in D, else d. d defaults to None.
items() → a set-like object providing a view on D's items
keys() → a set-like object providing a view on D's keys
pop(k[, d]) → v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() → (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

setdefault(k[, d]) → D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) → None. Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values() → an object providing a view on D's values
class madam.core.Madam(config: Optional[Mapping[str, Any]] = None)[source]

Bases: object

Represents an instance of the library.

__init__(config: Optional[Mapping[str, Any]] = None) → None[source]

Initializes a new library instance with default configuration.

The default configuration includes a list of all available Processor and MetadataProcessor implementations.

Parameters:config – Mapping with settings.
get_processor(file: IO) → Optional[madam.core.Processor][source]

Returns a processor that can read the data in the specified file. If no suitable processor can be found None will be returned.

Parameters:file (IO) – file-like object to be parsed.
Returns:Processor object that can handle the data in the specified file, or None if no suitable processor could be found.
Return type:Processor or None
read(file: IO, additional_metadata: Mapping[KT, VT_co] = None)[source]

Reads the specified file and returns its contents as an Asset object.

Parameters:
  • file (IO) – file-like object to be parsed
  • additional_metadata (Mapping) – optional metadata for the resulting asset. Existing metadata entries extracted from the file will be overwritten.
Returns:

Asset representing the specified file

Return type:

Asset

Raises:
Example:
>>> import io
>>> from madam import Madam
>>> manager = Madam()
>>> file = io.BytesIO(b'\x89PNG\r\n\x1a\n\x00\x00\x00\rIHDR\x00\x00\x00\x01\x00\x00\x00\x01'
... b'\x08\x06\x00\x00\x00\x1f\x15\xc4\x89\x00\x00\x00\nIDATx\x9cc\x00\x01\x00\x00\x05\x00'
... b'\x01\r\n-\xb4\x00\x00\x00\x00IEND\xaeB`\x82')
>>> asset = manager.read(file)
write(asset: madam.core.Asset, file: IO) → None[source]

Write the Asset object to the specified file.

Parameters:
  • asset (Asset) – Asset that contains the data to be written
  • file (IO) – file-like object to be written
Example:
>>> import io
>>> import os
>>> from madam import Madam
>>> from madam.core import Asset
>>> gif_asset = Asset(essence=io.BytesIO(b'GIF89a\x01\x00\x01\x00\x00\x00\x00;'), mime_type='image/gif')
>>> manager = Madam()
>>> with open(os.devnull, 'wb') as file:
...     manager.write(gif_asset, file)
>>> wav_asset = Asset(
...     essence=io.BytesIO(b'RIFF$\x00\x00\x00WAVEfmt \x10\x00\x00\x00\x01\x00\x01\x00D\xac'
...             b'\x00\x00\x88X\x01\x00\x02\x00\x10\x00data\x00\x00\x00\x00'),
...     mime_type='video/mp4')
>>> with open(os.devnull, 'wb') as file:
...     manager.write(wav_asset, file)
class madam.core.MetadataProcessor(config: Optional[Mapping[str, Any]] = None)[source]

Bases: object

Represents an entity that can manipulate metadata.

Every MetadataProcessor needs to have an __init__ method with an optional config parameter in order to be registered correctly.

__init__(config: Optional[Mapping[str, Any]] = None) → None[source]

Initializes a new MetadataProcessor.

combine(file: IO, metadata: Mapping[KT, VT_co]) → IO[source]

Returns a byte stream whose contents represent the specified file where the specified metadata was added.

Parameters:
  • metadata (Mapping) – Mapping of the metadata format to the metadata dict
  • file (IO) – Container file
Returns:

file-like object with combined content

Return type:

IO

formats

The metadata formats which are supported.

Returns:supported metadata formats
Return type:set[str]
read(file: IO) → Mapping[KT, VT_co][source]

Reads the file and returns the metadata.

The metadata that is returned is grouped by type. The keys are specified by format.

Parameters:file (IO) – File-like object to be read
Returns:Metadata contained in the file
Return type:Mapping
Raises:UnsupportedFormatError – if the data is corrupt or its format is not supported
strip(file: IO) → IO[source]

Removes all metadata of the supported type from the specified file.

Parameters:file (IO) – file-like that should get stripped of the metadata
Returns:file-like object without metadata
Return type:IO
exception madam.core.OperatorError(*args)[source]

Bases: Exception

Represents an error that is raised whenever an error occurs in an operator().

__init__(*args)[source]

Initializes a new OperatorError.

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

class madam.core.Pipeline[source]

Bases: object

Represents a processing pipeline for Asset objects.

The pipeline can be configured to hold a list of asset processing operators, all of which are applied to one or more assets when calling the process() method.

__init__() → None[source]

Initializes a new pipeline without operators.

add(operator: Callable) → None[source]

Appends the specified operator to the processing chain.

Parameters:operator – Operator to be added
process(*assets) → Generator[madam.core.Asset, float, None][source]

Applies the operators in this pipeline on the specified assets.

Parameters:*assets (Asset) – Asset objects to be processed
Returns:Generator with processed assets
class madam.core.Processor(config: Optional[Mapping[str, Any]] = None)[source]

Bases: object

Represents an entity that can create Asset objects from binary data.

Every Processor needs to have an __init__ method with an optional config parameter in order to be registered correctly.

__init__(config: Optional[Mapping[str, Any]] = None) → None[source]

Initializes a new Processor.

Parameters:config – Mapping with settings.
can_read(file: IO) → bool[source]

Returns whether the specified MIME type is supported by this processor.

Parameters:file (IO) – file-like object to be tested
Returns:whether the data format of the specified file is supported or not
Return type:bool
read(file: IO) → madam.core.Asset[source]

Returns an Asset object whose essence is identical to the contents of the specified file.

Parameters:file (IO) – file-like object to be read
Returns:Asset with essence
Return type:Asset
Raises:UnsupportedFormatError – if the specified data format is not supported
class madam.core.ShelveStorage(path: Union[pathlib.Path, str])[source]

Bases: madam.core.AssetStorage

Represents a persistent storage backend for Asset objects. Asset keys must be strings.

ShelveStorage uses a file on the file system to serialize Assets.

__init__(path: Union[pathlib.Path, str])[source]

Initializes a new ShelveStorage with the specified path.

Parameters:path (pathlib.Path or str) – File system path where the data should be stored
clear() → None. Remove all items from D.
filter(**kwargs) → Iterable[AssetKey]

Returns a sequence of asset keys whose assets match the criteria that are specified by the passed arguments.

Parameters:**kwargs – Criteria defined as keys and values
Returns:Sequence of asset keys
Return type:Iterable
filter_by_tags(*tags) → Iterable[AssetKey]

Returns a set of all asset keys in this storage that have at least the specified tags.

Parameters:*tags – Mandatory tags of an asset to be included in result
Returns:Keys of the assets whose tags are a superset of the specified tags
Return type:Iterable
get(k[, d]) → D[k] if k in D, else d. d defaults to None.
items() → a set-like object providing a view on D's items
keys() → a set-like object providing a view on D's keys
pop(k[, d]) → v, remove specified key and return the corresponding value.

If key is not found, d is returned if given, otherwise KeyError is raised.

popitem() → (k, v), remove and return some (key, value) pair

as a 2-tuple; but raise KeyError if D is empty.

setdefault(k[, d]) → D.get(k,d), also set D[k]=d if k not in D
update([E, ]**F) → None. Update D from mapping/iterable E and F.

If E present and has a .keys() method, does: for k in E: D[k] = E[k] If E present and lacks .keys() method, does: for (k, v) in E: D[k] = v In either case, this is followed by: for k, v in F.items(): D[k] = v

values() → an object providing a view on D's values
exception madam.core.UnsupportedFormatError(*args)[source]

Bases: Exception

Represents an error that is raised whenever file content with unknown type is encountered.

__init__(*args) → None[source]

Initializes a new UnsupportedFormatError.

with_traceback()

Exception.with_traceback(tb) – set self.__traceback__ to tb and return self.

madam.core.operator(function: Callable[[...], madam.core.Asset]) → Callable[[...], Callable[[...], madam.core.Asset]][source]

Decorator function for methods that process assets.

Usually, it will be used with operations in a Processor implementation to make the methods configurable before applying the method to an asset.

Only keyword arguments are allowed for configuration.

Example for using a decorated convert method:

convert_to_opus = processor.convert(mime_type='audio/opus')
convert_to_opus(asset)
Parameters:function – Method to decorate
Returns:Configurable method