##// END OF EJS Templates
Merge pull request #4453 from minrk/appnap...
Min RK -
r13730:a711e50f merge
parent child Browse files
Show More
@@ -0,0 +1,15 b''
1
2 try:
3 from appnope import *
4 except ImportError:
5 __version__ = '0.0.5'
6 import sys
7 import platform
8 from distutils.version import LooseVersion as V
9
10 if sys.platform != "darwin" or V(platform.mac_ver()[0]) < V("10.9"):
11 from _dummy import *
12 else:
13 from ._nope import *
14
15 del sys, platform, V
@@ -0,0 +1,30 b''
1 #-----------------------------------------------------------------------------
2 # Copyright (C) 2013 Min RK
3 #
4 # Distributed under the terms of the 2-clause BSD License.
5 #-----------------------------------------------------------------------------
6
7 from contextlib import contextmanager
8
9 def beginActivityWithOptions(options, reason=""):
10 return
11
12 def endActivity(activity):
13 return
14
15 def nope():
16 return
17
18 def nap():
19 return
20
21
22 @contextmanager
23 def nope_scope(
24 options=0,
25 reason="Because Reasons"
26 ):
27 yield
28
29 def napping_allowed():
30 return True No newline at end of file
@@ -0,0 +1,126 b''
1 #-----------------------------------------------------------------------------
2 # Copyright (C) 2013 Min RK
3 #
4 # Distributed under the terms of the 2-clause BSD License.
5 #-----------------------------------------------------------------------------
6
7 from contextlib import contextmanager
8
9 import ctypes
10 import ctypes.util
11
12 objc = ctypes.cdll.LoadLibrary(ctypes.util.find_library('objc'))
13
14 void_p = ctypes.c_void_p
15 ull = ctypes.c_uint64
16
17 objc.objc_getClass.restype = void_p
18 objc.sel_registerName.restype = void_p
19 objc.objc_msgSend.restype = void_p
20 objc.objc_msgSend.argtypes = [void_p, void_p]
21
22 msg = objc.objc_msgSend
23
24 def _utf8(s):
25 """ensure utf8 bytes"""
26 if not isinstance(s, bytes):
27 s = s.encode('utf8')
28 return s
29
30 def n(name):
31 """create a selector name (for methods)"""
32 return objc.sel_registerName(_utf8(name))
33
34 def C(classname):
35 """get an ObjC Class by name"""
36 return objc.objc_getClass(_utf8(classname))
37
38 # constants from Foundation
39
40 NSActivityIdleDisplaySleepDisabled = (1 << 40)
41 NSActivityIdleSystemSleepDisabled = (1 << 20)
42 NSActivitySuddenTerminationDisabled = (1 << 14)
43 NSActivityAutomaticTerminationDisabled = (1 << 15)
44 NSActivityUserInitiated = (0x00FFFFFF | NSActivityIdleSystemSleepDisabled)
45 NSActivityUserInitiatedAllowingIdleSystemSleep = (NSActivityUserInitiated & ~NSActivityIdleSystemSleepDisabled)
46 NSActivityBackground = 0x000000FF
47 NSActivityLatencyCritical = 0xFF00000000
48
49 def beginActivityWithOptions(options, reason=""):
50 """Wrapper for:
51
52 [ [ NSProcessInfo processInfo]
53 beginActivityWithOptions: (uint64)options
54 reason: (str)reason
55 ]
56 """
57 NSProcessInfo = C('NSProcessInfo')
58 NSString = C('NSString')
59
60 reason = msg(NSString, n("stringWithUTF8String:"), _utf8(reason))
61 info = msg(NSProcessInfo, n('processInfo'))
62 activity = msg(info,
63 n('beginActivityWithOptions:reason:'),
64 ull(options),
65 void_p(reason)
66 )
67 return activity
68
69 def endActivity(activity):
70 """end a process activity assertion"""
71 NSProcessInfo = C('NSProcessInfo')
72 info = msg(NSProcessInfo, n('processInfo'))
73 msg(info, n("endActivity:"), void_p(activity))
74
75 _theactivity = None
76
77 def nope():
78 """disable App Nap by setting NSActivityUserInitiatedAllowingIdleSystemSleep"""
79 global _theactivity
80 _theactivity = beginActivityWithOptions(
81 NSActivityUserInitiatedAllowingIdleSystemSleep,
82 "Because Reasons"
83 )
84
85 def nap():
86 """end the caffeinated state started by `nope`"""
87 global _theactivity
88 if _theactivity is not None:
89 endActivity(_theactivity)
90 _theactivity = None
91
92 def napping_allowed():
93 """is napping allowed?"""
94 return _theactivity is None
95
96 @contextmanager
97 def nope_scope(
98 options=NSActivityUserInitiatedAllowingIdleSystemSleep,
99 reason="Because Reasons"
100 ):
101 """context manager for beginActivityWithOptions.
102
103 Within this context, App Nap will be disabled.
104 """
105 activity = beginActivityWithOptions(options, reason)
106 try:
107 yield
108 finally:
109 endActivity(activity)
110
111 __all__ = [
112 "NSActivityIdleDisplaySleepDisabled",
113 "NSActivityIdleSystemSleepDisabled",
114 "NSActivitySuddenTerminationDisabled",
115 "NSActivityAutomaticTerminationDisabled",
116 "NSActivityUserInitiated",
117 "NSActivityUserInitiatedAllowingIdleSystemSleep",
118 "NSActivityBackground",
119 "NSActivityLatencyCritical",
120 "beginActivityWithOptions",
121 "endActivity",
122 "nope",
123 "nap",
124 "napping_allowed",
125 "nope_scope",
126 ]
@@ -16,10 +16,10 b''
16
16
17 import sys
17 import sys
18
18
19 # System library imports.
19 # System library imports
20 import zmq
20 import zmq
21
21
22 # Local imports.
22 # Local imports
23 from IPython.config.application import Application
23 from IPython.config.application import Application
24 from IPython.utils import io
24 from IPython.utils import io
25
25
@@ -28,18 +28,40 b' from IPython.utils import io'
28 # Eventloops for integrating the Kernel into different GUIs
28 # Eventloops for integrating the Kernel into different GUIs
29 #------------------------------------------------------------------------------
29 #------------------------------------------------------------------------------
30
30
31 def _on_os_x_10_9():
32 import platform
33 from distutils.version import LooseVersion as V
34 return sys.platform == 'darwin' and V(platform.mac_ver()[0]) >= V('10.9')
35
36 def _notify_stream_qt(kernel, stream):
37
38 from IPython.external.qt_for_kernel import QtCore
39
40 if _on_os_x_10_9() and kernel._darwin_app_nap:
41 from IPython.external.appnope import nope_scope as context
42 else:
43 from IPython.core.interactiveshell import no_op_context as context
44
45 def process_stream_events():
46 while stream.getsockopt(zmq.EVENTS) & zmq.POLLIN:
47 with context():
48 kernel.do_one_iteration()
49
50 fd = stream.getsockopt(zmq.FD)
51 notifier = QtCore.QSocketNotifier(fd, QtCore.QSocketNotifier.Read, kernel.app)
52 notifier.activated.connect(process_stream_events)
53
31 def loop_qt4(kernel):
54 def loop_qt4(kernel):
32 """Start a kernel with PyQt4 event loop integration."""
55 """Start a kernel with PyQt4 event loop integration."""
33
56
34 from IPython.external.qt_for_kernel import QtCore
35 from IPython.lib.guisupport import get_app_qt4, start_event_loop_qt4
57 from IPython.lib.guisupport import get_app_qt4, start_event_loop_qt4
36
58
37 kernel.app = get_app_qt4([" "])
59 kernel.app = get_app_qt4([" "])
38 kernel.app.setQuitOnLastWindowClosed(False)
60 kernel.app.setQuitOnLastWindowClosed(False)
39 kernel.timer = QtCore.QTimer()
61
40 kernel.timer.timeout.connect(kernel.do_one_iteration)
62 for s in kernel.shell_streams:
41 # Units for the timer are in milliseconds
63 _notify_stream_qt(kernel, s)
42 kernel.timer.start(1000*kernel._poll_interval)
64
43 start_event_loop_qt4(kernel.app)
65 start_event_loop_qt4(kernel.app)
44
66
45
67
@@ -48,6 +70,12 b' def loop_wx(kernel):'
48
70
49 import wx
71 import wx
50 from IPython.lib.guisupport import start_event_loop_wx
72 from IPython.lib.guisupport import start_event_loop_wx
73
74 if _on_os_x_10_9() and kernel._darwin_app_nap:
75 # we don't hook up App Nap contexts for Wx,
76 # just disable it outright.
77 from IPython.external.appnope import nope
78 nope()
51
79
52 doi = kernel.do_one_iteration
80 doi = kernel.do_one_iteration
53 # Wx uses milliseconds
81 # Wx uses milliseconds
@@ -32,7 +32,7 b' from IPython.utils.py3compat import builtin_mod, unicode_type, string_types'
32 from IPython.utils.jsonutil import json_clean
32 from IPython.utils.jsonutil import json_clean
33 from IPython.utils.traitlets import (
33 from IPython.utils.traitlets import (
34 Any, Instance, Float, Dict, List, Set, Integer, Unicode,
34 Any, Instance, Float, Dict, List, Set, Integer, Unicode,
35 Type
35 Type, Bool,
36 )
36 )
37
37
38 from .serialize import serialize_object, unpack_apply_message
38 from .serialize import serialize_object, unpack_apply_message
@@ -91,9 +91,15 b' class Kernel(Configurable):'
91 def _ident_default(self):
91 def _ident_default(self):
92 return unicode_type(uuid.uuid4())
92 return unicode_type(uuid.uuid4())
93
93
94
95 # Private interface
94 # Private interface
96
95
96 _darwin_app_nap = Bool(True, config=True,
97 help="""Whether to use appnope for compatiblity with OS X App Nap.
98
99 Only affects OS X >= 10.9.
100 """
101 )
102
97 # Time to sleep after flushing the stdout/err buffers in each execute
103 # Time to sleep after flushing the stdout/err buffers in each execute
98 # cycle. While this introduces a hard limit on the minimal latency of the
104 # cycle. While this introduces a hard limit on the minimal latency of the
99 # execute cycle, it helps prevent output synchronization problems for
105 # execute cycle, it helps prevent output synchronization problems for
General Comments 0
You need to be logged in to leave comments. Login now