Passed
Push — beta ( 91a9ed...2462f8 )
by Dean
02:58
created

Shows.process_matched_episodes()   C

Complexity

Conditions 8

Size

Total Lines 52

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 62.4227

Importance

Changes 2
Bugs 0 Features 0
Metric Value
dl 0
loc 52
ccs 1
cts 19
cp 0.0526
rs 5.5452
c 2
b 0
f 0
cc 8
crap 62.4227

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.core.constants import GUID_SERVICES
0 ignored issues
show
Unused Code introduced by
Unused GUID_SERVICES imported from plugin.core.constants
Loading history...
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
    data = [
17
        SyncData.Collection,
18
        SyncData.Playback,
19
        SyncData.Ratings,
20
        SyncData.Watched
21
    ]
22
23 1
    def __init__(self, task):
24
        super(Shows, self).__init__(task)
25
26
        # Sections
27
        self.p_sections = None
28
        self.p_sections_map = None
29
30
        # Shows
31
        self.p_shows = None
32
        self.p_shows_count = None
33
        self.p_shows_pending = None
34
        self.p_shows_unsupported = None
35
36
        # Seasons
37
        self.p_seasons = None
38
39
        # Episodes
40
        self.p_episodes = None
41
        self.p_episodes_count = None
42
        self.p_episodes_pending = None
43
44 1
    @elapsed.clock
45
    def construct(self):
46
        # Retrieve movie sections
47
        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...
48
49
        # Determine number of shows that will be processed
50
        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...
51
            self.p_sections
52
        )
53
54
        # Determine number of shows that will be processed
55
        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...
56
            self.p_sections
57
        )
58
59
        # Increment progress steps total
60
        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...
61
        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...
62
        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...
63
        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...
64
65 1
    @elapsed.clock
66
    def start(self):
67
        # Fetch movies with account settings
68
        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...
69
            self.p_sections, ([
70
                MetadataItem.title,
71
                MetadataItem.year
72
            ], [], [
73
                MediaItem.audio_channels,
74
                MediaItem.audio_codec,
75
                MediaItem.height,
76
                MediaItem.interlaced,
77
78
                Episode.added_at
79
            ]),
80
            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...
81
            parse_guid=True
82
        )
83
84
        # Reset state
85
        self.p_shows_pending = self.trakt.table.show_keys.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...
86
        self.p_shows_unsupported = {}
87
88
        self.p_episodes_pending = copy.deepcopy(self.trakt.table.episode_keys)
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...
89
90 1
    @elapsed.clock
91
    def run(self):
92
        # Process matched items
93
        self.process_matched_shows()
94
        self.process_matched_episodes()
95
96
        # Report unsupported shows
97
        log_unsupported(log, 'Found %d unsupported show(s)\n%s', self.p_shows_unsupported)
98
99
        # Process missing items
100
        self.process_missing_shows()
101
        self.process_missing_episodes()
102
103
    #
104
    # Shows
105
    #
106
107 1
    @elapsed.clock
108
    def process_matched_shows(self):
109
        # Iterate over plex shows
110
        for sh_id, p_guid, p_show in self.p_shows:
111
            # Increment one step
112
            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...
113
114
            # Process `p_guid` (map + validate)
115
            supported, p_guid = self.process_guid(p_guid)
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named process_guid.

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
            if not supported:
118
                mark_unsupported(self.p_shows_unsupported, sh_id, p_guid)
119
                continue
120
121
            key = (p_guid.service, p_guid.id)
122
123
            # Try retrieve `pk` for `key`
124
            pk = self.trakt.table('shows').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...
125
126
            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...
127
                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...
128
129
                # Execute show handlers
130
                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...
131
                    SyncMedia.Shows, data,
132
                    key=sh_id,
133
                    guid=p_guid,
134
135
                    p_item=p_show,
136
137
                    t_item=t_show
138
                )
139
140
            # Remove show from `pending_shows`
141
            if pk and pk in self.p_shows_pending:
142
                self.p_shows_pending.remove(pk)
143
144
            # Task checkpoint
145
            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...
146
147
        # Stop progress group
148 View Code Duplication
        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...
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
149
150 1
    @elapsed.clock
151
    def process_missing_shows(self):
152
        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...
153
            # Collection cleaning disabled for individual syncs
154
            return
155
156
        # Increment progress steps
157
        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...
158
159
        # Iterate over trakt shows (that aren't in plex)
160
        for pk in list(self.p_shows_pending):
161
            # Increment one step
162
            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...
163
164
            # Iterate over data handlers
165
            triggered = False
166
167
            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...
168
                if data not in [SyncData.Collection]:
169
                    continue
170
171
                # Retrieve show
172
                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...
173
174
                if not t_show:
