Completed
Push4a7df2...0864f5
passed — Build
created

Base.get_original_name()   A

↳ Parent: Base

Complexity

Conditions 1

Duplication

Lines 0
Ratio 0 %

Size

Total Lines 8

Importance

Changes 0
Metric Value
cc 1
dl 0
loc 8
rs 9.4285
c 0
b 0
f 0
1
"""
2
The base module provides a base :class:`Base` class for all objects that
3
are tracked by Elodie. The Base class provides some base functionality used
4
by all the media types, but isn't itself used to represent anything. Its
5
sub-classes (:class:`~elodie.media.audio.Audio`,
6
:class:`~elodie.media.photo.Photo`, :class:`~elodie.media.video.Video`, and
7
:class:`~elodie.media.text.Text`)
8
are used to represent the actual files.
9
10
.. moduleauthor:: Jaisen Mathai <[email protected]>
11
"""
12
13
import mimetypes
14
import os
15
16
try:        # Py3k compatibility
17
    basestring
18
except NameError:
19
    basestring = (bytes, str)
20
21
22
class Base(object):
23
24
    """The base class for all media objects.
25
26
    :param str source: The fully qualified path to the video file.
27
    """
28
29
    __name__ = 'Base'
30
31
    extensions = ()
32
33
    def __init__(self, source=None):
34
        self.source = source
35
        self.reset_cache()
36
37
    def format_metadata(self, **kwargs):
38
        """Method to consistently return a populated metadata dictionary.
39
40
        :returns: dict
41
        """
42
43
    def get_album(self):
44
        """Base method for getting an album
45
46
        :returns: None
47
        """
48
        return None
49
50
    def get_file_path(self):
51
        """Get the full path to the video.
52
53
        :returns: string
54
        """
55
        return self.source
56
57
    def get_coordinate(self, type):
58
        return None
59
60
    def get_extension(self):
61
        """Get the file extension as a lowercased string.
62
63
        :returns: string or None for a non-video
64
        """
65
        if(not self.is_valid()):
66
            return None
67
68
        source = self.source
69
        return os.path.splitext(source)[1][1:].lower()
70
71
    def get_metadata(self, update_cache=False):
72
        """Get a dictionary of metadata for any file.
73
74
        All keys will be present and have a value of None if not obtained.
75
76
        :returns: dict or None for non-text files
77
        """
78
        if(not self.is_valid()):
79
            return None
80
81
        if(isinstance(self.metadata, dict) and update_cache is False):
82
            return self.metadata
83
84
        source = self.source
85
86
        self.metadata = {
87
            'date_taken': self.get_date_taken(),
88
            'latitude': self.get_coordinate('latitude'),
89
            'longitude': self.get_coordinate('longitude'),
90
            'album': self.get_album(),
91
            'title': self.get_title(),
92
            'mime_type': self.get_mimetype(),
93
            'original_name': self.get_original_name(),
94
            'base_name': os.path.splitext(os.path.basename(source))[0],
95
            'extension': self.get_extension(),
96
            'directory_path': os.path.dirname(source)
97
        }
98
99
        return self.metadata
100
101
    def get_mimetype(self):
102
        """Get the mimetype of the file.
103
104
        :returns: str or None for unsupported files.
105
        """
106
        if(not self.is_valid()):
107
            return None
108
109
        source = self.source
110
        mimetype = mimetypes.guess_type(source)
111
        if(mimetype is None):
112
            return None
113
114
        return mimetype[0]
115
116
    def get_original_name(self):
117
        """Get the original name of the file from before it was imported.
118
        Does not include the extension.
119
        Overridden by Media class for files with EXIF.
120
121
        :returns: str or None for unsupported files.
122
        """
123
        return None
124
125
    def get_title(self):
126
        """Base method for getting the title of a file
127
128
        :returns: None
129
        """
130
        return None
131
132
    def is_valid(self):
133
        """Check the file extension against valid file extensions.
134
135
        The list of valid file extensions come from self.extensions.
136
137
        :returns: bool
138
        """
139
        source = self.source
140
        return os.path.splitext(source)[1][1:].lower() in self.extensions
141
142
    def reset_cache(self):
143
        """Resets any internal cache
144
        """
145
        self.metadata = None
146
147
    def set_album(self, name):
148
        """Base method for setting the album of a file
149
150
        :returns: None
151
        """
152
        return None
153
154
    def set_album_from_folder(self):
155
        """Set the album attribute based on the leaf folder name
156
157
        :returns: bool
158
        """
159
        metadata = self.get_metadata()
160
161
        # If this file has an album already set we do not overwrite EXIF
162
        if(not isinstance(metadata, dict) or metadata['album'] is not None):
163
            return False
164
165
        folder = os.path.basename(metadata['directory_path'])
166
        # If folder is empty we skip
167
        if(len(folder) == 0):
168
            return False
169
170
        self.set_album(folder)
171
        return True
172
173
    def set_metadata_basename(self, new_basename):
174
        """Update the basename attribute in the metadata dict for this instance.
175
176
        This is used for when we update the EXIF title of a media file. Since
177
        that determines the name of a file if we update the title of a file
178
        more than once it appends to the file name.
179
180
        i.e. 2015-12-31_00-00-00-my-first-title-my-second-title.jpg
181
182
        :param str new_basename: New basename of file (with the old title
183
            removed).
184
        """
185
        self.get_metadata()
186
        self.metadata['base_name'] = new_basename
187
188
    def set_metadata(self, **kwargs):
189
        """Method to manually update attributes in metadata.
190
191
        :params dict kwargs: Named parameters to update.
192
        """
193
        metadata = self.get_metadata()
194
        for key in kwargs:
195
            if(key in metadata):
196
                self.metadata[key] = kwargs[key]
197
198
    def set_original_name(self):
199
        """Stores the original file name into EXIF/metadata.
200
        :returns: bool
201
        """
202
        return False
203
204
    @classmethod
205
    def get_class_by_file(cls, _file, classes):
206
        """Static method to get a media object by file.
207
        """
208
        if not isinstance(_file, basestring) or not os.path.isfile(_file):
209
            return None
210
211
        extension = os.path.splitext(_file)[1][1:].lower()
212
213
        if len(extension) > 0:
214
            for i in classes:
215
                if(extension in i.extensions):
216
                    return i(_file)
217
218
        return None
219
220
    @classmethod
221
    def get_valid_extensions(cls):
222
        """Static method to access static extensions variable.
223
224
        :returns: tuple(str)
225
        """
226
        return cls.extensions
227
228
229
def get_all_subclasses(cls=None):
230
    """Module method to get all subclasses of Base.
231
    """
232
    subclasses = set()
233
234
    this_class = Base
235
    if cls is not None:
236
        this_class = cls
237
238
    subclasses.add(this_class)
239
240
    this_class_subclasses = this_class.__subclasses__()
241
    for child_class in this_class_subclasses:
242
        subclasses.update(get_all_subclasses(child_class))
243
244
    return subclasses
245