sift_py.file_attachment.metadata

Module containing optional metadata types to provide to Sift when uploading a file attachment. Though optional, providing this information could help improve quality of renders on the Sift app.

  1"""
  2Module containing optional metadata types to provide to Sift when uploading a file attachment.
  3Though optional, providing this information could help improve quality of renders on the Sift app.
  4"""
  5
  6from __future__ import annotations
  7
  8from datetime import datetime
  9from typing import Any, Optional, Type
 10
 11from google.protobuf.timestamp_pb2 import Timestamp
 12from sift.remote_files.v1.remote_files_pb2 import (
 13    ImageMetadata as ImageMetadataPb,
 14)
 15from sift.remote_files.v1.remote_files_pb2 import (
 16    VideoMetadata as VideoMetadataPb,
 17)
 18from typing_extensions import Self
 19
 20from sift_py._internal.convert.json import AsJson
 21from sift_py._internal.convert.protobuf import AsProtobuf
 22
 23
 24class Metadata(AsJson): ...
 25
 26
 27class VideoMetadata(AsProtobuf, Metadata):
 28    """
 29    Metadata for video media-types i.e. any mimetypes of the following pattern: `video/*`.
 30    """
 31
 32    width: int
 33    height: int
 34    duration_seconds: float
 35    timestamp: Optional[datetime]
 36
 37    def __init__(
 38        self, width: int, height: int, duration_seconds: float, timestamp: Optional[datetime] = None
 39    ):
 40        self.width = width
 41        self.height = height
 42        self.duration_seconds = duration_seconds
 43        self.timestamp = timestamp
 44
 45    def as_pb(self, klass: Type[VideoMetadataPb]) -> VideoMetadataPb:
 46        if self.timestamp is not None:
 47            timestamp_pb = Timestamp()
 48            timestamp_pb.FromDatetime(self.timestamp)
 49        else:
 50            timestamp_pb = None
 51
 52        return klass(
 53            width=self.width,
 54            height=self.height,
 55            duration_seconds=self.duration_seconds,
 56            timestamp=timestamp_pb,
 57        )
 58
 59    @classmethod
 60    def from_pb(cls, message: VideoMetadataPb) -> Self:
 61        return cls(
 62            width=message.width,
 63            height=message.height,
 64            duration_seconds=message.duration_seconds,
 65            timestamp=message.timestamp.ToDateTime(),  # type: ignore
 66        )
 67
 68    def as_json(self) -> Any:
 69        timestamp = None if self.timestamp is None else self.timestamp.isoformat()
 70        return {
 71            "height": self.height,
 72            "width": self.width,
 73            "duration_seconds": self.duration_seconds,
 74            "timestamp": timestamp,
 75        }
 76
 77
 78class ImageMetadata(AsProtobuf, Metadata):
 79    """
 80    Metadata for image media-types i.e. any mimetypes of the following pattern: `image/*`.
 81    """
 82
 83    width: int
 84    height: int
 85
 86    def __init__(self, width: int, height: int):
 87        self.width = width
 88        self.height = height
 89
 90    def as_pb(self, klass: Type[ImageMetadataPb]) -> ImageMetadataPb:
 91        return klass(
 92            width=self.width,
 93            height=self.height,
 94        )
 95
 96    @classmethod
 97    def from_pb(cls, message: ImageMetadataPb) -> Self:
 98        return cls(
 99            width=message.width,
100            height=message.height,
101        )
102
103    def as_json(self) -> Any:
104        return {
105            "height": self.height,
106            "width": self.width,
107        }
class Metadata(sift_py._internal.convert.json.AsJson):
25class Metadata(AsJson): ...

Utility sub-types that require custom-serialization meant to be used in conjunction with the to_json function. Sub-types should implement as_json which should return the object that you want passed to json.dumps.

class VideoMetadata(abc.ABC, typing.Generic[~T]):
28class VideoMetadata(AsProtobuf, Metadata):
29    """
30    Metadata for video media-types i.e. any mimetypes of the following pattern: `video/*`.
31    """
32
33    width: int
34    height: int
35    duration_seconds: float
36    timestamp: Optional[datetime]
37
38    def __init__(
39        self, width: int, height: int, duration_seconds: float, timestamp: Optional[datetime] = None
40    ):
41        self.width = width
42        self.height = height
43        self.duration_seconds = duration_seconds
44        self.timestamp = timestamp
45
46    def as_pb(self, klass: Type[VideoMetadataPb]) -> VideoMetadataPb:
47        if self.timestamp is not None:
48            timestamp_pb = Timestamp()
49            timestamp_pb.FromDatetime(self.timestamp)
50        else:
51            timestamp_pb = None
52
53        return klass(
54            width=self.width,
55            height=self.height,
56            duration_seconds=self.duration_seconds,
57            timestamp=timestamp_pb,
58        )
59
60    @classmethod
61    def from_pb(cls, message: VideoMetadataPb) -> Self:
62        return cls(
63            width=message.width,
64            height=message.height,
65            duration_seconds=message.duration_seconds,
66            timestamp=message.timestamp.ToDateTime(),  # type: ignore
67        )
68
69    def as_json(self) -> Any:
70        timestamp = None if self.timestamp is None else self.timestamp.isoformat()
71        return {
72            "height": self.height,
73            "width": self.width,
74            "duration_seconds": self.duration_seconds,
75            "timestamp": timestamp,
76        }

