Passed
Push — beta ( 72a57d...7d0ef0 )
by Dean
03:02
created

ListMessages()   F

Complexity

Conditions 14

Size

Total Lines 51

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 51
rs 2.8289
c 0
b 0
f 0
cc 14

How to fix   Long Method    Complexity   

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:

Complexity

Complex classes like ListMessages() often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

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