Test Setup Failed
Push — develop ( e459d6...12ef70 )
by Dean
02:19
created

Shows.process_missing_episodes()   D

Complexity

Conditions 9

Size

Total Lines 63

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 79.8826
Metric Value
cc 9
dl 0
loc 63
ccs 1
cts 23
cp 0.0434
crap 79.8826
rs 4.7173

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 1
    @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 1
    @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 1
    @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 1
    @elapsed.clock
101
    def process_matched_shows(self):
102
        # Iterate over plex shows
103
        for sh_id, 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 `guid` is available
108
            if not guid or guid.agent not in GUID_AGENTS:
109
                mark_unsupported(self.p_shows_unsupported, sh_id, guid, p_show)
110
                continue
111
112
            key = (guid.agent, 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
                    guid=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 1
    @elapsed.clock
142
    def process_missing_shows(self):
143
        if self.current.kwargs.get('section'):
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...
144
            # Collection cleaning disabled for individual syncs
145
            return
146
147
        # Increment progress steps
148
        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...
149
150
        # Iterate over trakt shows (that aren't in plex)
151
        for pk in list(self.p_shows_pending):
152
            # Increment one step
153
            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...
154
155
            # Iterate over data handlers
156
            triggered = False
157
158
            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...
159
                if data not in [SyncData.Collection]:
160
                    continue
161
162
                # Retrieve show
163
                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...
164
165
                if not t_show:
166
                    continue
167
168
                log.debug('Found show missing from plex: %r [data: %r]', pk, SyncData.title(data))
169
170
                # Trigger handler
171
                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...
172
                    SyncMedia.Shows, data,
173
174
                    key=None,
175
176
                    guid=Guid(*pk),
177
                    p_item=None,
178
179
                    t_item=t_show
180
                )
181
182
                # Mark triggered
183
                triggered = True
184
185
            # Check if action was triggered
186
            if not triggered:
187
                continue
188
189
            # Remove movie from `pending` set
190
            self.p_shows_pending.remove(pk)
191
192
        # Stop progress group
193
        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...
194
195
        self.log_pending('Unable to process %d show(s)\n%s', self.p_shows_pending)
196
197 1
    #
198
    # Episodes
199
    #
200
201
    @elapsed.clock
202
    def process_matched_episodes(self):
203
        # Iterate over plex episodes
204
        for ids, 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...
205
            # Increment one step
206
            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...
207
208
            # Ensure `guid` is available
209
            if not guid or guid.agent not in GUID_AGENTS:
210
                mark_unsupported(self.p_shows_unsupported, ids['show'], guid, p_show)
211
                continue
212
213
            key = (guid.agent, guid.sid)
214
            identifier = (season_num, episode_num)
215
216
            # Try retrieve `pk` for `key`
217
            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...
218
219
            with elapsed.clock(Shows, 'run:plex_episodes:execute_handlers'):
220
                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...
221
                    with elapsed.clock(Shows, 'run:plex_episodes:t_objects'):
222
                        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...
223
                            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...
224
                            season_num, episode_num
225
                        )
226
227
                    # Execute episode handlers
228
                    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...
229
                        SyncMedia.Episodes, data,
230
231
                        key=ids['episode'],
232
                        identifier=identifier,
233
234
                        guid=guid,
235
                        p_show=p_show,
236
                        p_item=p_episode,
237
238
                        t_show=t_show,
239
                        t_item=t_episode
240
                    )
241
242
            # Remove episode from `pending_episodes`
243
            if pk in self.p_episodes_pending and identifier in self.p_episodes_pending[pk]:
244
                self.p_episodes_pending[pk].remove(identifier)
245
246
            # Task checkpoint
247
            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...
248 1
249
        # Stop progress group
250
        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...
251
252
    @elapsed.clock
253
    def process_missing_episodes(self):
254
        if self.current.kwargs.get('section'):
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...
255
            # Collection cleaning disabled for individual syncs
256
            return
257
258
        # Increment progress steps
259
        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...
260
261
        # Iterate over trakt episodes (that aren't in plex)
262
        for pk, episodes in [(p, list(e)) for (p, e) in self.p_episodes_pending.items()]:
263
            # Increment one step
264
            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...
265
266
            # Iterate over trakt episodes (that aren't in plex)
267
            for identifier in episodes:
268
                # Iterate over data handlers
269
                season_num, episode_num = identifier
270
                triggered = False
271
272
                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...
273
                    if data not in [SyncData.Collection]:
274
                        continue
275
276
                    # Retrieve episode
277
                    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...
278
                        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...
279
                        season_num, episode_num
280
                    )
281
282
                    if not t_episode:
283
                        continue
284
285
                    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...
286
287
                    # Trigger handler
288
                    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...
289
                        SyncMedia.Episodes, data,
290
                        key=None,
291
                        identifier=identifier,
292
                        guid=Guid(*pk),
293
294
                        p_show=None,
295
                        p_item=None,
296
297
                        t_show=t_show,
298
                        t_item=t_episode
299
                    )
300
301
                    # Mark triggered
302
                    triggered = True
303
304
                # Check if action was triggered
305
                if not triggered:
306
                    continue
307
308 1
                # Remove movie from `pending` set
309
                self.p_episodes_pending[pk].remove(identifier)
310
311
        # Stop progress group
312
        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...
313
314
        self.log_pending('Unable to process %d episode(s)\n%s', self.p_episodes_pending)
315
316
    @staticmethod
317
    def t_objects(collection, pk, season_num, episode_num):
318
        # Try find trakt `Show` from `collection`
319
        t_show = collection.get(pk)
320
321
        if t_show is None:
322
            return t_show, None, None
323
324
        # Try find trakt `Season`
325
        t_season = t_show.seasons.get(season_num)
326
327
        if t_season is None:
328
            return t_show, t_season, None
329
330
        # Try find trakt `Episode`
331
        t_episode = t_season.episodes.get(episode_num)
332
333
        return t_show, t_season, t_episode
334