Metadata for video media-types i.e. any mimetypes of the following pattern: video/*.

VideoMetadata( width: int, height: int, duration_seconds: float, timestamp: Union[datetime.datetime, NoneType] = None)
38    def __init__(
39        self, width: int, height: int, duration_seconds: float, timestamp: Optional[datetime] = None
40    ):
41        self.width = width
42        self.height = height
43        self.duration_seconds = duration_seconds
44        self.timestamp = timestamp
width: int
height: int
duration_seconds: float
timestamp: Union[datetime.datetime, NoneType]
def as_pb( self, klass: Type[sift.remote_files.v1.remote_files_pb2.VideoMetadata]) -> sift.remote_files.v1.remote_files_pb2.VideoMetadata:
46    def as_pb(self, klass: Type[VideoMetadataPb]) -> VideoMetadataPb:
47        if self.timestamp is not None:
48            timestamp_pb = Timestamp()
49            timestamp_pb.FromDatetime(self.timestamp)
50        else:
51            timestamp_pb = None
52
53        return klass(
54            width=self.width,
55            height=self.height,
56            duration_seconds=self.duration_seconds,
57            timestamp=timestamp_pb,
58        )

Performs the conversion into a sub-type of ProtobufMessage.

@classmethod
def from_pb( cls, message: sift.remote_files.v1.remote_files_pb2.VideoMetadata) -> typing_extensions.Self:
60    @classmethod
61    def from_pb(cls, message: VideoMetadataPb) -> Self:
62        return cls(
63            width=message.width,
64            height=message.height,
65            duration_seconds=message.duration_seconds,
66            timestamp=message.timestamp.ToDateTime(),  # type: ignore
67        )

Converts a protobuf object to the type of the sub-class class.

def as_json(self) -> Any:
69    def as_json(self) -> Any:
70        timestamp = None if self.timestamp is None else self.timestamp.isoformat()
71        return {
72            "height": self.height,
73            "width": self.width,
74            "duration_seconds": self.duration_seconds,
75            "timestamp": timestamp,
76        }
class ImageMetadata(abc.ABC, typing.Generic[~T]):
 79class ImageMetadata(AsProtobuf, Metadata):
 80    """
 81    Metadata for image media-types i.e. any mimetypes of the following pattern: `image/*`.
 82    """
 83
 84    width: int
 85    height: int
 86
 87    def __init__(self, width: int, height: int):
 88        self.width = width
 89        self.height = height
 90
 91    def as_pb(self, klass: Type[ImageMetadataPb]) -> ImageMetadataPb:
 92        return klass(
 93            width=self.width,
 94            height=self.height,
 95        )
 96
 97    @classmethod
 98    def from_pb(cls, message: ImageMetadataPb) -> Self:
 99        return cls(
100            width=message.width,
101            height=message.height,
102        )
103
104    def as_json(self) -> Any:
105        return {
106            "height": self.height,
107            "width": self.width,
108        }

Metadata for image media-types i.e. any mimetypes of the following pattern: image/*.

ImageMetadata(width: int, height: int)
87    def __init__(self, width: int, height: int):
88        self.width = width
89        self.height = height
width: int
height: int
def as_pb( self, klass: Type[sift.remote_files.v1.remote_files_pb2.ImageMetadata]) -> sift.remote_files.v1.remote_files_pb2.ImageMetadata:
91    def as_pb(self, klass: Type[ImageMetadataPb]) -> ImageMetadataPb:
92        return klass(
93            width=self.width,
94            height=self.height,
95        )

Performs the conversion into a sub-type of ProtobufMessage.

@classmethod
def from_pb( cls, message: sift.remote_files.v1.remote_files_pb2.ImageMetadata) -> typing_extensions.Self:
 97    @classmethod
 98    def from_pb(cls, message: ImageMetadataPb) -> Self:
 99        return cls(
100            width=message.width,
101            height=message.height,
102        )

Converts a protobuf object to the type of the sub-class class.

def as_json(self) -> Any:
104    def as_json(self) -> Any:
105        return {
106            "height": self.height,
107            "width": self.width,
108        }