Test Failed
Push — develop ( 572338...fb7300 )
by Dean
02:29
created

Shows.process_missing_episodes()   C

Complexity

Conditions 8

Size

Total Lines 59

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 72
Metric Value
cc 8
dl 0
loc 59
ccs 0
cts 0
cp 0
crap 72
rs 5.8915

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1 1
from plugin.sync.core.constants import GUID_AGENTS
2 1
from plugin.sync.core.enums import SyncMedia, SyncData
3 1
from plugin.sync.modes.core.base import log_unsupported, mark_unsupported
4 1
from plugin.sync.modes.push.base import Base
5
6 1
from plex_database.models import MetadataItem, MediaItem, Episode
7 1
from plex_metadata import Guid
8 1
import copy
9 1
import elapsed
10 1
import logging
11
12 1
log = logging.getLogger(__name__)
13
14
15 1
class Shows(Base):
16 1
    def __init__(self, task):
17
        super(Shows, self).__init__(task)
18
19
        # Sections
20
        self.p_sections = None
21
        self.p_sections_map = None
22
23
        # Shows
24
        self.p_shows = None
25
        self.p_shows_count = None
26
        self.p_shows_pending = None
27
        self.p_shows_unsupported = None
28
29
        # Seasons
30
        self.p_seasons = None
31
32
        # Episodes
33
        self.p_episodes = None
34
        self.p_episodes_count = None
35
        self.p_episodes_pending = None
36
37
    @elapsed.clock
38
    def construct(self):
39
        # Retrieve movie sections
40
        self.p_sections, self.p_sections_map = self.sections('show')
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named sections.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
41
42
        # Determine number of shows that will be processed
43
        self.p_shows_count = self.plex.library.shows.count(
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named plex.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
44
            self.p_sections
45
        )
46
47
        # Determine number of shows that will be processed
48
        self.p_episodes_count = self.plex.library.episodes.count_items(
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named plex.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
49
            self.p_sections
50
        )
51
52
        # Increment progress steps total
53
        self.current.progress.group(Shows, 'matched:shows').add(self.p_shows_count)
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
54
        self.current.progress.group(Shows, 'matched:episodes').add(self.p_episodes_count)
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
55
        self.current.progress.group(Shows, 'missing:shows')
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
56
        self.current.progress.group(Shows, 'missing:episodes')
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
57
58
    @elapsed.clock
59
    def start(self):
60
        # Fetch movies with account settings
61
        self.p_shows, self.p_seasons, self.p_episodes = self.plex.library.episodes.mapped(
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named plex.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
62
            self.p_sections, ([
63
                MetadataItem.title,
64
                MetadataItem.year
65
            ], [], [
66
                MediaItem.audio_channels,
67
                MediaItem.audio_codec,
68
                MediaItem.height,
69
                MediaItem.interlaced,
70
71
                Episode.added_at
72
            ]),
73
            account=self.current.account.plex.key,
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
74
            parse_guid=True
75
        )
76
77
        # Reset state
78
        self.p_shows_pending = self.trakt.table.shows.copy()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named trakt.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
79
        self.p_shows_unsupported = {}
80
81
        self.p_episodes_pending = copy.deepcopy(self.trakt.table.episodes)
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named trakt.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
82
83
    @elapsed.clock
84
    def run(self):
85
        # Process matched items
86
        self.process_matched_shows()
87
        self.process_matched_episodes()
88
89
        # Report unsupported shows
90
        log_unsupported(log, 'Found %d unsupported show(s)\n%s', self.p_shows_unsupported)
91
92
        # Process missing items
93
        self.process_missing_shows()
94
        self.process_missing_episodes()
95
96
    #
97
    # Shows
98
    #
99
100
    @elapsed.clock
101
    def process_matched_shows(self):
102
        # Iterate over plex shows
103
        for sh_id, p_guid, p_show in self.p_shows:
104
            # Increment one step
105
            self.current.progress.group(Shows, 'matched:shows').step()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
106
107
            # Ensure `p_guid` is available
108
            if not p_guid or p_guid.agent not in GUID_AGENTS:
