GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

Orange.canvas.onrequest()   A
last analyzed

Complexity

Conditions 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %
Metric Value
cc 1
dl 0
loc 3
rs 10
1
"""
2
Orange Canvas main entry point
3
4
"""
5
6
import os
7
import sys
8
import gc
9
import re
10
import logging
11
import optparse
12
import pickle
13
import shlex
14
import shutil
15
import signal
16
17
import pkg_resources
18
19
from PyQt4.QtGui import QFont, QColor
0 ignored issues
show
Configuration introduced by
The import PyQt4.QtGui 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...
20
from PyQt4.QtCore import Qt, QDir
0 ignored issues
show
Configuration introduced by
The import PyQt4.QtCore 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...
21
22
from Orange import canvas
23
from Orange.canvas.application.application import CanvasApplication
24
from Orange.canvas.application.canvasmain import CanvasMainWindow
25
from Orange.canvas.application.outputview import TextStream, ExceptHook
26
27
from Orange.canvas.gui.splashscreen import SplashScreen
28
from Orange.canvas.config import cache_dir
29
from Orange.canvas import config
30
from Orange.canvas.utils.redirect import redirect_stdout, redirect_stderr
31
from Orange.canvas.utils.qtcompat import QSettings
32
33
from Orange.canvas.registry import qt
34
from Orange.canvas.registry import WidgetRegistry, set_global_registry
35
from Orange.canvas.registry import cache
36
37
log = logging.getLogger(__name__)
38
39
40
def running_in_ipython():
41
    try:
42
        __IPYTHON__
0 ignored issues
show
Unused Code introduced by
This statement seems to have no effect and could be removed.

This issue is typically triggered when a function that does not have side-effects is called and the return value is discarded:

class SomeClass:
    def __init__(self):
        self._x = 5

    def squared(self):
        return self._x * self._x

some_class = SomeClass()
some_class.squared()        # Flagged, as the return value is not used
print(some_class.squared()) # Ok
Loading history...
43
        return True
44
    except NameError:
45
        return False
46
47
48
# Allow termination with CTRL + C
49
import signal
0 ignored issues
show
Unused Code introduced by
The import signal was already done on line 15. You should be able to
remove this line.
Loading history...
50
signal.signal(signal.SIGINT, signal.SIG_DFL)
51
52
53
def fix_osx_10_9_private_font():
54
    """Temporary fix for QTBUG-32789."""
55
    from PyQt4.QtCore import QSysInfo, QT_VERSION
0 ignored issues
show
Configuration introduced by
The import PyQt4.QtCore 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...
56
    if sys.platform == "darwin":
57
        try:
58
            QFont.insertSubstitution(".Helvetica Neue DeskInterface",
59
                                     "Helvetica Neue")
60
            if QSysInfo.MacintoshVersion > QSysInfo.MV_10_8 and \
61
                            QT_VERSION < 0x40806:
62
                QFont.insertSubstitution(".Lucida Grande UI",
63
                                         "Lucida Grande")
64
        except AttributeError:
0 ignored issues
show
Unused Code introduced by
This except handler seems to be unused and could be removed.

Except handlers which only contain pass and do not have an else clause can usually simply be removed:

try:
    raises_exception()
except:  # Could be removed
    pass
Loading history...
65
            pass
66
67
68
def fix_win_pythonw_std_stream():
69
    """
70
    On windows when running without a console (using pythonw.exe) the
71
    std[err|out] file descriptors are invalid and start throwing exceptions
72
    when their buffer is flushed (`http://bugs.python.org/issue706263`_)
73
74
    """
75
    if sys.platform == "win32" and \
76
            os.path.basename(sys.executable) == "pythonw.exe":
77
        if sys.stdout is not None and sys.stdout.fileno() < 0:
78
            sys.stdout = open(os.devnull, "wb")
79
        if sys.stdout is not None and sys.stderr.fileno() < 0:
80
            sys.stderr = open(os.devnull, "wb")
81
82
83
def main(argv=None):
84
    if argv is None:
85
        argv = sys.argv
86
87
    usage = "usage: %prog [options] [workflow_file]"
88
    parser = optparse.OptionParser(usage=usage)
89
90
    parser.add_option("--no-discovery",
91
                      action="store_true",
92
                      help="Don't run widget discovery "
93
                           "(use full cache instead)")
94
    parser.add_option("--force-discovery",
95
                      action="store_true",
96
                      help="Force full widget discovery "
97
                           "(invalidate cache)")
98
    parser.add_option("--clear-widget-settings",
99
                      action="store_true",
100
                      help="Remove stored widget setting")
101
    parser.add_option("--no-welcome",
102
                      action="store_true",
103
                      help="Don't show welcome dialog.")
104
    parser.add_option("--no-splash",
105
                      action="store_true",
106
                      help="Don't show splash screen.")
107
    parser.add_option("-l", "--log-level",
108
                      help="Logging level (0, 1, 2, 3, 4)",
109
                      type="int", default=1)
