Passed
Push — master ( 66020a...b25270 )
by Dean
03:03
created

Lists.process()   C

Complexity

Conditions 7

Size

Total Lines 34

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 1
CRAP Score 46.2357
Metric Value
cc 7
dl 0
loc 34
ccs 1
cts 14
cp 0.0714
crap 46.2357
rs 5.5
1 1
from plugin.sync.core.enums import SyncMedia
2 1
from plugin.sync.core.playlist.mapper import PlaylistMapper
3 1
from plugin.sync.modes.core.base import PullListsMode
4
5 1
from trakt_sync.cache.main import Cache
6 1
import logging
7
8 1
log = logging.getLogger(__name__)
9
10
11 1
class Lists(PullListsMode):
0 ignored issues
show
Coding Style introduced by
This class has no __init__ method.
Loading history...
12 1
    def process(self, data, p_playlists, p_sections_map):
13
        # Iterate over trakt list changes
14
        for key, result in self.get_changed_lists(data):
15
            if 'lists' not in result.changes:
16
                log.warn('Unable to find "lists" key in changes: %r', result.changes)
17
                continue
18
19
            for action, t_items in result.changes['lists'].items():
20
                for t_list_id, t_item in t_items.items():
0 ignored issues
show
Unused Code introduced by
The variable t_item seems to be unused.
Loading history...
21
                    # Try retrieve trakt list
22
                    t_list = self.trakt[key].get(t_list_id)
0 ignored issues
show
Bug introduced by
The Instance of Lists 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...
23
24
                    # Execute handlers for list
25
                    self.execute_handlers(
0 ignored issues
show
Bug introduced by
The Instance of Lists 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...
26
                        SyncMedia.Lists, data,
27
                        action=action,
28
29
                        p_playlists=p_playlists,
30
31
                        key=t_list_id,
32
33
                        t_list=t_list
34
                    )
35
36
                    if action == 'removed':
37
                        # No changes to list items required
38
                        continue
39
40
                    if not t_list:
41
                        # List was removed
42
                        continue
43
44
                    # Process list items
45
                    self.process_list(action, data, p_playlists, p_sections_map, t_list)
46
47 1
    def process_list(self, action, data, p_playlists, p_sections_map, t_list):
48
        log.debug('Processing list: %r', t_list)
49
50
        # Create/retrieve plex list
51
        p_playlist = self.get_playlist(
52
            p_playlists,
53
            uri='trakt://list/%s/%s' % (self.current.account.id, t_list.id),
0 ignored issues
show
Bug introduced by
The Instance of Lists 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
            title=t_list.name
55
        )
56
57
        if not p_playlist:
58
            log.warn('Unable to create/retrieve playlist with name: %r', t_list.name)
59
            return
60
61
        # Retrieve trakt list items from cache
62
        t_list_items = self.trakt[(SyncMedia.Lists, data, t_list.id)]
0 ignored issues
show
Bug introduced by
The Instance of Lists 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...
63
64
        if t_list_items is None:
65
            log.warn('Unable to retrieve list items for: %r', t_list)
66
            return
67
68
        # Update (add/remove) list items
69
        if action == 'added':
70
            self.update_full(data, p_playlist, p_sections_map, t_list, t_list_items.itervalues())
71
        elif action == 'changed':
72
            self.update_changed(data, p_playlist, p_sections_map, t_list, t_list_items.itervalues())
73
        else:
74
            log.warn('Unsupported action for process(): %r', action)
75
            return
76
77
        # TODO Sort list items
0 ignored issues
show
Coding Style introduced by
TODO and FIXME comments should generally be avoided.
Loading history...
78
        # self.process_sort(data, p_playlist, p_sections_map, t_list, t_list_items.itervalues())
79
80 1
    def update_changed(self, data, p_playlist, p_sections_map, t_list=None, t_list_items=None):
81
        # Retrieve changed items
82
        t_changes = self.get_changed_items(data)
83
84
        if not t_changes:
85
            log.debug('No changes detected in %r collection', data)
86
            return
87
88
        # Construct playlist mapper
89
        mapper = PlaylistMapper(self.current, p_sections_map)
0 ignored issues
show
Bug introduced by
The Instance of Lists 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...
90
91
        # Parse plex playlist items
92
        mapper.plex.load(p_playlist)
93
94
        # Parse trakt list items
95
        mapper.trakt.load(t_list, t_list_items)
96
97
        # Match playlist items and expand shows/seasons
98
        m_trakt, m_plex = mapper.match()
99
100
        log.debug(
101
            'Update - Mapper Result (%d items)\nt_items:\n%s\n\np_items:\n%s',
102
            len(m_trakt) + len(m_plex),
103
            '\n'.join(self.format_mapper_result(m_trakt)),
104
            '\n'.join(self.format_mapper_result(m_plex))
105
        )
106
107
        log.debug(
108
            'Update - Changes (%d keys)\n%s',
109
            len(t_changes),
110
            '\n'.join(self.format_changes(t_changes)),
111
        )
112
113
        # Iterate over matched trakt items
114
        for key, index, (p_index, p_items), (t_index, t_items) in m_trakt:
