1
|
1 |
|
from plugin.sync.core.enums import SyncMode |
2
|
|
|
|
3
|
1 |
|
import inspect |
4
|
1 |
|
import logging |
5
|
|
|
|
6
|
1 |
|
log = logging.getLogger(__name__) |
7
|
|
|
|
8
|
|
|
|
9
|
1 |
|
class MediaHandler(object): |
10
|
1 |
|
media = None |
11
|
|
|
|
12
|
1 |
|
def __init__(self, data, task): |
13
|
1 |
|
self.__parent = data |
14
|
1 |
|
self.__task = task |
15
|
|
|
|
16
|
1 |
|
self.__handlers = {} |
17
|
|
|
|
18
|
1 |
|
@property |
19
|
|
|
def configuration(self): |
20
|
1 |
|
return self.__task.configuration |
21
|
|
|
|
22
|
1 |
|
@property |
23
|
|
|
def parent(self): |
24
|
1 |
|
return self.__parent |
25
|
|
|
|
26
|
1 |
|
def discover(self): |
27
|
1 |
|
for key in dir(self): |
28
|
1 |
|
if key.startswith('_'): |
29
|
1 |
|
continue |
30
|
|
|
|
31
|
|
|
# Retrieve function |
32
|
1 |
|
try: |
33
|
1 |
|
func = getattr(self, key) |
34
|
|
|
except Exception: |
|
|
|
|
35
|
|
|
continue |
36
|
|
|
|
37
|
1 |
|
if not func or not inspect.ismethod(func): |
38
|
1 |
|
continue |
39
|
|
|
|
40
|
|
|
# Retrieve binding metadata |
41
|
1 |
|
binding = getattr(func, 'binding', None) |
42
|
|
|
|
43
|
1 |
|
if not binding: |
44
|
1 |
|
continue |
45
|
|
|
|
46
|
|
|
# Parse metadata, set defaults |
47
|
1 |
|
action = binding['action'] |
48
|
|
|
|
49
|
1 |
|
modes = binding['modes'] or [ |
50
|
|
|
SyncMode.FastPull, |
51
|
|
|
|
52
|
|
|
SyncMode.Pull, |
53
|
|
|
SyncMode.Push, |
54
|
|
|
|
55
|
|
|
SyncMode.Full |
56
|
|
|
] |
57
|
|
|
|
58
|
1 |
|
if not action or not modes: |
59
|
|
|
continue |
60
|
|
|
|
61
|
|
|
# Store callback in `__handlers` |
62
|
1 |
|
for mode in modes: |
63
|
1 |
|
if mode not in self.__handlers: |
64
|
1 |
|
self.__handlers[mode] = {} |
65
|
|
|
|
66
|
1 |
|
self.__handlers[mode][action] = func |
67
|
|
|
|
68
|
1 |
|
@property |
69
|
|
|
def current(self): |
70
|
1 |
|
return self.__task |
71
|
|
|
|
72
|
1 |
|
@property |
73
|
|
|
def handlers(self): |
74
|
1 |
|
return self.__task.handlers |
75
|
|
|
|
76
|
1 |
|
@staticmethod |
77
|
|
|
def build_action(*args, **kwargs): |
78
|
|
|
raise NotImplementedError |
79
|
|
|
|
80
|
1 |
|
@staticmethod |
81
|
|
|
def get_operands(p_item, t_item): |
82
|
|
|
raise NotImplementedError |
83
|
|
|
|
84
|
1 |
|
def run(self, mode, *args, **kwargs): |
85
|
|
|
if mode == SyncMode.FastPull: |
86
|
|
|
return self.fast_pull(*args, **kwargs) |
87
|
|
|
|
88
|
|
|
if mode == SyncMode.Full: |
89
|
|
|
return self.full(*args, **kwargs) |
90
|
|
|
|
91
|
|
|
if mode == SyncMode.Pull: |
92
|
|
|
return self.pull(*args, **kwargs) |
93
|
|
|
|
94
|
|
|
if mode == SyncMode.Push: |
95
|
|
|
return self.push(*args, **kwargs) |
96
|
|
|
|
97
|
|
|
log.warn('No handler found for action: %r', mode) |
98
|
|
|
|
99
|
1 |
|
def fast_pull(self, *args, **kwargs): |
100
|
|
|
raise NotImplementedError |
101
|
|
|
|
102
|
1 |
|
def full(self, *args, **kwargs): |
103
|
|
|
raise NotImplementedError |
104
|
|
|
|
105
|
1 |
|
def pull(self, *args, **kwargs): |
106
|
|
|
raise NotImplementedError |
107
|
|
|
|
108
|
1 |
|
def push(self, *args, **kwargs): |
109
|
|
|
raise NotImplementedError |
110
|
|
|
|
111
|
|
|
# |
112
|
|
|
# Action handlers |
113
|
|
|
# |
114
|
|
|
|
115
|
1 |
|
def execute_actions(self, changes, key, p_settings): |
116
|
|
|
for action, t_items in changes.items(): |
117
|
|
|
if key not in t_items: |
118
|
|
|
continue |
119
|
|
|
|
120
|
|
|
self.execute_action( |
121
|
|
|
action, |
122
|
|
|
key=key, |
123
|
|
|
p_settings=p_settings, |
124
|
|
|
t_item=t_items[key] |
125
|
|
|
) |
126
|
|
|
|
127
|
1 |
|
def execute_action(self, action, **kwargs): |
128
|
|
|
# Find matching function |
129
|
|
|
func = self.__handlers.get(self.current.mode, {}).get(action) |
130
|
|
|
|
131
|
|
|
if func is None: |
132
|
|
|
#log.debug('Unable to find handler for mode %r, action %r', self.current.mode, action) |
133
|
|
|
return False |
134
|
|
|
|
135
|
|
|
# Execute action |
136
|
|
|
parameters = self.build_action( |
137
|
|
|
action=action, |
138
|
|
|
**kwargs |
139
|
|
|
) |
140
|
|
|
|
141
|
|
|
if parameters is None: |
142
|
|
|
return False |
143
|
|
|
|
144
|
|
|
return func(**parameters) |
145
|
|
|
|
146
|
1 |
|
def get_action(self, p_value, t_value): |
147
|
|
|
raise NotImplementedError |
148
|
|
|
|
149
|
1 |
|
def on_added(self, *args, **kwargs): |
150
|
|
|
raise NotImplementedError |
151
|
|
|
|
152
|
1 |
|
def on_removed(self, *args, **kwargs): |
153
|
|
|
raise NotImplementedError |
154
|
|
|
|
155
|
1 |
|
def on_changed(self, *args, **kwargs): |
156
|
|
|
raise NotImplementedError |
157
|
|
|
|
158
|
|
|
# |
159
|
|
|
# Artifacts |
160
|
|
|
# |
161
|
|
|
|
162
|
1 |
|
def store_show(self, action, guid, p_key=None, p_show=None, **kwargs): |
163
|
|
|
return self.current.artifacts.store_show( |
164
|
|
|
self.parent.data, action, guid, |
165
|
|
|
p_key=p_key, |
166
|
|
|
p_show=p_show, |
167
|
|
|
**kwargs |
168
|
|
|
) |
169
|
|
|
|
170
|
1 |
|
def store_episode(self, action, guid, identifier, p_key=None, p_show=None, p_episode=None, **kwargs): |
171
|
1 |
|
return self.current.artifacts.store_episode( |
172
|
|
|
self.parent.data, action, guid, identifier, |
173
|
|
|
p_key=p_key, |
174
|
|
|
p_show=p_show, |
175
|
|
|
p_episode=p_episode, |
176
|
|
|
**kwargs |
177
|
|
|
) |
178
|
|
|
|
179
|
1 |
|
def store_movie(self, action, guid, p_key=None, p_movie=None, **kwargs): |
180
|
1 |
|
return self.current.artifacts.store_movie( |
181
|
|
|
self.parent.data, action, guid, |
182
|
|
|
p_key=p_key, |
183
|
|
|
p_movie=p_movie, |
184
|
|
|
**kwargs |
185
|
|
|
) |
186
|
|
|
|
Generally, you would want to handle very specific errors in the exception handler. This ensure that you do not hide other types of errors which should be fixed.
So, unless you specifically plan to handle any error, consider adding a more specific exception.