Content and attachments#

Bundles can have local content embedded in the XML document, or attachments. Attachments are files that are referenced from the XML using the src attribute. Bundles with attachments are stored as zip files.

The <link>, <repository> and <file> nodes of the bundle XML all have an optional src attribute that can reference attachments. The path of src is relative to the location of the XML document of the bundle. The src attribute can refer to a single file or a directory. When src references a directory, all files in that directory and subdirectories thereof are part of the bundle. When working with an existing zip bundle, the files are accessed directly from the zip file.

The Link, Repository and File classes provide several methods to access the attachment, for example open() and copy_to(). All file access methods are documented in the SrcAttachmentMixin mixin.

When creating a bundle the src attribute should refer to the file or directory to attach. These files or directories need to remain available on the filesystem until the bundle has been exported using the to_buffer(), to_file() or to_directory() methods, and when using the latter export method, the src paths may not overlap the path to export the bundle to.

API#

exception momotor.bundles.elements.content.AttachmentContent#

Raised when the content is in an attachment. Subclass of ValueError

exception momotor.bundles.elements.content.NoContent#

Raised when no content was provided. Subclass of ValueError

class momotor.bundles.elements.content.ContentAttachmentElement(bundle)#

A full content element supporting attachments.

Contents can be string, bytes, boolean, integer, float or decimal.Decimal values, or provided as an attachment using the src attribute.

Parameters:

bundle (Bundle) – The Bundle containing this element

file_size(path=None)#

Get file size for the content.

Return type:

int | None

Returns:

The file size

has_writable_content()#

Returns True if the element has an attachment with content that can be written to

is_dir(path=None)#

Check if the attachment src refers to is a directory

Return type:

bool

open(path=None)#

Open the attachment file for reading. Handles opening files directly from filesystem and from zipped bundles

Parameters:

path (str | PurePosixPath | None) – for directory attachments, path selects a file in that directory

Return type:

BinaryIO

Returns:

the opened file

Raises:
  • FileNotFoundError – if the element has no attachment (when src is None), or when it’s a directory and path does not exist in that directory

  • IsADirectoryError – when it’s a directory

read(path=None)#

Read the contents of the attachment

Parameters:

path (str | PurePosixPath | None) – for directory attachments, path selects a file in that directory

Return type:

bytes

Returns:

A bytes object with the full file contents

property type_: str | None#

The type attribute.

class momotor.bundles.elements.content.ContentBasicElement(bundle)#

A basic content element. Contents can be string or boolean values.

Parameters:

bundle (Bundle) – The Bundle containing this element

HAS_ENCODING: typing.ClassVar[bool] = False#
VALID_PROCESSED_TYPES: typing.ClassVar[tuple[type, ...]] = (<class 'str'>, <class 'bool'>)#
class momotor.bundles.elements.content.ContentFullElement(bundle)#

A full content element.

Contents can be string, bytes, boolean, integer, float or decimal.Decimal values.

Parameters:

bundle (Bundle) – The Bundle containing this element

HAS_ENCODING: typing.ClassVar[bool] = True#
VALID_PROCESSED_TYPES: typing.ClassVar[tuple[type, ...]] = (<class 'str'>, <class 'bool'>, <class 'bytes'>, <class 'int'>, <class 'float'>, <class 'decimal.Decimal'>)#
property encoding: str | None#

encoding attribute: read-only, the encoding is automatically determined from the value

property type_: str | None#

The type attribute. Indicates the type of the value attribute: string, integer or float

momotor.bundles.elements.content.NO_CONTENT = <object object>#

A sentinel value indicating there is no content.

class momotor.bundles.mixins.attachments.SrcAttachmentMixin#

Mixin to provide attributes to refer to external files using the src attribute

See attachments for how attachments are handled differently depending on whether the bundle is new or an existing one.

copy_to(destination, *, name=None)#

Copy an attachment this element refers to, to given destination directory.

If the attachment is a file, creates a new file in the given directory. If name is provided this will be the name of the new file, otherwise the name of the source file is used.

If the attachment is a directory, copies the contents of the source directory to the destination directory. If name is provided it is created as a new directory inside the destination directory.

Will not overwrite an existing file or directory.

Parameters:
  • destination (Path) – base destination directory

  • name (PurePath | None) – name

Raises:
Return type:

Path

file_ctime(path=None)#

Get file creation time for the attachment.

Return type:

struct_time | None

file_hashes(hash_names)#

Calculate the hashes of the file.

Only for file attachments. Will return an empty dictionary if the file does not exist or is a directory.

Parameters:

hash_names (Iterable[str]) – Names of the hashes to calculate. Should be valid arguments to hashlib.new()

Return type:

dict[str, str]

Returns:

A dictionary hash-algorithm -> hash

file_size(path=None)#

Get file size for the attachment.

Return type:

int | None

has_attachment_content()#

Returns True if the element has an attachment with content

Return type:

bool

has_bundle()#

Returns True if src references a file associated with a bundle

Return type:

bool

has_writable_content()#

Returns True if the element has an attachment with content that can be written to

Return type:

bool

has_zip_bundle()#

Returns True if src references a file associated with a zipped bundle

Return type:

bool

is_dir(path=None)#

Check if the attachment src refers to is a directory

Return type:

bool

iterdir(*, include_empty_root=False)#

Recursively iterate the contents of a directory attachment. The returned paths are relative to self.absolute_path

If the attachment is an empty directory and include_empty_root is True, a single None value is yielded

Return type:

Generator[PurePosixPath | None, None, None]

open(path=None)#

Open the attachment file for reading. Handles opening files directly from filesystem and from zipped bundles

Parameters:

path (str | PurePosixPath | None) – for directory attachments, path selects a file in that directory

Return type:

BinaryIO

Returns:

the opened file

Raises:
  • FileNotFoundError – if the element has no attachment (when src is None), or when it’s a directory and path does not exist in that directory

  • IsADirectoryError – when it’s a directory

read(path=None)#

Read the contents of the attachment

Parameters:

path (str | PurePosixPath | None) – for directory attachments, path selects a file in that directory

Return type:

bytes

Returns:

A bytes object with the full file contents

validate_hashes(expected_hashes)#

Validate hash values of the file.

Only for file attachments

Parameters:

expected_hashes (dict[str, str]) – A dictionary of hash-algorithm -> hash items

Return type:

bool

Returns:

True of the hashes are the expected values

property absolute_path: Path#

Get the absolute path of the attachment referenced by src

Raises:

ZippedAttachment – when the attachment is in a zipped bundle and therefor has no filesystem path

property export_src: PurePosixPath | None#

The export path of the attachment, converted to be safe for use in ZIP files

property src: PurePath | None#

src attribute: file path of the content.

An absolute path (Path) when referencing a standalone file, or a relative path (PurePosixPath) when referencing a file in a bundle

property src_bundle: Bundle | None#

If src is a relative path, the Bundle src references to.

An src attribute with a relative path is always associated with a bundle, either the current bundle or another bundle from which this src was copied from using recreate(). The bundle provides the base path for the relative path.

class momotor.bundles.mixins.attachments.AttachmentSrc(path=None, bundle=None, *, validate=True)#
bundle: Optional[Bundle] = None#
path: PurePath | None = None#