0 ignored issues
show
Unused Code introduced by
The variable index seems to be unused.
Loading history...
Unused Code introduced by
The variable p_index seems to be unused.
Loading history...
Unused Code introduced by
The variable t_index seems to be unused.
Loading history...
115
            # Expand shows/seasons into episodes
116
            for p_item, t_item in self.expand(p_items, t_items):
117
                if not t_item:
118
                    continue
119
120
                if len(key) < 1:
121
                    log.warn('Invalid "key" format: %r', key)
122
                    continue
123
124
                actions = list(t_changes.get(key[0], []))
125
126
                if not actions:
127
                    continue
128
129
                if len(actions) > 1:
130
                    log.warn('Multiple actions returned for %r: %r', key[0], actions)
131
                    continue
132
133
                # Get `SyncMedia` for `t_item`
134
                media = self.get_media(t_item)
135
136
                if media is None:
137
                    log.warn('Unable to identify media of "t_item" (p_item: %r, t_item: %r)', p_item, t_item)
138
                    continue
139
140
                # Execute handler
141
                self.execute_handlers(
0 ignored issues
show
Bug introduced by
The Instance of Lists 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...
142
                    media, data,
143
144
                    action=actions[0],
145
146
                    p_sections_map=p_sections_map,
147
                    p_playlist=p_playlist,
148
149
                    key=key,
150
151
                    p_item=p_item,
152
                    t_item=t_item
153
                )
154
155 1
    def update_full(self, data, p_playlist, p_sections_map, t_list=None, t_list_items=None):
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
156
        # Construct playlist mapper
157
        mapper = PlaylistMapper(self.current, p_sections_map)
0 ignored issues
show
Bug introduced by
The Instance of Lists 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
        # Parse plex playlist items
160
        mapper.plex.load(p_playlist)
161
162
        # Parse trakt list items
163
        mapper.trakt.load(t_list, t_list_items)
164
165
        # Match playlist items and expand shows/seasons
166
        m_trakt, m_plex = mapper.match()
167
168
        log.debug(
169
            'Update - Mapper Result (%d items)\nt_items:\n%s\n\np_items:\n%s',
170
            len(m_trakt) + len(m_plex),
171
            '\n'.join(self.format_mapper_result(m_trakt)),
172
            '\n'.join(self.format_mapper_result(m_plex))
173
        )
174
175
        # Iterate over matched trakt items
176
        for key, index, (p_index, p_items), (t_index, t_items) in m_trakt:
0 ignored issues
show
Unused Code introduced by
The variable index seems to be unused.
Loading history...
Unused Code introduced by
The variable p_index seems to be unused.
Loading history...
Unused Code introduced by
The variable t_index seems to be unused.
Loading history...
177
            # Expand shows/seasons into episodes
178
            for p_item, t_item in self.expand(p_items, t_items):
179
                if not t_item:
180
                    continue
181
182
                # Get `SyncMedia` for `t_item`
183
                media = self.get_media(t_item)
184
185
                if media is None:
186
                    log.warn('Unable to identify media of "t_item" (p_item: %r, t_item: %r)', p_item, t_item)
187
                    continue
188
189
                # Execute handler
190
                self.execute_handlers(
0 ignored issues
show
Bug introduced by
The Instance of Lists 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...
191
                    media, data,
192
193
                    p_sections_map=p_sections_map,
194
                    p_playlist=p_playlist,
195
196
                    key=key,
197
198
                    p_item=p_item,
199
                    t_item=t_item
200
                )
201
202 1
    def get_changed_lists(self, data, extra=None):
203
        for key, result in self.trakt.changes:
0 ignored issues
show
Bug introduced by
The Instance of Lists 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...
204
            m, d = key[0:2]
205
206
            if len(key) > 2:
207
                e = key[2:]
208
            else:
209
                e = None
210
211
            if m != SyncMedia.Lists:
212
                continue
213
214
            if d != data:
215
                continue
216
217
            if extra is True and e is None:
218
                continue
219
            elif e != extra:
220
                continue
221
222
            yield key, result
223
224 1
    def get_changed_items(self, data):
225
        changes = {}
226
227
        for key, result in self.trakt.changes:
0 ignored issues
show
Bug introduced by
The Instance of Lists 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...
228
            m, d = key[0:2]
0 ignored issues
show
Unused Code introduced by
The variable m seems to be unused.
Loading history...
229
230
            if d != data:
231
                # Ignore non-watchlist data
232
                continue
233
234
            if not self.is_data_enabled(d):
0 ignored issues
show
Bug introduced by
The Instance of Lists does not seem to have a member named is_data_enabled.

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
                # Data type has been disabled
236
                continue
237
238
            data_name = Cache.Data.get(d)
239
240
            if data_name not in result.changes:
241
                # No changes for collection
242
                continue
243
244
            for action, t_items in result.changes[data_name].items():
245
                for guid, t_item in t_items.items():
0 ignored issues
show
Unused Code introduced by
The variable t_item seems to be unused.
Loading history...
246
                    if guid not in changes:
247
                        changes[guid] = set()
248
249
                    changes[guid].add(action)
250
251
        return changes
252