109
                mark_unsupported(self.p_shows_unsupported, sh_id, p_guid, p_show)
110
                continue
111
112
            key = (p_guid.agent, p_guid.sid)
113
114
            # Try retrieve `pk` for `key`
115
            pk = self.trakt.table.get(key)
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named trakt.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
116
117
            for data in self.get_data(SyncMedia.Shows):
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named get_data.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
118
                t_show = self.trakt[(SyncMedia.Shows, data)].get(pk)
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named trakt.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
119
120
                # Execute show handlers
121
                self.execute_handlers(
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named execute_handlers.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
122
                    SyncMedia.Shows, data,
123
                    key=sh_id,
124
                    p_guid=p_guid,
125
126
                    p_item=p_show,
127
128
                    t_item=t_show
129
                )
130
131
            # Remove show from `pending_shows`
132
            if pk and pk in self.p_shows_pending:
133
                self.p_shows_pending.remove(pk)
134
135
            # Task checkpoint
136
            self.checkpoint()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named checkpoint.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
137
138
        # Stop progress group
139
        self.current.progress.group(Shows, 'matched:shows').stop()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
140
141
    @elapsed.clock
142
    def process_missing_shows(self):
143
        # Increment progress steps
144
        self.current.progress.group(Shows, 'missing:shows').add(len(self.p_shows_pending))
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
145
146
        # Iterate over trakt shows (that aren't in plex)
147
        for pk in list(self.p_shows_pending):
148
            # Increment one step
149
            self.current.progress.group(Shows, 'missing:shows').step()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
150
151
            # Iterate over data handlers
152
            triggered = False
153
154
            for data in self.get_data(SyncMedia.Shows):
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named get_data.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
155
                if data not in [SyncData.Collection]:
156
                    continue
157
158
                # Retrieve show
159
                t_show = self.trakt[(SyncMedia.Shows, data)].get(pk)
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named trakt.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
160
161
                if not t_show:
162
                    continue
163
164
                log.debug('Found show missing from plex: %r [data: %r]', pk, SyncData.title(data))
165
166
                # Trigger handler
167
                self.execute_handlers(
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named execute_handlers.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
168
                    SyncMedia.Shows, data,
169
170
                    key=None,
171
172
                    p_guid=Guid(*pk),
173
                    p_item=None,
174
175
                    t_item=t_show
176
                )
177
178
                # Mark triggered
179
                triggered = True
180
181
            # Check if action was triggered
182
            if not triggered:
183
                continue
184
185
            # Remove movie from `pending` set
186
            self.p_shows_pending.remove(pk)
187
188
        # Stop progress group
189
        self.current.progress.group(Shows, 'missing:shows').stop()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
190
191
        self.log_pending('Unable to process %d show(s)\n%s', self.p_shows_pending)
192
193
    #
194
    # Episodes
195
    #
196
197
    @elapsed.clock
198
    def process_matched_episodes(self):
199
        # Iterate over plex episodes
200
        for ids, p_guid, (season_num, episode_num), p_show, p_season, p_episode in self.p_episodes:
0 ignored issues
show
Unused Code introduced by
The variable p_season seems to be unused.
Loading history...
201
            # Increment one step
202
            self.current.progress.group(Shows, 'matched:episodes').step()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
203
204
            # Ensure `p_guid` is available
205
            if not p_guid or p_guid.agent not in GUID_AGENTS:
206
                mark_unsupported(self.p_shows_unsupported, ids['show'], p_guid, p_show)
207
                continue
208
209
            key = (p_guid.agent, p_guid.sid)
210
            identifier = (season_num, episode_num)
211
212
            # Try retrieve `pk` for `key`
213
            pk = self.trakt.table.get(key)
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named trakt.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
214
215
            with elapsed.clock(Shows, 'run:plex_episodes:execute_handlers'):
216
                for data in self.get_data(SyncMedia.Episodes):
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named get_data.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
217
                    with elapsed.clock(Shows, 'run:plex_episodes:t_objects'):