110
    parser.add_option("--no-redirect",
111
                      action="store_true",
112
                      help="Do not redirect stdout/err to canvas output view.")
113
    parser.add_option("--style",
114
                      help="QStyle to use",
115
                      type="str", default=None)
116
    parser.add_option("--stylesheet",
117
                      help="Application level CSS style sheet to use",
118
                      type="str", default="orange.qss")
119
    parser.add_option("--qt",
120
                      help="Additional arguments for QApplication",
121
                      type="str", default=None)
122
123
    (options, args) = parser.parse_args(argv[1:])
124
125
    levels = [logging.CRITICAL,
126
              logging.ERROR,
127
              logging.WARN,
128
              logging.INFO,
129
              logging.DEBUG]
130
131
    # Fix streams before configuring logging (otherwise it will store
132
    # and write to the old file descriptors)
133
    fix_win_pythonw_std_stream()
134
135
    # Try to fix fonts on OSX Mavericks
136
    fix_osx_10_9_private_font()
137
138
    # File handler should always be at least INFO level so we need
139
    # the application root level to be at least at INFO.
140
    root_level = min(levels[options.log_level], logging.INFO)
141
    rootlogger = logging.getLogger(canvas.__name__)
142
    rootlogger.setLevel(root_level)
143
144
    # Standard output stream handler at the requested level
145
    stream_hander = logging.StreamHandler()
146
    stream_hander.setLevel(level=levels[options.log_level])
147
    rootlogger.addHandler(stream_hander)
148
149
    log.info("Starting 'Orange Canvas' application.")
150
151
    qt_argv = argv[:1]
152
153
    if options.style is not None:
154
        qt_argv += ["-style", options.style]
155
156
    if options.qt is not None:
157
        qt_argv += shlex.split(options.qt)
158
159
    qt_argv += args
160
161
    log.debug("Starting CanvasApplicaiton with argv = %r.", qt_argv)
162
    app = CanvasApplication(qt_argv)
163
164
    # NOTE: config.init() must be called after the QApplication constructor
165
    config.init()
166
167
    clear_settings_flag = os.path.join(
168
        config.widget_settings_dir(), "DELETE_ON_START")
169
170
    if options.clear_widget_settings or \
171
            os.path.isfile(clear_settings_flag):
172
        log.info("Clearing widget settings")
173
        shutil.rmtree(
174
            config.widget_settings_dir(),
175
            ignore_errors=True)
176
177
    file_handler = logging.FileHandler(
178
        filename=os.path.join(config.log_dir(), "canvas.log"),
179
        mode="w"
180
    )
181
182
    file_handler.setLevel(root_level)
183
    rootlogger.addHandler(file_handler)
184
185
    # intercept any QFileOpenEvent requests until the main window is
186
    # fully initialized.
187
    # NOTE: The QApplication must have the executable ($0) and filename
188
    # arguments passed in argv otherwise the FileOpen events are
189
    # triggered for them (this is done by Cocoa, but QApplicaiton filters
190
    # them out if passed in argv)
191
192
    open_requests = []
193
194
    def onrequest(url):
195
        log.info("Received an file open request %s", url)
196
        open_requests.append(url)
197
198
    app.fileOpenRequest.connect(onrequest)
199
200
    settings = QSettings()
201
202
    stylesheet = options.stylesheet
203
    stylesheet_string = None
204
205
    if stylesheet != "none":
206
        if os.path.isfile(stylesheet):
207
            stylesheet_string = open(stylesheet, "rb").read()
208
        else:
209
            if not os.path.splitext(stylesheet)[1]:
210
                # no extension
211
                stylesheet = os.path.extsep.join([stylesheet, "qss"])
212
213
            pkg_name = canvas.__name__
214
            resource = "styles/" + stylesheet
215
216
            if pkg_resources.resource_exists(pkg_name, resource):
217
                stylesheet_string = \
218
                    pkg_resources.resource_string(pkg_name, resource).decode()
219
220
                base = pkg_resources.resource_filename(pkg_name, "styles")
221
222
                pattern = re.compile(
223
                    r"^\s@([a-zA-Z0-9_]+?)\s*:\s*([a-zA-Z0-9_/]+?);\s*$",
224
                    flags=re.MULTILINE
225
                )
226
227
                matches = pattern.findall(stylesheet_string)
228
229
                for prefix, search_path in matches:
230
                    QDir.addSearchPath(prefix, os.path.join(base, search_path))
231
                    log.info("Adding search path %r for prefix, %r",
232
                             search_path, prefix)
233
234
                stylesheet_string = pattern.sub("", stylesheet_string)
235
236
            else:
237
                log.info("%r style sheet not found.", stylesheet)
238
239
    # Add the default canvas_icons search path
240
    dirpath = os.path.abspath(os.path.dirname(canvas.__file__))
241
    QDir.addSearchPath("canvas_icons", os.path.join(dirpath, "icons"))
