Test Failed
Push — develop ( a80574...5ed66c )
by Dean
02:36
created

Status()   B

Complexity

Conditions 5

Size

Total Lines 26

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 26
rs 8.0894
cc 5
1
from core.helpers import pad_title, try_convert, redirect
0 ignored issues
show
Bug introduced by
The name helpers does not seem to exist in module core.
Loading history...
Configuration introduced by
The import core.helpers could not be resolved.

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...
2
3
from plugin.core.constants import PLUGIN_PREFIX
0 ignored issues
show
Configuration introduced by
The import plugin.core.constants could not be resolved.

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...
4
from plugin.core.environment import translate as _
0 ignored issues
show
Configuration introduced by
The import plugin.core.environment could not be resolved.

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
from plugin.core.message import InterfaceMessages
0 ignored issues
show
Configuration introduced by
The import plugin.core.message could not be resolved.

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...
6
from plugin.managers.exception import ExceptionManager, MessageManager, VERSION_BASE
0 ignored issues
show
Configuration introduced by
The import plugin.managers.exception could not be resolved.

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...
7
from plugin.models import Exception, Message
0 ignored issues
show
Bug Best Practice introduced by
This seems to re-define the built-in Exception.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
Configuration introduced by
The import plugin.models could not be resolved.

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...
8
9
from ago import human
0 ignored issues
show
Configuration introduced by
The import ago could not be resolved.

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...
10
from datetime import datetime, timedelta
11
import logging
12
13
log = logging.getLogger(__name__)
14
15
ERROR_TYPES = [
16
    Message.Type.Exception,
17
18
    Message.Type.Warning,
19
    Message.Type.Error,
20
    Message.Type.Critical
21
]
22
23
24
@route(PLUGIN_PREFIX + '/messages/list')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'route'
Loading history...
25
def ListMessages(days=14, version='latest', viewed=False, *args, **kwargs):
0 ignored issues
show
Unused Code introduced by
The argument kwargs seems to be unused.
Loading history...
Unused Code introduced by
The argument args seems to be unused.
Loading history...
26
    # Cast `viewed` to boolean
27
    if type(viewed) is str:
28
        if viewed == 'None':
29
            viewed = None
30
        else:
31
            viewed = viewed == 'True'
32
33
    # Retrieve messages
34
    messages = list(List(
35
        days=try_convert(days, int),
36
        version=version,
37
        viewed=viewed
38
    ).order_by(
39
        Message.last_logged_at.desc()
40
    ).limit(50))
41
42
    total_messages = List(
43
        days=try_convert(days, int),
44
        version=version,
45
    ).count()
46
47
    # Construct container
48
    oc = ObjectContainer(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ObjectContainer'
Loading history...
49
        title2=_("Messages")
50
    )
51
52
    # Add "Dismiss All" button
53
    if viewed is False and len(messages) > 1:
54
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
55
            key=Callback(DismissMessages),
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
56
            title=pad_title(_("Dismiss all"))
57
        ))
58
59
    # Add interface messages
60
    for record in InterfaceMessages.records:
61
        # Pick object thumb
62
        if record.level >= logging.WARNING:
63
            thumb = R("icon-error.png")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'R'
Loading history...
64
        else:
65
            thumb = R("icon-notification.png")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'R'
Loading history...
66
67
        # Add object
68
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
69
            key=PLUGIN_PREFIX + '/messages/list',
70
            title=pad_title('[%s] %s' % (logging.getLevelName(record.level).capitalize(), record.message)),
71
            thumb=thumb
72
        ))
73
74
    # Add stored messages
75
    for m in messages:
76
        if m.type is None or\
77
           m.summary is None:
78
            continue
79
80
        # Pick thumb
81
        if m.type == Message.Type.Exception:
82
            thumb = R("icon-exception-viewed.png") if m.viewed else R("icon-exception.png")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'R'
Loading history...
83
        elif m.type == Message.Type.Info:
84
            thumb = R("icon-notification-viewed.png") if m.viewed else R("icon-notification.png")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'R'
Loading history...
85
        else:
86
            thumb = R("icon-error-viewed.png") if m.viewed else R("icon-error.png")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'R'
Loading history...
87
88
        # Add object
89
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
90
            key=Callback(ViewMessage, error_id=m.id),
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
91
            title=pad_title('[%s] %s' % (Message.Type.title(m.type), m.summary)),
92
            thumb=thumb
93
        ))
94
95
    # Append "View All" button
96
    if len(messages) != 50 and len(messages) < total_messages:
97
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
98
            key=Callback(ListMessages, days=None, viewed=None),
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
99
            title=pad_title(_("View All"))
100
        ))
101
102
    return oc
103
104
@route(PLUGIN_PREFIX + '/messages/view')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'route'
Loading history...
105
def ViewMessage(error_id, *args, **kwargs):
0 ignored issues
show
Unused Code introduced by
The argument kwargs seems to be unused.
Loading history...
Unused Code introduced by
The argument args seems to be unused.
Loading history...
106
    # Retrieve message from database
107
    message = MessageManager.get.by_id(error_id)
108
109
    # Update `last_viewed_at` field
110
    message.last_viewed_at = datetime.utcnow()
111
    message.save()
112
113
    # Parse request headers
114
    web_client = Request.Headers.get('X-Plex-Product', '').lower() == 'plex web'
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Request'
Loading history...
115
116
    # Build objects