175
                    continue
176
177
                log.debug('Found show missing from plex: %r [data: %r]', pk, SyncData.title(data))
178
179
                # Trigger handler
180
                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...
181
                    SyncMedia.Shows, data,
182
183
                    key=None,
184
185
                    guid=Guid.construct(*pk),
186
                    p_item=None,
187
188
                    t_item=t_show
189
                )
190
191
                # Mark triggered
192
                triggered = True
193
194
            # Check if action was triggered
195
            if not triggered:
196
                continue
197
198
            # Remove movie from `pending` set
199
            self.p_shows_pending.remove(pk)
200
201
        # Stop progress group
202
        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...
203
204
        self.log_pending('Unable to find %d show(s) in Plex\n%s', self.p_shows_pending)
205
206
    #
207
    # Episodes
208
    #
209
210 1
    @elapsed.clock
211
    def process_matched_episodes(self):
212
        # Iterate over plex episodes
213
        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...
214
            # Increment one step
215
            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...
216
217
            # Process `p_guid` (map + validate)
218
            supported, p_guid, season_num, episode_num = self.process_guid_episode(p_guid, season_num, episode_num)
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named process_guid_episode.

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...
219
220
            if not supported:
221
                mark_unsupported(self.p_shows_unsupported, ids['show'], p_guid)
222
                continue
223
224
            key = (p_guid.service, p_guid.id)
225
            identifier = (season_num, episode_num)
226
227
            # Try retrieve `pk` for `key`
228
            pk = self.trakt.table('shows').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...
229
230
            with elapsed.clock(Shows, 'run:plex_episodes:execute_handlers'):
231
                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...
232
                    with elapsed.clock(Shows, 'run:plex_episodes:t_objects'):
233
                        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...
234
                            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...
235
                            season_num, episode_num
236
                        )
237
238
                    # Execute episode handlers
239
                    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...
240
                        SyncMedia.Episodes, data,
241
242
                        key=ids['episode'],
243
                        identifier=identifier,
244
245
                        guid=p_guid,
246
                        p_show=p_show,
247
                        p_item=p_episode,
248
249
                        t_show=t_show,
250
                        t_item=t_episode
251
                    )
252
253
            # Remove episode from `pending_episodes`
254
            if pk in self.p_episodes_pending and identifier in self.p_episodes_pending[pk]:
255
                self.p_episodes_pending[pk].remove(identifier)
256
257
            # Task checkpoint
258
            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...
259
260
        # Stop progress group
261
        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...
262
263 1
    @elapsed.clock
264
    def process_missing_episodes(self):
265
        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...
266
            # Collection cleaning disabled for individual syncs
267
            return
268
269
        # Increment progress steps
270
        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...
271
272
        # Iterate over trakt episodes (that aren't in plex)
273
        for pk, episodes in [(p, list(e)) for (p, e) in self.p_episodes_pending.items()]:
274
            # Increment one step
275
            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...
276
277
            # Iterate over trakt episodes (that aren't in plex)
278
            for identifier in episodes:
279
                # Iterate over data handlers
280
                season_num, episode_num = identifier
281
                triggered = False
282
283
                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...
284
                    if data not in [SyncData.Collection]:
285
                        continue
286
287
                    # Retrieve episode
288
                    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...
289
                        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...
290
                        season_num, episode_num
291
                    )
292
293
                    if not t_episode:
294
                        continue
295
296
                    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...
297
298
                    # Trigger handler
299
                    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...
300
                        SyncMedia.Episodes, data,
301
                        key=None,
302
                        identifier=identifier,
303
                        guid=Guid.construct(*pk),
304
305
                        p_show=None,
306
                        p_item=None,
307
308
                        t_show=t_show,
309
                        t_item=t_episode
310
                    )
311
312
                    # Mark triggered
313
                    triggered = True
314
315
                # Check if action was triggered
316
                if not triggered:
317
                    continue
318
319
                # Remove movie from `pending` set
320
                self.p_episodes_pending[pk].remove(identifier)
321
322
        # Stop progress group
323
        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...
324
325
        self.log_pending('Unable to find %d episode(s) in Plex\n%s', self.p_episodes_pending)
326
327 1
    @staticmethod
328
    def t_objects(collection, pk, season_num, episode_num):
329
        # Try find trakt `Show` from `collection`
330
        t_show = collection.get(pk)
331
332
        if t_show is None:
333
            return t_show, None, None
334
335
        # Try find trakt `Season`
336
        t_season = t_show.seasons.get(season_num)
337
338
        if t_season is None:
339
            return t_show, t_season, None
340
341
        # Try find trakt `Episode`
342
        t_episode = t_season.episodes.get(episode_num)
343
344
        return t_show, t_season, t_episode
345