242
243
    canvas_window = CanvasMainWindow()
244
    canvas_window.setWindowIcon(config.application_icon())
245
246
    if stylesheet_string is not None:
247
        canvas_window.setStyleSheet(stylesheet_string)
248
249
    if not options.force_discovery:
250
        reg_cache = cache.registry_cache()
251
    else:
252
        reg_cache = None
253
254
    widget_discovery = qt.QtWidgetDiscovery(cached_descriptions=reg_cache)
255
256
    widget_registry = qt.QtWidgetRegistry()
257
258
    widget_discovery.found_category.connect(
259
        widget_registry.register_category
260
    )
261
    widget_discovery.found_widget.connect(
262
        widget_registry.register_widget
263
    )
264
265
    want_splash = \
266
        settings.value("startup/show-splash-screen", True, type=bool) and \
267
        not options.no_splash
268
269
    if want_splash:
270
        pm, rect = config.splash_screen()
271
        splash_screen = SplashScreen(pixmap=pm, textRect=rect)
272
        splash_screen.setFont(QFont("Helvetica", 12))
273
        color = QColor("#FFD39F")
274
275
        def show_message(message):
276
            splash_screen.showMessage(message, color=color)
277
278
        widget_discovery.discovery_start.connect(splash_screen.show)
279
        widget_discovery.discovery_process.connect(show_message)
280
        widget_discovery.discovery_finished.connect(splash_screen.hide)
281
282
    log.info("Running widget discovery process.")
283
284
    cache_filename = os.path.join(cache_dir(), "widget-registry.pck")
285
    if options.no_discovery:
286
        widget_registry = pickle.load(open(cache_filename, "rb"))
287
        widget_registry = qt.QtWidgetRegistry(widget_registry)
288
    else:
289
        widget_discovery.run(config.widgets_entry_points())
290
        # Store cached descriptions
291
        cache.save_registry_cache(widget_discovery.cached_descriptions)
292
        pickle.dump(WidgetRegistry(widget_registry),
293
                     open(cache_filename, "wb"))
294
    set_global_registry(widget_registry)
295
    canvas_window.set_widget_registry(widget_registry)
296
    canvas_window.show()
297
    canvas_window.raise_()
298
299
    want_welcome = \
300
        settings.value("startup/show-welcome-screen", True, type=bool) \
301
        and not options.no_welcome
302
303
    # Process events to make sure the canvas_window layout has
304
    # a chance to activate (the welcome dialog is modal and will
305
    # block the event queue, plus we need a chance to receive open file
306
    # signals when running without a splash screen)
307
    app.processEvents()
308
309
    app.fileOpenRequest.connect(canvas_window.open_scheme_file)
310
311
    if want_welcome and not args and not open_requests:
312
        canvas_window.welcome_dialog()
313
314
    elif args:
315
        log.info("Loading a scheme from the command line argument %r",
316
                 args[0])
317
        canvas_window.load_scheme(args[0])
318
    elif open_requests:
319
        log.info("Loading a scheme from an `QFileOpenEvent` for %r",
320
                 open_requests[-1])
321
        canvas_window.load_scheme(open_requests[-1].toLocalFile())
322
323
    stdout_redirect = \
324
        settings.value("output/redirect-stdout", True, type=bool)
325
326
    stderr_redirect = \
327
        settings.value("output/redirect-stderr", True, type=bool)
328
329
    # cmd line option overrides settings / no redirect is possible
330
    # under ipython
331
    if options.no_redirect or running_in_ipython():
332
        stderr_redirect = stdout_redirect = False
333
334
    output_view = canvas_window.output_view()
335
336
    if stdout_redirect:
337
        stdout = TextStream()
338
        stdout.stream.connect(output_view.write)
339
        if sys.stdout is not None:
340
            # also connect to original fd
341
            stdout.stream.connect(sys.stdout.write)
342
    else:
343
        stdout = sys.stdout
344
345
    if stderr_redirect:
346
        error_writer = output_view.formated(color=Qt.red)
347
        stderr = TextStream()
348
        stderr.stream.connect(error_writer.write)
349
        if sys.stderr is not None:
350
            # also connect to original fd
351
            stderr.stream.connect(sys.stderr.write)
352
    else:
353
        stderr = sys.stderr
354
355
    if stderr_redirect:
356
        sys.excepthook = ExceptHook()
357
        sys.excepthook.handledException.connect(output_view.parent().show)
358
359
    with redirect_stdout(stdout), redirect_stderr(stderr):
360
        log.info("Entering main event loop.")
361
        try:
362
            status = app.exec_()
363
        except BaseException:
364
            log.error("Error in main event loop.", exc_info=True)
365
366
    canvas_window.deleteLater()
367
    app.processEvents()
368
    app.flush()
369
    del canvas_window
370
371
    # Collect any cycles before deleting the QApplication instance
372
    gc.collect()
373
374
    del app
375
    return status
376
377
378
if __name__ == "__main__":
379
    sys.exit(main())
380