218
                        t_show, t_season, t_episode = self.t_objects(
0 ignored issues
show
Unused Code introduced by
The variable t_season seems to be unused.
Loading history...
219 1
                            self.trakt[(SyncMedia.Episodes, data)], pk,
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named trakt.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
220
                            season_num, episode_num
221
                        )
222
223
                    # Execute episode handlers
224
                    self.execute_handlers(
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named execute_handlers.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
225
                        SyncMedia.Episodes, data,
226
227
                        key=ids['episode'],
228
                        identifier=identifier,
229
230
                        p_guid=p_guid,
231
                        p_show=p_show,
232
                        p_item=p_episode,
233
234
                        t_show=t_show,
235
                        t_item=t_episode
236
                    )
237
238
            # Remove episode from `pending_episodes`
239
            if pk in self.p_episodes_pending and identifier in self.p_episodes_pending[pk]:
240
                self.p_episodes_pending[pk].remove(identifier)
241
242
            # Task checkpoint
243
            self.checkpoint()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named checkpoint.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
244
245
        # Stop progress group
246
        self.current.progress.group(Shows, 'matched:episodes').stop()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
247
248
    @elapsed.clock
249
    def process_missing_episodes(self):
250
        # Increment progress steps
251
        self.current.progress.group(Shows, 'missing:episodes').add(len(self.p_episodes_pending))
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
252
253
        # Iterate over trakt episodes (that aren't in plex)
254
        for pk, episodes in [(p, list(e)) for (p, e) in self.p_episodes_pending.items()]:
255
            # Increment one step
256
            self.current.progress.group(Shows, 'missing:episodes').step()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
257
258
            # Iterate over trakt episodes (that aren't in plex)
259
            for identifier in episodes:
260
                # Iterate over data handlers
261
                season_num, episode_num = identifier
262
                triggered = False
263
264
                for data in self.get_data(SyncMedia.Episodes):
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named get_data.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
265
                    if data not in [SyncData.Collection]:
266
                        continue
267
268
                    # Retrieve episode
269
                    t_show, t_season, t_episode = self.t_objects(
0 ignored issues
show
Unused Code introduced by
The variable t_season seems to be unused.
Loading history...
270
                        self.trakt[(SyncMedia.Episodes, data)], pk,
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named trakt.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
271
                        season_num, episode_num
272
                    )
273
274
                    if not t_episode:
275
                        continue
276
277
                    log.debug('Found episode missing from plex: %r - %r [data: %r]', pk, identifier, SyncData.title(data))
0 ignored issues
show
Coding Style introduced by
This line is too long as per the coding-style (122/120).

This check looks for lines that are too long. You can specify the maximum line length.

Loading history...
278
279
                    # Trigger handler
280
                    self.execute_handlers(
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named execute_handlers.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
281
                        SyncMedia.Episodes, data,
282
                        key=None,
283
                        identifier=identifier,
284
                        p_guid=Guid(*pk),
285
286
                        p_show=None,
287
                        p_item=None,
288
289
                        t_show=t_show,
290
                        t_item=t_episode
291
                    )
292
293
                    # Mark triggered
294
                    triggered = True
295
296
                # Check if action was triggered
297
                if not triggered:
298
                    continue
299
300
                # Remove movie from `pending` set
301
                self.p_episodes_pending[pk].remove(identifier)
302
303
        # Stop progress group
304
        self.current.progress.group(Shows, 'missing:episodes').stop()
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named current.

This check looks for calls to members that are non-existent. These calls will fail.

The member could have been renamed or removed.

Loading history...
305
306
        self.log_pending('Unable to process %d episode(s)\n%s', self.p_episodes_pending)
307
308
    @staticmethod
309
    def t_objects(collection, pk, season_num, episode_num):
310
        # Try find trakt `Show` from `collection`
311
        t_show = collection.get(pk)
312
313
        if t_show is None:
314
            return t_show, None, None
315
316
        # Try find trakt `Season`
317
        t_season = t_show.seasons.get(season_num)
318
319
        if t_season is None:
320
            return t_show, t_season, None
321
322
        # Try find trakt `Episode`
323
        t_episode = t_season.episodes.get(episode_num)
324
325
        return t_show, t_season, t_episode
326