117
    oc = ObjectContainer(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ObjectContainer'
Loading history...
118
        title2='[%s] %s' % (Message.Type.title(message.type), Trim(message.summary))
119
    )
120
121
    if message.type == Message.Type.Exception:
122
        # Display exception samples
123
        for e in message.exceptions.order_by(Exception.timestamp.desc()).limit(50):
124
            since = datetime.utcnow() - e.timestamp
125
126
            callback = Callback(ViewMessage, error_id=error_id)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
127
128
            if web_client:
129
                # Display exception traceback in Plex/Web
130
                callback = Callback(ViewException, exception_id=e.id)
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
131
132
            oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
133
                key=callback,
134
                title=pad_title('[%s] %s: %s' % (human(since, precision=1), e.type, e.message)),
135
                thumb=R("icon-exception.png")
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'R'
Loading history...
136
            ))
137
    elif message.type in [Message.Type.Info, Message.Type.Warning, Message.Type.Error, Message.Type.Critical]:
138
        # Display message code
139
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
140
            key='',
141
            title=pad_title(_('Code: %s') % hex(message.code))
142
        ))
143
144
        # Display message description
145
        if message.description:
146
            oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
147
                key='',
148
                title=pad_title(_('Description: %s') % message.description)
149
            ))
150
151
    return oc
152
153
@route(PLUGIN_PREFIX + '/exceptions/view')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'route'
Loading history...
154
def ViewException(exception_id, *args, **kwargs):
0 ignored issues
show
Unused Code introduced by
The argument kwargs seems to be unused.
Loading history...
Unused Code introduced by
The argument args seems to be unused.
Loading history...
155
    # Retrieve exception from database
156
    exception = ExceptionManager.get.by_id(exception_id)
157
158
    # Split traceback into lines
159
    traceback = exception.traceback
160
161
    if traceback:
162
        traceback = traceback.split('\n')
163
164
    # Build exception view
165
    oc = ObjectContainer(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'ObjectContainer'
Loading history...
166
        title2='%s: %s' % (exception.type, Trim(exception.message))
167
    )
168
169
    if not traceback:
170
        return oc
171
172
    for line in traceback:
173
        if not line:
174
            continue
175
176
        length = len(line)
177
178
        line = line.lstrip()
179
        spaces = length - len(line)
180
181
        oc.add(DirectoryObject(
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'DirectoryObject'
Loading history...
182
            key=Callback(ViewException, exception_id=exception_id),
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'Callback'
Loading history...
183
            title=pad_title(('&nbsp;' * spaces) + line)
184
        ))
185
186
    return oc
187
188
189
@route(PLUGIN_PREFIX + '/messages/dismissAll')
0 ignored issues
show
Comprehensibility Best Practice introduced by
Undefined variable 'route'
Loading history...
190
def DismissMessages(days=14, version='latest', *args, **kwargs):
0 ignored issues
show
Unused Code introduced by
The argument args seems to be unused.
Loading history...
Unused Code introduced by
The argument kwargs seems to be unused.
Loading history...
191
    # Retrieve messages that match the specified criteria
192
    messages = List(
193
        days=days,
194
        version=version,
195
        viewed=False
196
    )
197
198
    # Mark all messages as viewed
199
    for message in messages:
200
        # Update `last_viewed_at` field
201
        message.last_viewed_at = datetime.utcnow()
202
        message.save()
203
204
    # Redirect back to the messages view
205
    return redirect(
206
        '/messages/list',
207
        days=days,
208
        version=version
209
    )
210
211
212
def Status(viewed=None):
213
    """Get the number and type of messages logged in the last week"""
214
    messages = List(
215
        days=14,
216
        version='latest',
217
        viewed=viewed
218
    )
219
220
    count = 0
221
    type = 'notification'
0 ignored issues
show
Bug Best Practice introduced by
This seems to re-define the built-in type.

It is generally discouraged to redefine built-ins as this makes code very hard to read.

Loading history...
222
223
    # Process stored messages
224
    for message in messages:
225
        if message.type in ERROR_TYPES:
226
            type = 'error'
227
228
        count += 1
229
230
    # Process interface messages
231
    for record in InterfaceMessages.records:
232
        if record.level >= logging.ERROR:
233
            type = 'error'
234
235
        count += 1
236
237
    return count, type
238
239
240
def List(days=None, version=None, viewed=None):
241
    """Get messages logged in the last week"""
242
    where = []
243
244
    # Days
245
    if days is not None:
246
        where.append(
247
            Message.last_logged_at > datetime.utcnow() - timedelta(days=days)
248
        )
249
250
    # Version
251
    if version == 'latest':
252
        where.append(
253
            Message.version_base == VERSION_BASE
254
        )
255
    elif version is not None:
256
        log.warn('Unknown version specified: %r', version)
257
258
    # Viewed state
259
    if viewed is True:
260
        where.append(
261
            ~(Message.last_viewed_at >> None),
262
            Message.last_viewed_at > Message.last_logged_at
263
        )
264
    elif viewed is False:
265
        where.append(
266
            (Message.last_viewed_at >> None) | (Message.last_viewed_at < Message.last_logged_at)
267
        )
268
269
    # Build query
270
    if where:
271
        return MessageManager.get.where(*where)
272
273
    return MessageManager.get.all()
274
275
276
def Trim(value, length=45):
277
    if value and len(value) > length:
278
        return value[:length - 3] + "..."
279
280
    return value
281