Passed
Push — beta ( 8befa3...d680d6 )
by Dean
06:01 queued 03:09
created

Shows.process_matched_shows()   B

Complexity

Conditions 6

Size

Total Lines 42

Duplication

Lines 42
Ratio 100 %

Code Coverage

Tests 1
CRAP Score 35.6629

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 42
loc 42
ccs 1
cts 16
cp 0.0625
rs 7.5384
cc 6
crap 35.6629
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
0 ignored issues
show
Bug introduced by
The name base does not seem to exist in module plugin.sync.modes.push.
Loading history...
Configuration introduced by
Unable to import 'plugin.sync.modes.push.base' (invalid syntax (<string>, line 37))

This can be caused by one of the following:

1. Missing Dependencies

This error could indicate a configuration issue of Pylint. Make sure that your libraries are available by adding the necessary commands.

# .scrutinizer.yml
before_commands:
    - sudo pip install abc # Python2
    - sudo pip3 install abc # Python3
Tip: We are currently not using virtualenv to run pylint, when installing your modules make sure to use the command for the correct version.

2. Missing __init__.py files

This error could also result from missing __init__.py files in your module folders. Make sure that you place one file in each sub-folder.

Loading history...
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)', 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 View Code Duplication
    @elapsed.clock
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.
Loading history...
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
        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...
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(
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named log_pending.

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...
205
            log, 'Unable to find %d show(s) in Plex, list has been saved to: %s',
206
            self.current.account, 'shows', 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...
207
        )
208
209
    #
210
    # Episodes
211
    #
212
213 1
    @elapsed.clock
214
    def process_matched_episodes(self):
215
        # Iterate over plex episodes
216
        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...
217
            # Increment one step
218
            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...
219
220
            # Process `p_guid` (map + validate)
221
            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...
222
223
            if not supported:
224
                mark_unsupported(self.p_shows_unsupported, ids['show'], p_guid)
225
                continue
226
227
            key = (p_guid.service, p_guid.id)
228
            identifier = (season_num, episode_num)
229
230
            # Try retrieve `pk` for `key`
231
            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...
232
233
            with elapsed.clock(Shows, 'run:plex_episodes:execute_handlers'):
234
                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...
235
                    with elapsed.clock(Shows, 'run:plex_episodes:t_objects'):
236
                        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...
237
                            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...
238
                            season_num, episode_num
239
                        )
240
241
                    # Execute episode handlers
242
                    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...
243
                        SyncMedia.Episodes, data,
244
245
                        key=ids['episode'],
246
                        identifier=identifier,
247
248
                        guid=p_guid,
249
                        p_show=p_show,
250
                        p_item=p_episode,
251
252
                        t_show=t_show,
253
                        t_item=t_episode
254
                    )
255
256
            # Remove episode from `pending_episodes`
257
            if pk in self.p_episodes_pending and identifier in self.p_episodes_pending[pk]:
258
                self.p_episodes_pending[pk].remove(identifier)
259
260
            # Task checkpoint
261
            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...
262
263
        # Stop progress group
264
        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...
265
266 1
    @elapsed.clock
267
    def process_missing_episodes(self):
268
        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...
269
            # Collection cleaning disabled for individual syncs
270
            return
271
272
        # Increment progress steps
273
        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...
274
275
        # Iterate over trakt episodes (that aren't in plex)
276
        for pk, episodes in [(p, list(e)) for (p, e) in self.p_episodes_pending.items()]:
277
            # Increment one step
278
            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...
279
280
            # Iterate over trakt episodes (that aren't in plex)
281
            for identifier in episodes:
282
                # Iterate over data handlers
283
                season_num, episode_num = identifier
284
                triggered = False
285
286
                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...
287
                    if data not in [SyncData.Collection]:
288
                        continue
289
290
                    # Retrieve episode
291
                    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...
292
                        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...
293
                        season_num, episode_num
294
                    )
295
296
                    if not t_episode:
297
                        continue
298
299
                    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...
300
301
                    # Trigger handler
302
                    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...
303
                        SyncMedia.Episodes, data,
304
                        key=None,
305
                        identifier=identifier,
306
                        guid=Guid.construct(*pk),
307
308
                        p_show=None,
309
                        p_item=None,
310
311
                        t_show=t_show,
312
                        t_item=t_episode
313
                    )
314
315
                    # Mark triggered
316
                    triggered = True
317
318
                # Check if action was triggered
319
                if not triggered:
320
                    continue
321
322
                # Remove movie from `pending` set
323
                self.p_episodes_pending[pk].remove(identifier)
324
325
        # Stop progress group
326
        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...
327
328
        self.log_pending(
0 ignored issues
show
Bug introduced by
The Instance of Shows does not seem to have a member named log_pending.

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...
329
            log, 'Unable to find %d episode(s) in Plex, list has been saved to: %s',
330
            self.current.account, 'episodes', 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...
331
        )
332
333 1
    @staticmethod
334
    def t_objects(collection, pk, season_num, episode_num):
335
        # Try find trakt `Show` from `collection`
336
        t_show = collection.get(pk)
337
338
        if t_show is None:
339
            return t_show, None, None
340
341
        # Try find trakt `Season`
342
        t_season = t_show.seasons.get(season_num)
343
344
        if t_season is None:
345
            return t_show, t_season, None
346
347
        # Try find trakt `Episode`
348
        t_episode = t_season.episodes.get(episode_num)
349
350
        return t_show, t_season, t_episode
351