##// END OF EJS Templates
Merge master
Gordon Ball -
r17698:0a458d02 merge
parent child Browse files
Show More
@@ -0,0 +1,43 b''
1
2 //
3 // Tests for the Session object
4 //
5
6 casper.notebook_test(function () {
7 this.evaluate(function () {
8 var kernel = IPython.notebook.session.kernel;
9 IPython._channels = [
10 kernel.shell_channel,
11 kernel.iopub_channel,
12 kernel.stdin_channel
13 ];
14 IPython.notebook.session.delete();
15 });
16
17 this.waitFor(function () {
18 return this.evaluate(function(){
19 for (var i=0; i < IPython._channels.length; i++) {
20 var ws = IPython._channels[i];
21 if (ws.readyState !== ws.CLOSED) {
22 return false;
23 }
24 }
25 return true;
26 });
27 });
28
29 this.then(function () {
30 var states = this.evaluate(function() {
31 var states = [];
32 for (var i = 0; i < IPython._channels.length; i++) {
33 states.push(IPython._channels[i].readyState);
34 }
35 return states;
36 });
37
38 for (var i = 0; i < states.length; i++) {
39 this.test.assertEquals(states[i], WebSocket.CLOSED,
40 "Session.delete closes websockets[" + i + "]");
41 }
42 });
43 });
@@ -0,0 +1,73 b''
1 """Box class.
2
3 Represents a container that can be used to group other widgets.
4 """
5
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
8
9 from .widget import DOMWidget
10 from IPython.utils.traitlets import Unicode, Tuple, TraitError, Int, CaselessStrEnum
11 from IPython.utils.warn import DeprecatedClass
12
13 class Box(DOMWidget):
14 """Displays multiple widgets in a group."""
15 _view_name = Unicode('BoxView', sync=True)
16
17 # Child widgets in the container.
18 # Using a tuple here to force reassignment to update the list.
19 # When a proper notifying-list trait exists, that is what should be used here.
20 children = Tuple(sync=True, allow_none=False)
21
22 def __init__(self, children = (), **kwargs):
23 kwargs['children'] = children
24 super(Box, self).__init__(**kwargs)
25 self.on_displayed(Box._fire_children_displayed)
26
27 def _fire_children_displayed(self):
28 for child in self.children:
29 child._handle_displayed()
30
31
32 class Popup(Box):
33 """Displays multiple widgets in an in page popup div."""
34 _view_name = Unicode('PopupView', sync=True)
35
36 description = Unicode(sync=True)
37 button_text = Unicode(sync=True)
38
39
40 class FlexBox(Box):
41 """Displays multiple widgets using the flexible box model."""
42 _view_name = Unicode('FlexBoxView', sync=True)
43 orientation = CaselessStrEnum(values=['vertical', 'horizontal'], default_value='vertical', sync=True)
44 flex = Int(0, sync=True, help="""Specify the flexible-ness of the model.""")
45 def _flex_changed(self, name, old, new):
46 new = min(max(0, new), 2)
47 if self.flex != new:
48 self.flex = new
49
50 _locations = ['start', 'center', 'end', 'baseline', 'stretch']
51 pack = CaselessStrEnum(
52 values=_locations,
53 default_value='start', allow_none=False, sync=True)
54 align = CaselessStrEnum(
55 values=_locations,
56 default_value='start', allow_none=False, sync=True)
57
58
59 def VBox(*pargs, **kwargs):
60 """Displays multiple widgets vertically using the flexible box model."""
61 kwargs['orientation'] = 'vertical'
62 return FlexBox(*pargs, **kwargs)
63
64 def HBox(*pargs, **kwargs):
65 """Displays multiple widgets horizontally using the flexible box model."""
66 kwargs['orientation'] = 'horizontal'
67 return FlexBox(*pargs, **kwargs)
68
69
70 # Remove in IPython 4.0
71 ContainerWidget = DeprecatedClass(Box, 'ContainerWidget')
72 PopupWidget = DeprecatedClass(Popup, 'PopupWidget')
73
@@ -0,0 +1,6 b''
1 * The widget classes have been renamed from `*Widget` to `*`. The old names are
2 still functional, but are deprecated. i.e. `IntSliderWidget` has been renamed
3 to `IntSlider`.
4 * The ContainerWidget was renamed to Box and no longer defaults as a flexible
5 box in the web browser. A new FlexBox widget was added, which allows you to
6 use the flexible box model.
@@ -84,6 +84,9 b' class KernelActionHandler(IPythonHandler):'
84 84
85 85 class ZMQChannelHandler(AuthenticatedZMQStreamHandler):
86 86
87 def __repr__(self):
88 return "%s(%s)" % (self.__class__.__name__, getattr(self, 'kernel_id', 'uninitialized'))
89
87 90 def create_stream(self):
88 91 km = self.kernel_manager
89 92 meth = getattr(km, 'connect_%s' % self.channel)
@@ -145,6 +148,12 b' class ZMQChannelHandler(AuthenticatedZMQStreamHandler):'
145 148 self.zmq_stream.on_recv(self._on_zmq_reply)
146 149
147 150 def on_message(self, msg):
151 if self.zmq_stream is None:
152 return
153 elif self.zmq_stream.closed():
154 self.log.info("%s closed, closing websocket.", self)
155 self.close()
156 return
148 157 msg = json.loads(msg)
149 158 self.session.send(self.zmq_stream, msg)
150 159
@@ -184,6 +184,30 b' Browsers not listed, including Safari, are supported via the styling under the'
184 184 justify-content: center;
185 185 }
186 186
187 .hbox.baseline,
188 .vbox.baseline,
189 .baseline {
190 /* Old browsers */
191 -webkit-box-pack: baseline;
192 -moz-box-pack: baseline;
193 box-pack: baseline;
194
195 /* Modern browsers */
196 justify-content: baseline;
197 }
198
199 .hbox.stretch,
200 .vbox.stretch,
201 .stretch {
202 /* Old browsers */
203 -webkit-box-pack: stretch;
204 -moz-box-pack: stretch;
205 box-pack: stretch;
206
207 /* Modern browsers */
208 justify-content: stretch;
209 }
210
187 211 .hbox.align-start,
188 212 .vbox.align-start,
189 213 .align-start {
@@ -219,3 +243,27 b' Browsers not listed, including Safari, are supported via the styling under the'
219 243 /* Modern browsers */
220 244 align-items: center;
221 245 }
246
247 .hbox.align-baseline,
248 .vbox.align-baseline,
249 .align-baseline {
250 /* Old browsers */
251 -webkit-box-align: baseline;
252 -moz-box-align: baseline;
253 box-align: baseline;
254
255 /* Modern browsers */
256 align-items: baseline;
257 }
258
259 .hbox.align-stretch,
260 .vbox.align-stretch,
261 .align-stretch {
262 /* Old browsers */
263 -webkit-box-align: stretch;
264 -moz-box-align: stretch;
265 box-align: stretch;
266
267 /* Modern browsers */
268 align-items: stretch;
269 }
@@ -54,9 +54,19 b' define(['
54 54 return;
55 55 }
56 56 var ks = this.kernelspecs[kernel_name];
57 try {
58 this.notebook.start_session(kernel_name);
59 } catch (e) {
60 if (e.name === 'SessionAlreadyStarting') {
61 console.log("Cannot change kernel while waiting for pending session start.");
62 } else {
63 // unhandled error
64 throw e;
65 }
66 // only trigger spec_changed if change was successful
67 return;
68 }
57 69 this.events.trigger('spec_changed.Kernel', ks);
58 this.notebook.session.delete();
59 this.notebook.start_session(kernel_name);
60 70 };
61 71
62 72 KernelSelector.prototype.bind_events = function() {
@@ -157,12 +157,13 b' define(['
157 157 }
158 158 });
159 159 this.element.find('#kill_and_exit').click(function () {
160 that.notebook.session.delete();
161 setTimeout(function(){
160 var close_window = function () {
162 161 // allow closing of new tabs in Chromium, impossible in FF
163 162 window.open('', '_self', '');
164 163 window.close();
165 }, 500);
164 };
165 // finish with close on success or failure
166 that.notebook.session.delete(close_window, close_window);
166 167 });
167 168 // Edit
168 169 this.element.find('#cut_cell').click(function () {
@@ -62,6 +62,7 b' define(['
62 62 this.save_widget = options.save_widget;
63 63 this.tooltip = new tooltip.Tooltip(this.events);
64 64 this.ws_url = options.ws_url;
65 this._session_starting = false;
65 66 // default_kernel_name is a temporary measure while we implement proper
66 67 // kernel selection and delayed start. Do not rely on it.
67 68 this.default_kernel_name = 'python';
@@ -1525,9 +1526,38 b' define(['
1525 1526 * @method start_session
1526 1527 */
1527 1528 Notebook.prototype.start_session = function (kernel_name) {
1529 var that = this;
1528 1530 if (kernel_name === undefined) {
1529 1531 kernel_name = this.default_kernel_name;
1530 1532 }
1533 if (this._session_starting) {
1534 throw new session.SessionAlreadyStarting();
1535 }
1536 this._session_starting = true;
1537
1538 if (this.session !== null) {
1539 var s = this.session;
1540 this.session = null;
1541 // need to start the new session in a callback after delete,
1542 // because javascript does not guarantee the ordering of AJAX requests (?!)
1543 s.delete(function () {
1544 // on successful delete, start new session
1545 that._session_starting = false;
1546 that.start_session(kernel_name);
1547 }, function (jqXHR, status, error) {
1548 // log the failed delete, but still create a new session
1549 // 404 just means it was already deleted by someone else,
1550 // but other errors are possible.
1551 utils.log_ajax_error(jqXHR, status, error);
1552 that._session_starting = false;
1553 that.start_session(kernel_name);
1554 }
1555 );
1556 return;
1557 }
1558
1559
1560
1531 1561 this.session = new session.Session({
1532 1562 base_url: this.base_url,
1533 1563 ws_url: this.ws_url,
@@ -1539,7 +1569,10 b' define(['
1539 1569 kernel_name: kernel_name,
1540 1570 notebook: this});
1541 1571
1542 this.session.start($.proxy(this._session_started, this));
1572 this.session.start(
1573 $.proxy(this._session_started, this),
1574 $.proxy(this._session_start_failed, this)
1575 );
1543 1576 };
1544 1577
1545 1578
@@ -1548,7 +1581,8 b' define(['
1548 1581 * comm manager to the widget manager
1549 1582 *
1550 1583 */
1551 Notebook.prototype._session_started = function(){
1584 Notebook.prototype._session_started = function (){
1585 this._session_starting = false;
1552 1586 this.kernel = this.session.kernel;
1553 1587 var ncells = this.ncells();
1554 1588 for (var i=0; i<ncells; i++) {
@@ -1558,7 +1592,11 b' define(['
1558 1592 }
1559 1593 }
1560 1594 };
1561
1595 Notebook.prototype._session_start_failed = function (jqxhr, status, error){
1596 this._session_starting = false;
1597 utils.log_ajax_error(jqxhr, status, error);
1598 };
1599
1562 1600 /**
1563 1601 * Prompt the user to restart the IPython kernel.
1564 1602 *
@@ -109,6 +109,12 b' define(['
109 109 knw.set_message("Restarting kernel", 2000);
110 110 });
111 111
112 this.events.on('status_dead.Kernel',function () {
113 that.save_widget.update_document_title();
114 knw.danger("Dead kernel");
115 $kernel_ind_icon.attr('class','kernel_dead_icon').attr('title','Kernel Dead');
116 });
117
112 118 this.events.on('status_interrupting.Kernel',function () {
113 119 knw.set_message("Interrupting kernel", 2000);
114 120 });
@@ -118,6 +124,8 b' define(['
118 124 $kernel_ind_icon.attr('class','kernel_busy_icon').attr('title','Kernel Busy');
119 125
120 126 this.events.on('status_started.Kernel', function (evt, data) {
127 knw.info("Websockets Connected", 500);
128 that.events.trigger('status_busy.Kernel');
121 129 data.kernel.kernel_info(function () {
122 130 that.events.trigger('status_idle.Kernel');
123 131 });
@@ -153,8 +161,13 b' define(['
153 161 var ws_url = data.ws_url;
154 162 var early = data.early;
155 163 var msg;
164
165 $kernel_ind_icon
166 .attr('class', 'kernel_disconnected_icon')
167 .attr('title', 'No Connection to Kernel');
168
156 169 if (!early) {
157 knw.set_message('Reconnecting WebSockets', 1000);
170 knw.warning('Reconnecting');
158 171 setTimeout(function () {
159 172 kernel.start_channels();
160 173 }, 5000);
@@ -173,7 +186,7 b' define(['
173 186 "OK": {},
174 187 "Reconnect": {
175 188 click: function () {
176 knw.set_message('Reconnecting WebSockets', 1000);
189 knw.warning('Reconnecting');
177 190 setTimeout(function () {
178 191 kernel.start_channels();
179 192 }, 5000);
@@ -43,4 +43,12 b''
43 43 .icon(@fa-var-circle);
44 44 }
45 45
46 .kernel_dead_icon:before {
47 .icon(@fa-var-bomb);
48 }
49
50 .kernel_disconnected_icon:before {
51 .icon(@fa-var-chain-broken);
52 }
53
46 54
@@ -179,10 +179,18 b' define(['
179 179 that._websocket_closed(ws_host_url, false);
180 180 }
181 181 };
182 var ws_error = function(evt){
183 if (already_called_onclose){
184 return;
185 }
186 already_called_onclose = true;
187 that._websocket_closed(ws_host_url, false);
188 };
182 189 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
183 190 for (var i=0; i < channels.length; i++) {
184 191 channels[i].onopen = $.proxy(this._ws_opened, this);
185 192 channels[i].onclose = ws_closed_early;
193 channels[i].onerror = ws_error;
186 194 }
187 195 // switch from early-close to late-close message after 1s
188 196 setTimeout(function() {
@@ -211,7 +219,7 b' define(['
211 219 var channels = [this.shell_channel, this.iopub_channel, this.stdin_channel];
212 220 for (var i=0; i < channels.length; i++) {
213 221 // if any channel is not ready, don't trigger event.
214 if ( !channels[i].readyState ) return;
222 if ( channels[i].readyState == WebSocket.OPEN ) return;
215 223 }
216 224 // all events ready, trigger started event.
217 225 this.events.trigger('status_started.Kernel', {kernel: this});
@@ -385,15 +393,17 b' define(['
385 393 };
386 394
387 395
388 Kernel.prototype.kill = function () {
396 Kernel.prototype.kill = function (success, error) {
389 397 if (this.running) {
390 398 this.running = false;
391 399 var settings = {
392 400 cache : false,
393 401 type : "DELETE",
394 error : utils.log_ajax_error,
402 success : success,
403 error : error || utils.log_ajax_error,
395 404 };
396 405 $.ajax(utils.url_join_encode(this.kernel_url), settings);
406 this.stop_channels();
397 407 }
398 408 };
399 409
@@ -21,7 +21,7 b' define(['
21 21 this.ws_url = options.ws_url;
22 22 };
23 23
24 Session.prototype.start = function(callback) {
24 Session.prototype.start = function (success, error) {
25 25 var that = this;
26 26 var model = {
27 27 notebook : {
@@ -40,11 +40,17 b' define(['
40 40 dataType : "json",
41 41 success : function (data, status, xhr) {
42 42 that._handle_start_success(data);
43 if (callback) {
44 callback(data, status, xhr);
43 if (success) {
44 success(data, status, xhr);
45 45 }
46 46 },
47 error : utils.log_ajax_error,
47 error : function (xhr, status, err) {
48 that._handle_start_failure(xhr, status, err);
49 if (error !== undefined) {
50 error(xhr, status, err);
51 }
52 utils.log_ajax_error(xhr, status, err);
53 }
48 54 };
49 55 var url = utils.url_join_encode(this.base_url, 'api/sessions');
50 56 $.ajax(url, settings);
@@ -71,15 +77,19 b' define(['
71 77 $.ajax(url, settings);
72 78 };
73 79
74 Session.prototype.delete = function() {
80 Session.prototype.delete = function (success, error) {
75 81 var settings = {
76 82 processData : false,
77 83 cache : false,
78 84 type : "DELETE",
79 85 dataType : "json",
80 error : utils.log_ajax_error,
86 success : success,
87 error : error || utils.log_ajax_error,
81 88 };
82 this.kernel.running = false;
89 if (this.kernel) {
90 this.kernel.running = false;
91 this.kernel.stop_channels();
92 }
83 93 var url = utils.url_join_encode(this.base_url, 'api/sessions', this.id);
84 94 $.ajax(url, settings);
85 95 };
@@ -99,6 +109,11 b' define(['
99 109 this.kernel = new kernel.Kernel(kernel_service_url, this.ws_url, this.notebook, this.kernel_name);
100 110 this.kernel._kernel_started(data.kernel);
101 111 };
112
113 Session.prototype._handle_start_failure = function (xhr, status, error) {
114 this.events.trigger('start_failed.Session', [this, xhr, status, error]);
115 this.events.trigger('status_dead.Kernel');
116 };
102 117
103 118 /**
104 119 * Prompt the user to restart the IPython kernel.
@@ -118,8 +133,18 b' define(['
118 133 this.kernel.kill();
119 134 };
120 135
136 var SessionAlreadyStarting = function (message) {
137 this.name = "SessionAlreadyStarting";
138 this.message = (message || "");
139 };
140
141 SessionAlreadyStarting.prototype = Error.prototype;
142
121 143 // For backwards compatability.
122 144 IPython.Session = Session;
123 145
124 return {'Session': Session};
146 return {
147 Session: Session,
148 SessionAlreadyStarting: SessionAlreadyStarting,
149 };
125 150 });
@@ -1501,7 +1501,7 b' div.cell.text_cell.rendered {'
1501 1501 box-pack: start;
1502 1502 /* Modern browsers */
1503 1503 justify-content: flex-start;
1504 /* ContainerWidget */
1504 /* Box */
1505 1505 box-sizing: border-box;
1506 1506 -moz-box-sizing: border-box;
1507 1507 -webkit-box-sizing: border-box;
@@ -1532,7 +1532,7 b' div.cell.text_cell.rendered {'
1532 1532 box-pack: start;
1533 1533 /* Modern browsers */
1534 1534 justify-content: flex-start;
1535 /* ContainerWidget */
1535 /* Box */
1536 1536 box-sizing: border-box;
1537 1537 -moz-box-sizing: border-box;
1538 1538 -webkit-box-sizing: border-box;
@@ -1584,7 +1584,7 b' div.cell.text_cell.rendered {'
1584 1584 box-pack: start;
1585 1585 /* Modern browsers */
1586 1586 justify-content: flex-start;
1587 /* ContainerWidget */
1587 /* Box */
1588 1588 box-sizing: border-box;
1589 1589 -moz-box-sizing: border-box;
1590 1590 -webkit-box-sizing: border-box;
@@ -1639,7 +1639,7 b' div.cell.text_cell.rendered {'
1639 1639 box-pack: start;
1640 1640 /* Modern browsers */
1641 1641 justify-content: flex-start;
1642 /* ContainerWidget */
1642 /* Box */
1643 1643 box-sizing: border-box;
1644 1644 -moz-box-sizing: border-box;
1645 1645 -webkit-box-sizing: border-box;
@@ -1691,7 +1691,7 b' div.cell.text_cell.rendered {'
1691 1691 box-pack: start;
1692 1692 /* Modern browsers */
1693 1693 justify-content: flex-start;
1694 /* ContainerWidget */
1694 /* Box */
1695 1695 box-sizing: border-box;
1696 1696 -moz-box-sizing: border-box;
1697 1697 -webkit-box-sizing: border-box;
@@ -1724,7 +1724,7 b' div.cell.text_cell.rendered {'
1724 1724 width: 30px;
1725 1725 }
1726 1726 .widget-modal {
1727 /* ContainerWidget - ModalView */
1727 /* Box - ModalView */
1728 1728 overflow: hidden;
1729 1729 position: absolute !important;
1730 1730 top: 0px;
@@ -1732,11 +1732,11 b' div.cell.text_cell.rendered {'
1732 1732 margin-left: 0px !important;
1733 1733 }
1734 1734 .widget-modal-body {
1735 /* ContainerWidget - ModalView Body */
1735 /* Box - ModalView Body */
1736 1736 max-height: none !important;
1737 1737 }
1738 .widget-container {
1739 /* ContainerWidget */
1738 .widget-box {
1739 /* Box */
1740 1740 box-sizing: border-box;
1741 1741 -moz-box-sizing: border-box;
1742 1742 -webkit-box-sizing: border-box;
@@ -9273,7 +9273,7 b' div.cell.text_cell.rendered {'
9273 9273 box-pack: start;
9274 9274 /* Modern browsers */
9275 9275 justify-content: flex-start;
9276 /* ContainerWidget */
9276 /* Box */
9277 9277 box-sizing: border-box;
9278 9278 -moz-box-sizing: border-box;
9279 9279 -webkit-box-sizing: border-box;
@@ -9304,7 +9304,7 b' div.cell.text_cell.rendered {'
9304 9304 box-pack: start;
9305 9305 /* Modern browsers */
9306 9306 justify-content: flex-start;
9307 /* ContainerWidget */
9307 /* Box */
9308 9308 box-sizing: border-box;
9309 9309 -moz-box-sizing: border-box;
9310 9310 -webkit-box-sizing: border-box;
@@ -9356,7 +9356,7 b' div.cell.text_cell.rendered {'
9356 9356 box-pack: start;
9357 9357 /* Modern browsers */
9358 9358 justify-content: flex-start;
9359 /* ContainerWidget */
9359 /* Box */
9360 9360 box-sizing: border-box;
9361 9361 -moz-box-sizing: border-box;
9362 9362 -webkit-box-sizing: border-box;
@@ -9411,7 +9411,7 b' div.cell.text_cell.rendered {'
9411 9411 box-pack: start;
9412 9412 /* Modern browsers */
9413 9413 justify-content: flex-start;
9414 /* ContainerWidget */
9414 /* Box */
9415 9415 box-sizing: border-box;
9416 9416 -moz-box-sizing: border-box;
9417 9417 -webkit-box-sizing: border-box;
@@ -9463,7 +9463,7 b' div.cell.text_cell.rendered {'
9463 9463 box-pack: start;
9464 9464 /* Modern browsers */
9465 9465 justify-content: flex-start;
9466 /* ContainerWidget */
9466 /* Box */
9467 9467 box-sizing: border-box;
9468 9468 -moz-box-sizing: border-box;
9469 9469 -webkit-box-sizing: border-box;
@@ -9496,7 +9496,7 b' div.cell.text_cell.rendered {'
9496 9496 width: 30px;
9497 9497 }
9498 9498 .widget-modal {
9499 /* ContainerWidget - ModalView */
9499 /* Box - ModalView */
9500 9500 overflow: hidden;
9501 9501 position: absolute !important;
9502 9502 top: 0px;
@@ -9504,11 +9504,11 b' div.cell.text_cell.rendered {'
9504 9504 margin-left: 0px !important;
9505 9505 }
9506 9506 .widget-modal-body {
9507 /* ContainerWidget - ModalView Body */
9507 /* Box - ModalView Body */
9508 9508 max-height: none !important;
9509 9509 }
9510 .widget-container {
9511 /* ContainerWidget */
9510 .widget-box {
9511 /* Box */
9512 9512 box-sizing: border-box;
9513 9513 -moz-box-sizing: border-box;
9514 9514 -webkit-box-sizing: border-box;
@@ -10006,6 +10006,38 b' ul#help_menu li a i {'
10006 10006 .kernel_busy_icon:before.pull-right {
10007 10007 margin-left: .3em;
10008 10008 }
10009 .kernel_dead_icon:before {
10010 display: inline-block;
10011 font-family: FontAwesome;
10012 font-style: normal;
10013 font-weight: normal;
10014 line-height: 1;
10015 -webkit-font-smoothing: antialiased;
10016 -moz-osx-font-smoothing: grayscale;
10017 content: "\f1e2";
10018 }
10019 .kernel_dead_icon:before.pull-left {
10020 margin-right: .3em;
10021 }
10022 .kernel_dead_icon:before.pull-right {
10023 margin-left: .3em;
10024 }
10025 .kernel_disconnected_icon:before {
10026 display: inline-block;
10027 font-family: FontAwesome;
10028 font-style: normal;
10029 font-weight: normal;
10030 line-height: 1;
10031 -webkit-font-smoothing: antialiased;
10032 -moz-osx-font-smoothing: grayscale;
10033 content: "\f127";
10034 }
10035 .kernel_disconnected_icon:before.pull-left {
10036 margin-right: .3em;
10037 }
10038 .kernel_disconnected_icon:before.pull-right {
10039 margin-left: .3em;
10040 }
10009 10041 .notification_widget {
10010 10042 color: #777777;
10011 10043 padding: 1px 12px;
@@ -5,7 +5,7 b' define(['
5 5 "widgets/js/manager",
6 6 "widgets/js/widget_bool",
7 7 "widgets/js/widget_button",
8 "widgets/js/widget_container",
8 "widgets/js/widget_box",
9 9 "widgets/js/widget_float",
10 10 "widgets/js/widget_image",
11 11 "widgets/js/widget_int",
@@ -7,11 +7,10 b' define(['
7 7 "bootstrap",
8 8 ], function(widget, $){
9 9
10 var ContainerView = widget.DOMWidgetView.extend({
10 var BoxView = widget.DOMWidgetView.extend({
11 11 initialize: function(){
12 12 // Public constructor
13 ContainerView.__super__.initialize.apply(this, arguments);
14 this.update_children([], this.model.get('children'));
13 BoxView.__super__.initialize.apply(this, arguments);
15 14 this.model.on('change:children', function(model, value) {
16 15 this.update_children(model.previous('children'), value);
17 16 }, this);
@@ -19,7 +18,9 b' define(['
19 18
20 19 render: function(){
21 20 // Called when view is rendered.
22 this.$el.addClass('widget-container').addClass('vbox');
21 this.$box = this.$el;
22 this.$box.addClass('widget-box');
23 this.update_children([], this.model.get('children'));
23 24 },
24 25
25 26 update_children: function(old_list, new_list) {
@@ -37,7 +38,7 b' define(['
37 38 add_child_model: function(model) {
38 39 // Called when a model is added to the children list.
39 40 var view = this.create_child_view(model);
40 this.$el.append(view.$el);
41 this.$box.append(view.$el);
41 42
42 43 // Trigger the displayed event of the child view.
43 44 this.after_displayed(function() {
@@ -45,9 +46,54 b' define(['
45 46 });
46 47 },
47 48 });
48
49 49
50 var PopupView = widget.DOMWidgetView.extend({
50
51 var FlexBoxView = BoxView.extend({
52 render: function(){
53 FlexBoxView.__super__.render.apply(this);
54 this.model.on('change:orientation', this.update_orientation, this);
55 this.model.on('change:flex', this._flex_changed, this);
56 this.model.on('change:pack', this._pack_changed, this);
57 this.model.on('change:align', this._align_changed, this);
58 this._flex_changed();
59 this._pack_changed();
60 this._align_changed();
61 this.update_orientation();
62 },
63
64 update_orientation: function(){
65 var orientation = this.model.get("orientation");
66 if (orientation == "vertical") {
67 this.$box.removeClass("hbox").addClass("vbox");
68 } else {
69 this.$box.removeClass("vbox").addClass("hbox");
70 }
71 },
72
73 _flex_changed: function(){
74 if (this.model.previous('flex')) {
75 this.$box.removeClass('box-flex' + this.model.previous('flex'));
76 }
77 this.$box.addClass('box-flex' + this.model.get('flex'));
78 },
79
80 _pack_changed: function(){
81 if (this.model.previous('pack')) {
82 this.$box.removeClass(this.model.previous('pack'));
83 }
84 this.$box.addClass(this.model.get('pack'));
85 },
86
87 _align_changed: function(){
88 if (this.model.previous('align')) {
89 this.$box.removeClass('align-' + this.model.previous('align'));
90 }
91 this.$box.addClass('align-' + this.model.get('align'));
92 },
93 });
94
95 var PopupView = BoxView.extend({
96
51 97 render: function(){
52 98 // Called when view is rendered.
53 99 var that = this;
@@ -130,11 +176,11 b' define(['
130 176 this.$title = $('<div />')
131 177 .addClass('widget-modal-title')
132 178 .html("&nbsp;")
133 .appendTo(this.$title_bar);
134 this.$body = $('<div />')
179 .appendTo(this.$title_bar);
180 this.$box = $('<div />')
135 181 .addClass('modal-body')
136 182 .addClass('widget-modal-body')
137 .addClass('widget-container')
183 .addClass('widget-box')
138 184 .addClass('vbox')
139 185 .appendTo(this.$window);
140 186
@@ -149,7 +195,7 b' define(['
149 195 this.$window.draggable({handle: '.popover-title', snap: '#notebook, .modal', snapMode: 'both'});
150 196 this.$window.resizable();
151 197 this.$window.on('resize', function(){
152 that.$body.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
198 that.$box.outerHeight(that.$window.innerHeight() - that.$title_bar.outerHeight());
153 199 });
154 200
155 201 this._shown_once = false;
@@ -203,29 +249,6 b' define(['
203 249 this.$window.css('z-index', max_zindex);
204 250 },
205 251
206 update_children: function(old_list, new_list) {
207 // Called when the children list is modified.
208 this.do_diff(old_list, new_list,
209 $.proxy(this.remove_child_model, this),
210 $.proxy(this.add_child_model, this));
211 },
212
213 remove_child_model: function(model) {
214 // Called when a child is removed from children list.
215 this.pop_child_view(model).remove();
216 },
217
218 add_child_model: function(model) {
219 // Called when a child is added to children list.
220 var view = this.create_child_view(model);
221 this.$body.append(view.$el);
222
223 // Trigger the displayed event of the child view.
224 this.after_displayed(function() {
225 view.trigger('displayed');
226 });
227 },
228
229 252 update: function(){
230 253 // Update the contents of this view
231 254 //
@@ -277,7 +300,8 b' define(['
277 300 });
278 301
279 302 return {
280 'ContainerView': ContainerView,
303 'BoxView': BoxView,
281 304 'PopupView': PopupView,
305 'FlexBoxView': FlexBoxView,
282 306 };
283 307 });
@@ -226,7 +226,7 b''
226 226 margin : 5px;
227 227
228 228 .start();
229 .widget-container();
229 .widget-box();
230 230 }
231 231
232 232 .widget-hbox {
@@ -258,7 +258,7 b''
258 258 }
259 259
260 260 .widget-modal {
261 /* ContainerWidget - ModalView */
261 /* Box - ModalView */
262 262 overflow : hidden;
263 263 position : absolute !important;
264 264 top : 0px;
@@ -267,12 +267,12 b''
267 267 }
268 268
269 269 .widget-modal-body {
270 /* ContainerWidget - ModalView Body */
270 /* Box - ModalView Body */
271 271 max-height: none !important;
272 272 }
273 273
274 .widget-container {
275 /* ContainerWidget */
274 .widget-box {
275 /* Box */
276 276 .border-box-sizing();
277 277 .align-start();
278 278 }
@@ -1,12 +1,12 b''
1 1
2 2 //
3 // Miscellaneous javascript tests
3 // Kernel tests
4 4 //
5 5 casper.notebook_test(function () {
6 6 this.evaluate(function () {
7 7 IPython.notebook.kernel.kernel_info(
8 8 function(msg){
9 IPython._kernel_info_response = msg;
9 IPython._kernel_info_response = msg;
10 10 })
11 11 });
12 12
@@ -24,5 +24,41 b' casper.notebook_test(function () {'
24 24 this.test.assertTrue( kernel_info_response.msg_type === 'kernel_info_reply', 'Kernel info request return kernel_info_reply');
25 25 this.test.assertTrue( kernel_info_response.content !== undefined, 'Kernel_info_reply is not undefined');
26 26 });
27
27
28 this.thenEvaluate(function () {
29 var kernel = IPython.notebook.session.kernel;
30 IPython._channels = [
31 kernel.shell_channel,
32 kernel.iopub_channel,
33 kernel.stdin_channel
34 ];
35 kernel.kill();
36 });
37
38 this.waitFor(function () {
39 return this.evaluate(function(){
40 for (var i=0; i < IPython._channels.length; i++) {
41 var ws = IPython._channels[i];
42 if (ws.readyState !== ws.CLOSED) {
43 return false;
44 }
45 }
46 return true;
47 });
48 });
49
50 this.then(function () {
51 var states = this.evaluate(function() {
52 var states = [];
53 for (var i = 0; i < IPython._channels.length; i++) {
54 states.push(IPython._channels[i].readyState);
55 }
56 return states;
57 });
58
59 for (var i = 0; i < states.length; i++) {
60 this.test.assertEquals(states[i], WebSocket.CLOSED,
61 "Kernel.kill closes websockets[" + i + "]");
62 }
63 });
28 64 });
@@ -147,7 +147,7 b' casper.notebook_test(function () {'
147 147 var textbox = {};
148 148 throttle_index = this.append_cell(
149 149 'import time\n' +
150 'textbox = widgets.TextWidget()\n' +
150 'textbox = widgets.Text()\n' +
151 151 'display(textbox)\n' +
152 152 'textbox.add_class("my-throttle-textbox", selector="input")\n' +
153 153 'def handle_change(name, old, new):\n' +
@@ -7,8 +7,8 b' casper.notebook_test(function () {'
7 7 this.execute_cell_then(index);
8 8
9 9 var bool_index = this.append_cell(
10 'bool_widgets = [widgets.CheckboxWidget(description="Title", value=True),\n' +
11 ' widgets.ToggleButtonWidget(description="Title", value=True)]\n' +
10 'bool_widgets = [widgets.Checkbox(description="Title", value=True),\n' +
11 ' widgets.ToggleButton(description="Title", value=True)]\n' +
12 12 'display(bool_widgets[0])\n' +
13 13 'display(bool_widgets[1])\n' +
14 14 'print("Success")');
@@ -7,8 +7,8 b' casper.notebook_test(function () {'
7 7 this.execute_cell_then(index);
8 8
9 9 var container_index = this.append_cell(
10 'container = widgets.ContainerWidget()\n' +
11 'button = widgets.ButtonWidget()\n'+
10 'container = widgets.Box()\n' +
11 'button = widgets.Button()\n'+
12 12 'container.children = [button]\n'+
13 13 'display(container)\n'+
14 14 'container.add_class("my-test-class")\n'+
@@ -23,7 +23,7 b' casper.notebook_test(function () {'
23 23 'Widget subarea exists.');
24 24
25 25 this.test.assert(this.cell_element_exists(index,
26 '.widget-area .widget-subarea .widget-container'),
26 '.widget-area .widget-subarea .widget-box'),
27 27 'Widget container exists.');
28 28
29 29 this.test.assert(this.cell_element_exists(index,
@@ -70,7 +70,7 b' casper.notebook_test(function () {'
70 70 'Display container child executed with correct output.');
71 71
72 72 this.test.assert(! this.cell_element_exists(index,
73 '.widget-area .widget-subarea .widget-container'),
73 '.widget-area .widget-subarea .widget-box'),
74 74 'Parent container not displayed.');
75 75
76 76 this.test.assert(this.cell_element_exists(index,
@@ -7,7 +7,7 b' casper.notebook_test(function () {'
7 7 this.execute_cell_then(index);
8 8
9 9 var button_index = this.append_cell(
10 'button = widgets.ButtonWidget(description="Title")\n' +
10 'button = widgets.Button(description="Title")\n' +
11 11 'display(button)\n' +
12 12 'print("Success")\n' +
13 13 'def handle_click(sender):\n' +
@@ -9,7 +9,7 b' casper.notebook_test(function () {'
9 9 var float_text = {};
10 10 float_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-float-text';
11 11 float_text.index = this.append_cell(
12 'float_widget = widgets.FloatTextWidget()\n' +
12 'float_widget = widgets.FloatText()\n' +
13 13 'display(float_widget)\n' +
14 14 'float_widget.add_class("my-second-float-text", selector="input")\n' +
15 15 'print(float_widget.model_id)\n');
@@ -59,8 +59,8 b' casper.notebook_test(function () {'
59 59 var slider = {};
60 60 slider.query = '.widget-area .widget-subarea .widget-hbox-single .slider';
61 61 slider.index = this.append_cell(
62 'floatrange = [widgets.BoundedFloatTextWidget(), \n' +
63 ' widgets.FloatSliderWidget()]\n' +
62 'floatrange = [widgets.BoundedFloatText(), \n' +
63 ' widgets.FloatSlider()]\n' +
64 64 '[display(floatrange[i]) for i in range(2)]\n' +
65 65 'print("Success")\n');
66 66 this.execute_cell_then(slider.index, function(index){
@@ -18,7 +18,7 b' casper.notebook_test(function () {'
18 18 var image_index = this.append_cell(
19 19 'import base64\n' +
20 20 'data = base64.b64decode("' + test_jpg + '")\n' +
21 'image = widgets.ImageWidget()\n' +
21 'image = widgets.Image()\n' +
22 22 'image.format = "jpeg"\n' +
23 23 'image.value = data\n' +
24 24 'image.width = "50px"\n' +
@@ -9,7 +9,7 b' casper.notebook_test(function () {'
9 9 var int_text = {};
10 10 int_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-int-text';
11 11 int_text.index = this.append_cell(
12 'int_widget = widgets.IntTextWidget()\n' +
12 'int_widget = widgets.IntText()\n' +
13 13 'display(int_widget)\n' +
14 14 'int_widget.add_class("my-second-int-text", selector="input")\n' +
15 15 'print(int_widget.model_id)\n');
@@ -44,10 +44,10 b' casper.notebook_test(function () {'
44 44 //values=["' + selection_values + '"[i] for i in range(4)]
45 45 selection_index = this.append_cell(
46 46 'values=["' + selection_values + '"[i] for i in range(4)]\n' +
47 'selection = [widgets.DropdownWidget(values=values),\n' +
48 ' widgets.ToggleButtonsWidget(values=values),\n' +
49 ' widgets.RadioButtonsWidget(values=values),\n' +
50 ' widgets.SelectWidget(values=values)]\n' +
47 'selection = [widgets.Dropdown(values=values),\n' +
48 ' widgets.ToggleButtons(values=values),\n' +
49 ' widgets.RadioButtons(values=values),\n' +
50 ' widgets.Select(values=values)]\n' +
51 51 '[display(selection[i]) for i in range(4)]\n' +
52 52 'for widget in selection:\n' +
53 53 ' def handle_change(name,old,new):\n' +
@@ -9,10 +9,10 b' casper.notebook_test(function () {'
9 9 // Test tab view
10 10 var multicontainer1_query = '.widget-area .widget-subarea div div.nav-tabs';
11 11 var multicontainer1_index = this.append_cell(
12 'multicontainer = widgets.TabWidget()\n' +
13 'page1 = widgets.TextWidget()\n' +
14 'page2 = widgets.TextWidget()\n' +
15 'page3 = widgets.TextWidget()\n' +
12 'multicontainer = widgets.Tab()\n' +
13 'page1 = widgets.Text()\n' +
14 'page2 = widgets.Text()\n' +
15 'page3 = widgets.Text()\n' +
16 16 'multicontainer.children = [page1, page2, page3]\n' +
17 17 'display(multicontainer)\n' +
18 18 'multicontainer.selected_index = 0\n' +
@@ -64,10 +64,10 b' casper.notebook_test(function () {'
64 64 // Test accordion view
65 65 var multicontainer2_query = '.widget-area .widget-subarea .panel-group';
66 66 var multicontainer2_index = this.append_cell(
67 'multicontainer = widgets.AccordionWidget()\n' +
68 'page1 = widgets.TextWidget()\n' +
69 'page2 = widgets.TextWidget()\n' +
70 'page3 = widgets.TextWidget()\n' +
67 'multicontainer = widgets.Accordion()\n' +
68 'page1 = widgets.Text()\n' +
69 'page2 = widgets.Text()\n' +
70 'page3 = widgets.Text()\n' +
71 71 'multicontainer.children = [page1, page2, page3]\n' +
72 72 'multicontainer.set_title(2, "good")\n' +
73 73 'display(multicontainer)\n' +
@@ -7,10 +7,10 b' casper.notebook_test(function () {'
7 7 this.execute_cell_then(index);
8 8
9 9 var string_index = this.append_cell(
10 'string_widget = [widgets.TextWidget(value = "xyz", placeholder = "abc"),\n' +
11 ' widgets.TextareaWidget(value = "xyz", placeholder = "def"),\n' +
12 ' widgets.HTMLWidget(value = "xyz"),\n' +
13 ' widgets.LatexWidget(value = "$\\\\LaTeX{}$")]\n' +
10 'string_widget = [widgets.Text(value = "xyz", placeholder = "abc"),\n' +
11 ' widgets.Textarea(value = "xyz", placeholder = "def"),\n' +
12 ' widgets.HTML(value = "xyz"),\n' +
13 ' widgets.Latex(value = "$\\\\LaTeX{}$")]\n' +
14 14 '[display(widget) for widget in string_widget]\n'+
15 15 'print("Success")');
16 16 this.execute_cell_then(string_index, function(index){
@@ -1,12 +1,23 b''
1 1 from .widget import Widget, DOMWidget, CallbackDispatcher
2 2
3 from .widget_bool import Checkbox, ToggleButton
4 from .widget_button import Button
5 from .widget_box import Box, Popup, FlexBox, HBox, VBox
6 from .widget_float import FloatText, BoundedFloatText, FloatSlider, FloatProgress, FloatRangeSlider
7 from .widget_image import Image
8 from .widget_int import IntText, BoundedIntText, IntSlider, IntProgress, IntRangeSlider
9 from .widget_selection import RadioButtons, ToggleButtons, Dropdown, Select
10 from .widget_selectioncontainer import Tab, Accordion
11 from .widget_string import HTML, Latex, Text, Textarea
12 from .interaction import interact, interactive, fixed
13
14 # Deprecated classes
3 15 from .widget_bool import CheckboxWidget, ToggleButtonWidget
4 16 from .widget_button import ButtonWidget
5 from .widget_container import ContainerWidget, PopupWidget
6 from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget, FloatRangeSliderWidget
17 from .widget_box import ContainerWidget, PopupWidget
18 from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget
7 19 from .widget_image import ImageWidget
8 from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget, IntRangeSliderWidget
20 from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget
9 21 from .widget_selection import RadioButtonsWidget, ToggleButtonsWidget, DropdownWidget, SelectWidget
10 22 from .widget_selectioncontainer import TabWidget, AccordionWidget
11 23 from .widget_string import HTMLWidget, LatexWidget, TextWidget, TextareaWidget
12 from .interaction import interact, interactive, fixed
@@ -21,9 +21,9 b' except ImportError:'
21 21 from inspect import getcallargs
22 22
23 23 from IPython.core.getipython import get_ipython
24 from IPython.html.widgets import (Widget, TextWidget,
25 FloatSliderWidget, IntSliderWidget, CheckboxWidget, DropdownWidget,
26 ContainerWidget, DOMWidget)
24 from IPython.html.widgets import (Widget, Text,
25 FloatSlider, IntSlider, Checkbox, Dropdown,
26 Box, DOMWidget)
27 27 from IPython.display import display, clear_output
28 28 from IPython.utils.py3compat import string_types, unicode_type
29 29 from IPython.utils.traitlets import HasTraits, Any, Unicode
@@ -70,17 +70,17 b' def _get_min_max_value(min, max, value=None, step=None):'
70 70 def _widget_abbrev_single_value(o):
71 71 """Make widgets from single values, which can be used as parameter defaults."""
72 72 if isinstance(o, string_types):
73 return TextWidget(value=unicode_type(o))
73 return Text(value=unicode_type(o))
74 74 elif isinstance(o, dict):
75 return DropdownWidget(values=o)
75 return Dropdown(values=o)
76 76 elif isinstance(o, bool):
77 return CheckboxWidget(value=o)
77 return Checkbox(value=o)
78 78 elif isinstance(o, float):
79 79 min, max, value = _get_min_max_value(None, None, o)
80 return FloatSliderWidget(value=o, min=min, max=max)
80 return FloatSlider(value=o, min=min, max=max)
81 81 elif isinstance(o, int):
82 82 min, max, value = _get_min_max_value(None, None, o)
83 return IntSliderWidget(value=o, min=min, max=max)
83 return IntSlider(value=o, min=min, max=max)
84 84 else:
85 85 return None
86 86
@@ -89,13 +89,13 b' def _widget_abbrev(o):'
89 89 float_or_int = (float, int)
90 90 if isinstance(o, (list, tuple)):
91 91 if o and all(isinstance(x, string_types) for x in o):
92 return DropdownWidget(values=[unicode_type(k) for k in o])
92 return Dropdown(values=[unicode_type(k) for k in o])
93 93 elif _matches(o, (float_or_int, float_or_int)):
94 94 min, max, value = _get_min_max_value(o[0], o[1])
95 95 if all(isinstance(_, int) for _ in o):
96 cls = IntSliderWidget
96 cls = IntSlider
97 97 else:
98 cls = FloatSliderWidget
98 cls = FloatSlider
99 99 return cls(value=value, min=min, max=max)
100 100 elif _matches(o, (float_or_int, float_or_int, float_or_int)):
101 101 step = o[2]
@@ -103,9 +103,9 b' def _widget_abbrev(o):'
103 103 raise ValueError("step must be >= 0, not %r" % step)
104 104 min, max, value = _get_min_max_value(o[0], o[1], step=step)
105 105 if all(isinstance(_, int) for _ in o):
106 cls = IntSliderWidget
106 cls = IntSlider
107 107 else:
108 cls = FloatSliderWidget
108 cls = FloatSlider
109 109 return cls(value=value, min=min, max=max, step=step)
110 110 else:
111 111 return _widget_abbrev_single_value(o)
@@ -176,7 +176,7 b' def interactive(__interact_f, **kwargs):'
176 176 f = __interact_f
177 177 co = kwargs.pop('clear_output', True)
178 178 kwargs_widgets = []
179 container = ContainerWidget()
179 container = Box()
180 180 container.result = None
181 181 container.args = []
182 182 container.kwargs = dict()
@@ -92,7 +92,7 b' def test_single_value_string():'
92 92 c = interactive(f, a=a)
93 93 w = c.children[0]
94 94 check_widget(w,
95 cls=widgets.TextWidget,
95 cls=widgets.Text,
96 96 description='a',
97 97 value=a,
98 98 )
@@ -102,7 +102,7 b' def test_single_value_bool():'
102 102 c = interactive(f, a=a)
103 103 w = c.children[0]
104 104 check_widget(w,
105 cls=widgets.CheckboxWidget,
105 cls=widgets.Checkbox,
106 106 description='a',
107 107 value=a,
108 108 )
@@ -115,7 +115,7 b' def test_single_value_dict():'
115 115 c = interactive(f, d=d)
116 116 w = c.children[0]
117 117 check_widget(w,
118 cls=widgets.DropdownWidget,
118 cls=widgets.Dropdown,
119 119 description='d',
120 120 values=d,
121 121 value=next(iter(d.values())),
@@ -126,7 +126,7 b' def test_single_value_float():'
126 126 c = interactive(f, a=a)
127 127 w = c.children[0]
128 128 check_widget(w,
129 cls=widgets.FloatSliderWidget,
129 cls=widgets.FloatSlider,
130 130 description='a',
131 131 value=a,
132 132 min= -a if a > 0 else 3*a,
@@ -141,7 +141,7 b' def test_single_value_int():'
141 141 nt.assert_equal(len(c.children), 1)
142 142 w = c.children[0]
143 143 check_widget(w,
144 cls=widgets.IntSliderWidget,
144 cls=widgets.IntSlider,
145 145 description='a',
146 146 value=a,
147 147 min= -a if a > 0 else 3*a,
@@ -159,7 +159,7 b' def test_list_tuple_2_int():'
159 159 c = interactive(f, tup=(min, max), lis=[min, max])
160 160 nt.assert_equal(len(c.children), 2)
161 161 d = dict(
162 cls=widgets.IntSliderWidget,
162 cls=widgets.IntSlider,
163 163 min=min,
164 164 max=max,
165 165 step=1,
@@ -176,7 +176,7 b' def test_list_tuple_3_int():'
176 176 c = interactive(f, tup=(min, max, step), lis=[min, max, step])
177 177 nt.assert_equal(len(c.children), 2)
178 178 d = dict(
179 cls=widgets.IntSliderWidget,
179 cls=widgets.IntSlider,
180 180 min=min,
181 181 max=max,
182 182 step=step,
@@ -193,7 +193,7 b' def test_list_tuple_2_float():'
193 193 c = interactive(f, tup=(min, max), lis=[min, max])
194 194 nt.assert_equal(len(c.children), 2)
195 195 d = dict(
196 cls=widgets.FloatSliderWidget,
196 cls=widgets.FloatSlider,
197 197 min=min,
198 198 max=max,
199 199 step=.1,
@@ -212,7 +212,7 b' def test_list_tuple_3_float():'
212 212 c = interactive(f, tup=(min, max, step), lis=[min, max, step])
213 213 nt.assert_equal(len(c.children), 2)
214 214 d = dict(
215 cls=widgets.FloatSliderWidget,
215 cls=widgets.FloatSlider,
216 216 min=min,
217 217 max=max,
218 218 step=step,
@@ -227,7 +227,7 b' def test_list_tuple_str():'
227 227 c = interactive(f, tup=tuple(values), lis=list(values))
228 228 nt.assert_equal(len(c.children), 2)
229 229 d = dict(
230 cls=widgets.DropdownWidget,
230 cls=widgets.Dropdown,
231 231 value=first,
232 232 values=dvalues
233 233 )
@@ -253,15 +253,15 b' def test_defaults():'
253 253 c = interactive(f)
254 254 check_widgets(c,
255 255 n=dict(
256 cls=widgets.IntSliderWidget,
256 cls=widgets.IntSlider,
257 257 value=10,
258 258 ),
259 259 f=dict(
260 cls=widgets.FloatSliderWidget,
260 cls=widgets.FloatSlider,
261 261 value=4.5,
262 262 ),
263 263 g=dict(
264 cls=widgets.IntSliderWidget,
264 cls=widgets.IntSlider,
265 265 value=1,
266 266 ),
267 267 )
@@ -274,24 +274,24 b' def test_default_values():'
274 274 c = interactive(f)
275 275 check_widgets(c,
276 276 n=dict(
277 cls=widgets.IntSliderWidget,
277 cls=widgets.IntSlider,
278 278 value=10,
279 279 ),
280 280 f=dict(
281 cls=widgets.FloatSliderWidget,
281 cls=widgets.FloatSlider,
282 282 value=4.5,
283 283 ),
284 284 g=dict(
285 cls=widgets.IntSliderWidget,
285 cls=widgets.IntSlider,
286 286 value=5,
287 287 ),
288 288 h=dict(
289 cls=widgets.DropdownWidget,
289 cls=widgets.Dropdown,
290 290 values={'a': 1, 'b': 2},
291 291 value=2
292 292 ),
293 293 j=dict(
294 cls=widgets.DropdownWidget,
294 cls=widgets.Dropdown,
295 295 values={'hi':'hi', 'there':'there'},
296 296 value='there'
297 297 ),
@@ -305,34 +305,34 b' def test_default_out_of_bounds():'
305 305 c = interactive(f)
306 306 check_widgets(c,
307 307 f=dict(
308 cls=widgets.FloatSliderWidget,
308 cls=widgets.FloatSlider,
309 309 value=5.,
310 310 ),
311 311 h=dict(
312 cls=widgets.DropdownWidget,
312 cls=widgets.Dropdown,
313 313 values={'a': 1},
314 314 value=1,
315 315 ),
316 316 j=dict(
317 cls=widgets.DropdownWidget,
317 cls=widgets.Dropdown,
318 318 values={'hi':'hi', 'there':'there'},
319 319 value='hi',
320 320 ),
321 321 )
322 322
323 323 def test_annotations():
324 @annotate(n=10, f=widgets.FloatTextWidget())
324 @annotate(n=10, f=widgets.FloatText())
325 325 def f(n, f):
326 326 pass
327 327
328 328 c = interactive(f)
329 329 check_widgets(c,
330 330 n=dict(
331 cls=widgets.IntSliderWidget,
331 cls=widgets.IntSlider,
332 332 value=10,
333 333 ),
334 334 f=dict(
335 cls=widgets.FloatTextWidget,
335 cls=widgets.FloatText,
336 336 ),
337 337 )
338 338
@@ -344,11 +344,11 b' def test_priority():'
344 344 c = interactive(f, kwarg='kwarg')
345 345 check_widgets(c,
346 346 kwarg=dict(
347 cls=widgets.TextWidget,
347 cls=widgets.Text,
348 348 value='kwarg',
349 349 ),
350 350 annotate=dict(
351 cls=widgets.TextWidget,
351 cls=widgets.Text,
352 352 value='annotate',
353 353 ),
354 354 )
@@ -362,7 +362,7 b' def test_decorator_kwarg():'
362 362 nt.assert_equal(len(displayed), 1)
363 363 w = displayed[0].children[0]
364 364 check_widget(w,
365 cls=widgets.IntSliderWidget,
365 cls=widgets.IntSlider,
366 366 value=5,
367 367 )
368 368
@@ -375,7 +375,7 b' def test_decorator_no_call():'
375 375 nt.assert_equal(len(displayed), 1)
376 376 w = displayed[0].children[0]
377 377 check_widget(w,
378 cls=widgets.TextWidget,
378 cls=widgets.Text,
379 379 value='default',
380 380 )
381 381
@@ -388,7 +388,7 b' def test_call_interact():'
388 388 nt.assert_equal(len(displayed), 1)
389 389 w = displayed[0].children[0]
390 390 check_widget(w,
391 cls=widgets.TextWidget,
391 cls=widgets.Text,
392 392 value='default',
393 393 )
394 394
@@ -401,7 +401,7 b' def test_call_interact_kwargs():'
401 401 nt.assert_equal(len(displayed), 1)
402 402 w = displayed[0].children[0]
403 403 check_widget(w,
404 cls=widgets.IntSliderWidget,
404 cls=widgets.IntSlider,
405 405 value=10,
406 406 )
407 407
@@ -417,7 +417,7 b' def test_call_decorated_on_trait_change():'
417 417 nt.assert_equal(len(displayed), 1)
418 418 w = displayed[0].children[0]
419 419 check_widget(w,
420 cls=widgets.TextWidget,
420 cls=widgets.Text,
421 421 value='default',
422 422 )
423 423 # test calling the function directly
@@ -441,7 +441,7 b' def test_call_decorated_kwargs_on_trait_change():'
441 441 nt.assert_equal(len(displayed), 1)
442 442 w = displayed[0].children[0]
443 443 check_widget(w,
444 cls=widgets.TextWidget,
444 cls=widgets.Text,
445 445 value='kwarg',
446 446 )
447 447 # test calling the function directly
@@ -458,7 +458,7 b' def test_fixed():'
458 458 nt.assert_equal(len(c.children), 1)
459 459 w = c.children[0]
460 460 check_widget(w,
461 cls=widgets.TextWidget,
461 cls=widgets.Text,
462 462 value='text',
463 463 description='b',
464 464 )
@@ -467,22 +467,22 b' def test_default_description():'
467 467 c = interactive(f, b='text')
468 468 w = c.children[0]
469 469 check_widget(w,
470 cls=widgets.TextWidget,
470 cls=widgets.Text,
471 471 value='text',
472 472 description='b',
473 473 )
474 474
475 475 def test_custom_description():
476 c = interactive(f, b=widgets.TextWidget(value='text', description='foo'))
476 c = interactive(f, b=widgets.Text(value='text', description='foo'))
477 477 w = c.children[0]
478 478 check_widget(w,
479 cls=widgets.TextWidget,
479 cls=widgets.Text,
480 480 value='text',
481 481 description='foo',
482 482 )
483 483
484 484 def test_int_range_logic():
485 irsw = widgets.IntRangeSliderWidget
485 irsw = widgets.IntRangeSlider
486 486 w = irsw(value=(2, 4), min=0, max=6)
487 487 check_widget(w, cls=irsw, value=(2, 4), min=0, max=6)
488 488 w.value = (4, 2)
@@ -537,7 +537,7 b' def test_int_range_logic():'
537 537
538 538
539 539 def test_float_range_logic():
540 frsw = widgets.FloatRangeSliderWidget
540 frsw = widgets.FloatRangeSlider
541 541 w = frsw(value=(.2, .4), min=0., max=.6)
542 542 check_widget(w, cls=frsw, value=(.2, .4), min=0., max=.6)
543 543 w.value = (.4, .2)
@@ -588,4 +588,4 b' def test_float_range_logic():'
588 588 with nt.assert_raises(ValueError):
589 589 frsw(value=(2, 4), lower=3, upper=3)
590 590 with nt.assert_raises(ValueError):
591 frsw(min=.2, max=.1) No newline at end of file
591 frsw(min=.2, max=.1)
@@ -1,4 +1,4 b''
1 """BoolWidget class.
1 """Bool class.
2 2
3 3 Represents a boolean using a widget.
4 4 """
@@ -15,20 +15,29 b' Represents a boolean using a widget.'
15 15 #-----------------------------------------------------------------------------
16 16 from .widget import DOMWidget
17 17 from IPython.utils.traitlets import Unicode, Bool
18 from IPython.utils.warn import DeprecatedClass
18 19
19 20 #-----------------------------------------------------------------------------
20 21 # Classes
21 22 #-----------------------------------------------------------------------------
22 class _BoolWidget(DOMWidget):
23 class _Bool(DOMWidget):
24 """A base class for creating widgets that represent booleans."""
23 25 value = Bool(False, help="Bool value", sync=True)
24 description = Unicode('', help="Description of the boolean (label).", sync=True)
26 description = Unicode('', help="Description of the boolean (label).", sync=True)
25 27 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
26 28
27 29
28 class CheckboxWidget(_BoolWidget):
30 class Checkbox(_Bool):
31 """Displays a boolean `value`."""
29 32 _view_name = Unicode('CheckboxView', sync=True)
30 33
31 34
32 class ToggleButtonWidget(_BoolWidget):
33 _view_name = Unicode('ToggleButtonView', sync=True)
35 class ToggleButton(_Bool):
36 """Displays a boolean `value`."""
34 37
38 _view_name = Unicode('ToggleButtonView', sync=True)
39
40
41 # Remove in IPython 4.0
42 CheckboxWidget = DeprecatedClass(Checkbox, 'CheckboxWidget')
43 ToggleButtonWidget = DeprecatedClass(ToggleButton, 'ToggleButtonWidget')
@@ -1,4 +1,4 b''
1 """ButtonWidget class.
1 """Button class.
2 2
3 3 Represents a button in the frontend using a widget. Allows user to listen for
4 4 click events on the button and trigger backend code when the clicks are fired.
@@ -16,11 +16,16 b' click events on the button and trigger backend code when the clicks are fired.'
16 16 #-----------------------------------------------------------------------------
17 17 from .widget import DOMWidget, CallbackDispatcher
18 18 from IPython.utils.traitlets import Unicode, Bool
19 from IPython.utils.warn import DeprecatedClass
19 20
20 21 #-----------------------------------------------------------------------------
21 22 # Classes
22 23 #-----------------------------------------------------------------------------
23 class ButtonWidget(DOMWidget):
24 class Button(DOMWidget):
25 """Button widget.
26
27 This widget has an `on_click` method that allows you to listen for the
28 user clicking on the button. The click event itself is stateless."""
24 29 _view_name = Unicode('ButtonView', sync=True)
25 30
26 31 # Keys
@@ -29,7 +34,7 b' class ButtonWidget(DOMWidget):'
29 34
30 35 def __init__(self, **kwargs):
31 36 """Constructor"""
32 super(ButtonWidget, self).__init__(**kwargs)
37 super(Button, self).__init__(**kwargs)
33 38 self._click_handlers = CallbackDispatcher()
34 39 self.on_msg(self._handle_button_msg)
35 40
@@ -54,3 +59,7 b' class ButtonWidget(DOMWidget):'
54 59 Content of the msg."""
55 60 if content.get('event', '') == 'click':
56 61 self._click_handlers(self)
62
63
64 # Remove in IPython 4.0
65 ButtonWidget = DeprecatedClass(Button, 'ButtonWidget')
@@ -1,4 +1,4 b''
1 """FloatWidget class.
1 """Float class.
2 2
3 3 Represents an unbounded float using a widget.
4 4 """
@@ -15,17 +15,18 b' Represents an unbounded float using a widget.'
15 15 #-----------------------------------------------------------------------------
16 16 from .widget import DOMWidget
17 17 from IPython.utils.traitlets import Unicode, CFloat, Bool, Enum, Tuple
18 from IPython.utils.warn import DeprecatedClass
18 19
19 20 #-----------------------------------------------------------------------------
20 21 # Classes
21 22 #-----------------------------------------------------------------------------
22 class _FloatWidget(DOMWidget):
23 value = CFloat(0.0, help="Float value", sync=True)
23 class _Float(DOMWidget):
24 value = CFloat(0.0, help="Float value", sync=True)
24 25 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 26 description = Unicode(help="Description of the value this widget represents", sync=True)
26 27
27 28
28 class _BoundedFloatWidget(_FloatWidget):
29 class _BoundedFloat(_Float):
29 30 max = CFloat(100.0, help="Max value", sync=True)
30 31 min = CFloat(0.0, help="Min value", sync=True)
31 32 step = CFloat(0.1, help="Minimum step that the value can take (ignored by some views)", sync=True)
@@ -42,26 +43,26 b' class _BoundedFloatWidget(_FloatWidget):'
42 43 self.value = min(max(new, self.min), self.max)
43 44
44 45
45 class FloatTextWidget(_FloatWidget):
46 class FloatText(_Float):
46 47 _view_name = Unicode('FloatTextView', sync=True)
47 48
48 49
49 class BoundedFloatTextWidget(_BoundedFloatWidget):
50 class BoundedFloatText(_BoundedFloat):
50 51 _view_name = Unicode('FloatTextView', sync=True)
51 52
52 53
53 class FloatSliderWidget(_BoundedFloatWidget):
54 class FloatSlider(_BoundedFloat):
54 55 _view_name = Unicode('FloatSliderView', sync=True)
55 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
56 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
56 57 help="Vertical or horizontal.", sync=True)
57 58 range = Bool(False, help="Display a range selector", sync=True)
58 59 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
59 60
60 61
61 class FloatProgressWidget(_BoundedFloatWidget):
62 class FloatProgress(_BoundedFloat):
62 63 _view_name = Unicode('ProgressView', sync=True)
63 64
64 class _FloatRangeWidget(_FloatWidget):
65 class _FloatRange(_Float):
65 66 value = Tuple(CFloat, CFloat, default_value=(0.0, 1.0), help="Tuple of (lower, upper) bounds", sync=True)
66 67 lower = CFloat(0.0, help="Lower bound", sync=False)
67 68 upper = CFloat(1.0, help="Upper bound", sync=False)
@@ -90,14 +91,14 b' class _FloatRangeWidget(_FloatWidget):'
90 91 elif name == 'upper':
91 92 self.value = (self.value[0], new)
92 93
93 class _BoundedFloatRangeWidget(_FloatRangeWidget):
94 class _BoundedFloatRange(_FloatRange):
94 95 step = CFloat(1.0, help="Minimum step that the value can take (ignored by some views)", sync=True)
95 96 max = CFloat(100.0, help="Max value", sync=True)
96 97 min = CFloat(0.0, help="Min value", sync=True)
97 98
98 99 def __init__(self, *pargs, **kwargs):
99 100 any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
100 _FloatRangeWidget.__init__(self, *pargs, **kwargs)
101 _FloatRange.__init__(self, *pargs, **kwargs)
101 102
102 103 # ensure a minimal amount of sanity
103 104 if self.min > self.max:
@@ -156,9 +157,15 b' class _BoundedFloatRangeWidget(_FloatRangeWidget):'
156 157 self.lower = low
157 158
158 159
159 class FloatRangeSliderWidget(_BoundedFloatRangeWidget):
160 class FloatRangeSlider(_BoundedFloatRange):
160 161 _view_name = Unicode('FloatSliderView', sync=True)
161 162 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
162 163 help="Vertical or horizontal.", sync=True)
163 164 range = Bool(True, help="Display a range selector", sync=True)
164 165 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
166
167 # Remove in IPython 4.0
168 FloatTextWidget = DeprecatedClass(FloatText, 'FloatTextWidget')
169 BoundedFloatTextWidget = DeprecatedClass(BoundedFloatText, 'BoundedFloatTextWidget')
170 FloatSliderWidget = DeprecatedClass(FloatSlider, 'FloatSliderWidget')
171 FloatProgressWidget = DeprecatedClass(FloatProgress, 'FloatProgressWidget')
@@ -1,4 +1,4 b''
1 """ImageWidget class.
1 """Image class.
2 2
3 3 Represents an image in the frontend using a widget.
4 4 """
@@ -17,11 +17,18 b' import base64'
17 17
18 18 from .widget import DOMWidget
19 19 from IPython.utils.traitlets import Unicode, CUnicode, Bytes
20 from IPython.utils.warn import DeprecatedClass
20 21
21 22 #-----------------------------------------------------------------------------
22 23 # Classes
23 24 #-----------------------------------------------------------------------------
24 class ImageWidget(DOMWidget):
25 class Image(DOMWidget):
26 """Displays an image as a widget.
27
28 The `value` of this widget accepts a byte string. The byte string is the raw
29 image data that you want the browser to display. You can explicitly define
30 the format of the byte string using the `format` trait (which defaults to
31 "png")."""
25 32 _view_name = Unicode('ImageView', sync=True)
26 33
27 34 # Define the custom state properties to sync with the front-end
@@ -33,3 +40,7 b' class ImageWidget(DOMWidget):'
33 40 value = Bytes()
34 41 def _value_changed(self, name, old, new):
35 42 self._b64value = base64.b64encode(new)
43
44
45 # Remove in IPython 4.0
46 ImageWidget = DeprecatedClass(Image, 'ImageWidget')
@@ -1,4 +1,4 b''
1 """IntWidget class.
1 """Int class.
2 2
3 3 Represents an unbounded int using a widget.
4 4 """
@@ -15,17 +15,21 b' Represents an unbounded int using a widget.'
15 15 #-----------------------------------------------------------------------------
16 16 from .widget import DOMWidget
17 17 from IPython.utils.traitlets import Unicode, CInt, Bool, Enum, Tuple
18 from IPython.utils.warn import DeprecatedClass
18 19
19 20 #-----------------------------------------------------------------------------
20 21 # Classes
21 22 #-----------------------------------------------------------------------------
22 class _IntWidget(DOMWidget):
23 value = CInt(0, help="Int value", sync=True)
23 class _Int(DOMWidget):
24 """Base class used to create widgets that represent an int."""
25 value = CInt(0, help="Int value", sync=True)
24 26 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 27 description = Unicode(help="Description of the value this widget represents", sync=True)
26 28
27 29
28 class _BoundedIntWidget(_IntWidget):
30 class _BoundedInt(_Int):
31 """Base class used to create widgets that represent a int that is bounded
32 by a minium and maximum."""
29 33 step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
30 34 max = CInt(100, help="Max value", sync=True)
31 35 min = CInt(0, help="Min value", sync=True)
@@ -41,26 +45,30 b' class _BoundedIntWidget(_IntWidget):'
41 45 self.value = min(max(new, self.min), self.max)
42 46
43 47
44 class IntTextWidget(_IntWidget):
48 class IntText(_Int):
49 """Textbox widget that represents a int."""
45 50 _view_name = Unicode('IntTextView', sync=True)
46 51
47 52
48 class BoundedIntTextWidget(_BoundedIntWidget):
53 class BoundedIntText(_BoundedInt):
54 """Textbox widget that represents a int bounded by a minimum and maximum value."""
49 55 _view_name = Unicode('IntTextView', sync=True)
50 56
51 57
52 class IntSliderWidget(_BoundedIntWidget):
58 class IntSlider(_BoundedInt):
59 """Slider widget that represents a int bounded by a minimum and maximum value."""
53 60 _view_name = Unicode('IntSliderView', sync=True)
54 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
61 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
55 62 help="Vertical or horizontal.", sync=True)
56 63 range = Bool(False, help="Display a range selector", sync=True)
57 64 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
58 65
59 66
60 class IntProgressWidget(_BoundedIntWidget):
67 class IntProgress(_BoundedInt):
68 """Progress bar that represents a int bounded by a minimum and maximum value."""
61 69 _view_name = Unicode('ProgressView', sync=True)
62 70
63 class _IntRangeWidget(_IntWidget):
71 class _IntRange(_Int):
64 72 value = Tuple(CInt, CInt, default_value=(0, 1), help="Tuple of (lower, upper) bounds", sync=True)
65 73 lower = CInt(0, help="Lower bound", sync=False)
66 74 upper = CInt(1, help="Upper bound", sync=False)
@@ -89,14 +97,14 b' class _IntRangeWidget(_IntWidget):'
89 97 elif name == 'upper':
90 98 self.value = (self.value[0], new)
91 99
92 class _BoundedIntRangeWidget(_IntRangeWidget):
100 class _BoundedIntRange(_IntRange):
93 101 step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
94 102 max = CInt(100, help="Max value", sync=True)
95 103 min = CInt(0, help="Min value", sync=True)
96 104
97 105 def __init__(self, *pargs, **kwargs):
98 106 any_value_given = 'value' in kwargs or 'upper' in kwargs or 'lower' in kwargs
99 _IntRangeWidget.__init__(self, *pargs, **kwargs)
107 _IntRange.__init__(self, *pargs, **kwargs)
100 108
101 109 # ensure a minimal amount of sanity
102 110 if self.min > self.max:
@@ -153,9 +161,15 b' class _BoundedIntRangeWidget(_IntRangeWidget):'
153 161 self.upper = high
154 162 self.lower = low
155 163
156 class IntRangeSliderWidget(_BoundedIntRangeWidget):
164 class IntRangeSlider(_BoundedIntRange):
157 165 _view_name = Unicode('IntSliderView', sync=True)
158 166 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
159 167 help="Vertical or horizontal.", sync=True)
160 168 range = Bool(True, help="Display a range selector", sync=True)
161 169 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
170
171 # Remove in IPython 4.0
172 IntTextWidget = DeprecatedClass(IntText, 'IntTextWidget')
173 BoundedIntTextWidget = DeprecatedClass(BoundedIntText, 'BoundedIntTextWidget')
174 IntSliderWidget = DeprecatedClass(IntSlider, 'IntSliderWidget')
175 IntProgressWidget = DeprecatedClass(IntProgress, 'IntProgressWidget')
@@ -1,4 +1,4 b''
1 """SelectionWidget classes.
1 """Selection classes.
2 2
3 3 Represents an enumeration using a widget.
4 4 """
@@ -20,11 +20,12 b' from threading import Lock'
20 20 from .widget import DOMWidget
21 21 from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict, TraitError
22 22 from IPython.utils.py3compat import unicode_type
23 from IPython.utils.warn import DeprecatedClass
23 24
24 25 #-----------------------------------------------------------------------------
25 26 # SelectionWidget
26 27 #-----------------------------------------------------------------------------
27 class _SelectionWidget(DOMWidget):
28 class _Selection(DOMWidget):
28 29 """Base class for Selection widgets
29 30
30 31 ``values`` can be specified as a list or dict. If given as a list,
@@ -109,17 +110,30 b' class _SelectionWidget(DOMWidget):'
109 110 self.value_lock.release()
110 111
111 112
112 class ToggleButtonsWidget(_SelectionWidget):
113 class ToggleButtons(_Selection):
114 """Group of toggle buttons that represent an enumeration. Only one toggle
115 button can be toggled at any point in time."""
113 116 _view_name = Unicode('ToggleButtonsView', sync=True)
114 117
115 118
116 class DropdownWidget(_SelectionWidget):
119 class Dropdown(_Selection):
120 """Allows you to select a single item from a dropdown."""
117 121 _view_name = Unicode('DropdownView', sync=True)
118 122
119 123
120 class RadioButtonsWidget(_SelectionWidget):
124 class RadioButtons(_Selection):
125 """Group of radio buttons that represent an enumeration. Only one radio
126 button can be toggled at any point in time."""
121 127 _view_name = Unicode('RadioButtonsView', sync=True)
122 128
123 129
124 class SelectWidget(_SelectionWidget):
130 class Select(_Selection):
131 """Listbox that only allows one item to be selected at any given time."""
125 132 _view_name = Unicode('SelectView', sync=True)
133
134
135 # Remove in IPython 4.0
136 ToggleButtonsWidget = DeprecatedClass(ToggleButtons, 'ToggleButtonsWidget')
137 DropdownWidget = DeprecatedClass(Dropdown, 'DropdownWidget')
138 RadioButtonsWidget = DeprecatedClass(RadioButtons, 'RadioButtonsWidget')
139 SelectWidget = DeprecatedClass(Select, 'SelectWidget')
@@ -1,4 +1,4 b''
1 """SelectionContainerWidget class.
1 """SelectionContainer class.
2 2
3 3 Represents a multipage container that can be used to group other widgets into
4 4 pages.
@@ -14,13 +14,15 b' pages.'
14 14 #-----------------------------------------------------------------------------
15 15 # Imports
16 16 #-----------------------------------------------------------------------------
17 from .widget_container import ContainerWidget
17 from .widget_box import Box
18 18 from IPython.utils.traitlets import Unicode, Dict, CInt
19 from IPython.utils.warn import DeprecatedClass
19 20
20 21 #-----------------------------------------------------------------------------
21 22 # Classes
22 23 #-----------------------------------------------------------------------------
23 class _SelectionContainerWidget(ContainerWidget):
24 class _SelectionContainer(Box):
25 """Base class used to display multiple child widgets."""
24 26 _titles = Dict(help="Titles of the pages", sync=True)
25 27 selected_index = CInt(0, sync=True)
26 28
@@ -50,9 +52,16 b' class _SelectionContainerWidget(ContainerWidget):'
50 52 return None
51 53
52 54
53 class AccordionWidget(_SelectionContainerWidget):
55 class Accordion(_SelectionContainer):
56 """Displays children each on a separate accordion page."""
54 57 _view_name = Unicode('AccordionView', sync=True)
55 58
56 59
57 class TabWidget(_SelectionContainerWidget):
60 class Tab(_SelectionContainer):
61 """Displays children each on a separate accordion tab."""
58 62 _view_name = Unicode('TabView', sync=True)
63
64
65 # Remove in IPython 4.0
66 AccordionWidget = DeprecatedClass(Accordion, 'AccordionWidget')
67 TabWidget = DeprecatedClass(Tab, 'TabWidget')
@@ -1,4 +1,4 b''
1 """StringWidget class.
1 """String class.
2 2
3 3 Represents a unicode string using a widget.
4 4 """
@@ -15,37 +15,44 b' Represents a unicode string using a widget.'
15 15 #-----------------------------------------------------------------------------
16 16 from .widget import DOMWidget, CallbackDispatcher
17 17 from IPython.utils.traitlets import Unicode, Bool
18 from IPython.utils.warn import DeprecatedClass
18 19
19 20 #-----------------------------------------------------------------------------
20 21 # Classes
21 22 #-----------------------------------------------------------------------------
22 class _StringWidget(DOMWidget):
23 class _String(DOMWidget):
24 """Base class used to create widgets that represent a string."""
23 25 value = Unicode(help="String value", sync=True)
24 26 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 27 description = Unicode(help="Description of the value this widget represents", sync=True)
26 28 placeholder = Unicode("", help="Placeholder text to display when nothing has been typed", sync=True)
27 29
28 30
29 class HTMLWidget(_StringWidget):
31 class HTML(_String):
32 """Renders the string `value` as HTML."""
30 33 _view_name = Unicode('HTMLView', sync=True)
31 34
32 35
33 class LatexWidget(_StringWidget):
36 class Latex(_String):
37 """Renders math inside the string `value` as Latex (requires $ $ or $$ $$
38 and similar latex tags)."""
34 39 _view_name = Unicode('LatexView', sync=True)
35 40
36 41
37 class TextareaWidget(_StringWidget):
42 class Textarea(_String):
43 """Multiline text area widget."""
38 44 _view_name = Unicode('TextareaView', sync=True)
39 45
40 46 def scroll_to_bottom(self):
41 47 self.send({"method": "scroll_to_bottom"})
42 48
43 49
44 class TextWidget(_StringWidget):
50 class Text(_String):
51 """Single line textbox widget."""
45 52 _view_name = Unicode('TextView', sync=True)
46 53
47 54 def __init__(self, **kwargs):
48 super(TextWidget, self).__init__(**kwargs)
55 super(Text, self).__init__(**kwargs)
49 56 self._submission_callbacks = CallbackDispatcher()
50 57 self.on_msg(self._handle_string_msg)
51 58
@@ -71,3 +78,10 b' class TextWidget(_StringWidget):'
71 78 remove: bool (optional)
72 79 Whether to unregister the callback"""
73 80 self._submission_callbacks.register_callback(callback, remove=remove)
81
82
83 # Remove in IPython 4.0
84 HTMLWidget = DeprecatedClass(HTML, 'HTMLWidget')
85 LatexWidget = DeprecatedClass(Latex, 'LatexWidget')
86 TextareaWidget = DeprecatedClass(Textarea, 'TextareaWidget')
87 TextWidget = DeprecatedClass(Text, 'TextWidget')
@@ -8,7 +8,7 b' pjoin = os.path.join'
8 8
9 9 from IPython.utils.path import get_ipython_dir
10 10 from IPython.utils.py3compat import PY3
11 from IPython.utils.traitlets import HasTraits, List, Unicode, Dict
11 from IPython.utils.traitlets import HasTraits, List, Unicode, Dict, Any
12 12
13 13 if os.name == 'nt':
14 14 programdata = os.environ.get('PROGRAMDATA', None)
@@ -36,18 +36,12 b' class KernelSpec(HasTraits):'
36 36 argv = List()
37 37 display_name = Unicode()
38 38 language = Unicode()
39 codemirror_mode = None
39 codemirror_mode = Any() # can be unicode or dict
40 40 env = Dict()
41
42 41 resource_dir = Unicode()
43 42
44 def __init__(self, resource_dir, argv, display_name, language,
45 codemirror_mode=None):
46 super(KernelSpec, self).__init__(resource_dir=resource_dir, argv=argv,
47 display_name=display_name, language=language,
48 codemirror_mode=codemirror_mode)
49 if not self.codemirror_mode:
50 self.codemirror_mode = self.language
43 def _codemirror_mode_default(self):
44 return self.language
51 45
52 46 @classmethod
53 47 def from_resource_dir(cls, resource_dir):
@@ -61,3 +61,18 b' def getoutput(cmd):'
61 61 myError = reg.StandardError
62 62 error = myError.ReadToEnd()
63 63 return output
64
65 def check_pid(pid):
66 """
67 Check if a process with the given PID (pid) exists
68 """
69 try:
70 System.Diagnostics.Process.GetProcessById(pid)
71 # process with given pid is running
72 return True
73 except System.InvalidOperationException:
74 # process wasn't started by this object (but is running)
75 return True
76 except System.ArgumentException:
77 # process with given pid isn't running
78 return False
@@ -23,7 +23,7 b' import sys'
23 23 if sys.platform == 'win32':
24 24 from ._process_win32 import _find_cmd, system, getoutput, arg_split, check_pid
25 25 elif sys.platform == 'cli':
26 from ._process_cli import _find_cmd, system, getoutput, arg_split
26 from ._process_cli import _find_cmd, system, getoutput, arg_split, check_pid
27 27 else:
28 28 from ._process_posix import _find_cmd, system, getoutput, arg_split, check_pid
29 29
@@ -406,6 +406,13 b' class TestHasTraits(TestCase):'
406 406 a = A()
407 407 self.assertEqual(a.trait_metadata('i','config_key'), 'MY_VALUE')
408 408
409 def test_trait_metadata_default(self):
410 class A(HasTraits):
411 i = Int()
412 a = A()
413 self.assertEqual(a.trait_metadata('i', 'config_key'), None)
414 self.assertEqual(a.trait_metadata('i', 'config_key', 'default'), 'default')
415
409 416 def test_traits(self):
410 417 class A(HasTraits):
411 418 i = Int
@@ -458,8 +458,8 b' class TraitType(object):'
458 458 % (self.name, self.info(), repr_type(value))
459 459 raise TraitError(e)
460 460
461 def get_metadata(self, key):
462 return getattr(self, '_metadata', {}).get(key, None)
461 def get_metadata(self, key, default=None):
462 return getattr(self, '_metadata', {}).get(key, default)
463 463
464 464 def set_metadata(self, key, value):
465 465 getattr(self, '_metadata', {})[key] = value
@@ -728,7 +728,7 b' class HasTraits(py3compat.with_metaclass(MetaHasTraits, object)):'
728 728
729 729 return result
730 730
731 def trait_metadata(self, traitname, key):
731 def trait_metadata(self, traitname, key, default=None):
732 732 """Get metadata values for trait by key."""
733 733 try:
734 734 trait = getattr(self.__class__, traitname)
@@ -736,7 +736,7 b' class HasTraits(py3compat.with_metaclass(MetaHasTraits, object)):'
736 736 raise TraitError("Class %s does not have a trait named %s" %
737 737 (self.__class__.__name__, traitname))
738 738 else:
739 return trait.get_metadata(key)
739 return trait.get_metadata(key, default)
740 740
741 741 #-----------------------------------------------------------------------------
742 742 # Actual TraitTypes implementations/subclasses
@@ -16,6 +16,7 b" Utilities for warnings. Shoudn't we just use the built in warnings module."
16 16 from __future__ import print_function
17 17
18 18 import sys
19 import warnings
19 20
20 21 from IPython.utils import io
21 22
@@ -65,3 +66,16 b' def fatal(msg,exit_val=1):'
65 66
66 67 warn(msg,exit_val=exit_val,level=4)
67 68
69
70 def DeprecatedClass(base, class_name):
71 # Hook the init method of the base class.
72 def init_hook(self, *pargs, **kwargs):
73 base.__init__(self, *pargs, **kwargs)
74
75 # Warn once per class.
76 if base not in DeprecatedClass._warned_classes:
77 DeprecatedClass._warned_classes.append(base)
78 warn('"{}" is deprecated, please use "{}" instead.'.format(
79 class_name, base.__name__))
80 return type(class_name, (base,), {'__init__': init_hook})
81 DeprecatedClass._warned_classes = []
@@ -3,23 +3,44 b''
3 3 # test suite on all supported python versions. To use it, "pip install tox"
4 4 # and then run "tox" from this directory.
5 5
6 # Building the source distribution requires both fabric's fab binary
7 # (http://www.fabfile.org/) and the lessc binary of the css preprocessor
8 # less (http://lesscss.org/) in the PATH.
9 # "pip install fabric" will install fabric. Less can be installed by
10 # node.js' (http://nodejs.org/) package manager npm:
11 # "npm install -g less".
12
13 # Javascript tests need additional dependencies that can be installed
14 # using node.js' package manager npm:
15 # [*] casperjs: "npm install -g casperjs"
16 # [*] slimerjs: "npm install -g slimerjs"
17 # [*] phantomjs: "npm install -g phantomjs"
18
19 # Note: qt4 versions break some tests with tornado versions >=4.0.
20
6 21 [tox]
7 envlist = py27, py33
22 envlist = py27, py33, py34
8 23
9 24 [testenv]
10 deps =
25 deps =
26 pyzmq
11 27 nose
12 mock
13 tornado
28 tornado<4.0
14 29 jinja2
15 30 sphinx
16 31 pygments
32 jsonpointer
33 jsonschema
34 mistune
35
17 36 # To avoid loading IPython module in the current directory, change
18 37 # current directory to ".tox/py*/tmp" before running test.
19 38 changedir = {envtmpdir}
20 39
21 40 commands =
22 # As pip does not treat egg, use easy_install to install PyZMQ.
23 # See also: https://github.com/zeromq/pyzmq
24 easy_install -q pyzmq
25 iptest --all
41 iptest --all
42
43 [testenv:py27]
44 deps=
45 mock
46 {[testenv]deps}
1 NO CONTENT: file was removed
General Comments 0
You need to be logged in to leave comments. Login now