##// END OF EJS Templates
Renamed *Widget to *,...
Jonathan Frederic -
Show More
@@ -1,188 +1,188 b''
1 var xor = function (a, b) {return !a ^ !b;};
1 var xor = function (a, b) {return !a ^ !b;};
2 var isArray = function (a) {
2 var isArray = function (a) {
3 try {
3 try {
4 return Object.toString.call(a) === "[object Array]" || Object.toString.call(a) === "[object RuntimeArray]";
4 return Object.toString.call(a) === "[object Array]" || Object.toString.call(a) === "[object RuntimeArray]";
5 } catch (e) {
5 } catch (e) {
6 return Array.isArray(a);
6 return Array.isArray(a);
7 }
7 }
8 };
8 };
9 var recursive_compare = function(a, b) {
9 var recursive_compare = function(a, b) {
10 // Recursively compare two objects.
10 // Recursively compare two objects.
11 var same = true;
11 var same = true;
12 same = same && !xor(a instanceof Object || typeof a == 'object', b instanceof Object || typeof b == 'object');
12 same = same && !xor(a instanceof Object || typeof a == 'object', b instanceof Object || typeof b == 'object');
13 same = same && !xor(isArray(a), isArray(b));
13 same = same && !xor(isArray(a), isArray(b));
14
14
15 if (same) {
15 if (same) {
16 if (a instanceof Object) {
16 if (a instanceof Object) {
17 var key;
17 var key;
18 for (key in a) {
18 for (key in a) {
19 if (a.hasOwnProperty(key) && !recursive_compare(a[key], b[key])) {
19 if (a.hasOwnProperty(key) && !recursive_compare(a[key], b[key])) {
20 same = false;
20 same = false;
21 break;
21 break;
22 }
22 }
23 }
23 }
24 for (key in b) {
24 for (key in b) {
25 if (b.hasOwnProperty(key) && !recursive_compare(a[key], b[key])) {
25 if (b.hasOwnProperty(key) && !recursive_compare(a[key], b[key])) {
26 same = false;
26 same = false;
27 break;
27 break;
28 }
28 }
29 }
29 }
30 } else {
30 } else {
31 return a === b;
31 return a === b;
32 }
32 }
33 }
33 }
34
34
35 return same;
35 return same;
36 };
36 };
37
37
38 // Test the widget framework.
38 // Test the widget framework.
39 casper.notebook_test(function () {
39 casper.notebook_test(function () {
40 var index;
40 var index;
41
41
42 this.then(function () {
42 this.then(function () {
43
43
44 // Check if the WidgetManager class is defined.
44 // Check if the WidgetManager class is defined.
45 this.test.assert(this.evaluate(function() {
45 this.test.assert(this.evaluate(function() {
46 return IPython.WidgetManager !== undefined;
46 return IPython.WidgetManager !== undefined;
47 }), 'WidgetManager class is defined');
47 }), 'WidgetManager class is defined');
48 });
48 });
49
49
50 index = this.append_cell(
50 index = this.append_cell(
51 'from IPython.html import widgets\n' +
51 'from IPython.html import widgets\n' +
52 'from IPython.display import display, clear_output\n' +
52 'from IPython.display import display, clear_output\n' +
53 'print("Success")');
53 'print("Success")');
54 this.execute_cell_then(index);
54 this.execute_cell_then(index);
55
55
56 this.then(function () {
56 this.then(function () {
57 // Check if the widget manager has been instantiated.
57 // Check if the widget manager has been instantiated.
58 this.test.assert(this.evaluate(function() {
58 this.test.assert(this.evaluate(function() {
59 return IPython.notebook.kernel.widget_manager !== undefined;
59 return IPython.notebook.kernel.widget_manager !== undefined;
60 }), 'Notebook widget manager instantiated');
60 }), 'Notebook widget manager instantiated');
61
61
62 // Functions that can be used to test the packing and unpacking APIs
62 // Functions that can be used to test the packing and unpacking APIs
63 var that = this;
63 var that = this;
64 var test_pack = function (input) {
64 var test_pack = function (input) {
65 var output = that.evaluate(function(input) {
65 var output = that.evaluate(function(input) {
66 var model = new IPython.WidgetModel(IPython.notebook.kernel.widget_manager, undefined);
66 var model = new IPython.WidgetModel(IPython.notebook.kernel.widget_manager, undefined);
67 var results = model._pack_models(input);
67 var results = model._pack_models(input);
68 return results;
68 return results;
69 }, {input: input});
69 }, {input: input});
70 that.test.assert(recursive_compare(input, output),
70 that.test.assert(recursive_compare(input, output),
71 JSON.stringify(input) + ' passed through Model._pack_model unchanged');
71 JSON.stringify(input) + ' passed through Model._pack_model unchanged');
72 };
72 };
73 var test_unpack = function (input) {
73 var test_unpack = function (input) {
74 var output = that.evaluate(function(input) {
74 var output = that.evaluate(function(input) {
75 var model = new IPython.WidgetModel(IPython.notebook.kernel.widget_manager, undefined);
75 var model = new IPython.WidgetModel(IPython.notebook.kernel.widget_manager, undefined);
76 var results = model._unpack_models(input);
76 var results = model._unpack_models(input);
77 return results;
77 return results;
78 }, {input: input});
78 }, {input: input});
79 that.test.assert(recursive_compare(input, output),
79 that.test.assert(recursive_compare(input, output),
80 JSON.stringify(input) + ' passed through Model._unpack_model unchanged');
80 JSON.stringify(input) + ' passed through Model._unpack_model unchanged');
81 };
81 };
82 var test_packing = function(input) {
82 var test_packing = function(input) {
83 test_pack(input);
83 test_pack(input);
84 test_unpack(input);
84 test_unpack(input);
85 };
85 };
86
86
87 test_packing({0: 'hi', 1: 'bye'});
87 test_packing({0: 'hi', 1: 'bye'});
88 test_packing(['hi', 'bye']);
88 test_packing(['hi', 'bye']);
89 test_packing(['hi', 5]);
89 test_packing(['hi', 5]);
90 test_packing(['hi', '5']);
90 test_packing(['hi', '5']);
91 test_packing([1.0, 0]);
91 test_packing([1.0, 0]);
92 test_packing([1.0, false]);
92 test_packing([1.0, false]);
93 test_packing([1, false]);
93 test_packing([1, false]);
94 test_packing([1, false, {a: 'hi'}]);
94 test_packing([1, false, {a: 'hi'}]);
95 test_packing([1, false, ['hi']]);
95 test_packing([1, false, ['hi']]);
96
96
97 // Test multi-set, single touch code. First create a custom widget.
97 // Test multi-set, single touch code. First create a custom widget.
98 this.evaluate(function() {
98 this.evaluate(function() {
99 var MultiSetView = IPython.DOMWidgetView.extend({
99 var MultiSetView = IPython.DOMWidgetView.extend({
100 render: function(){
100 render: function(){
101 this.model.set('a', 1);
101 this.model.set('a', 1);
102 this.model.set('b', 2);
102 this.model.set('b', 2);
103 this.model.set('c', 3);
103 this.model.set('c', 3);
104 this.touch();
104 this.touch();
105 },
105 },
106 });
106 });
107 IPython.WidgetManager.register_widget_view('MultiSetView', MultiSetView);
107 IPython.WidgetManager.register_widget_view('MultiSetView', MultiSetView);
108 }, {});
108 }, {});
109 });
109 });
110
110
111 // Try creating the multiset widget, verify that sets the values correctly.
111 // Try creating the multiset widget, verify that sets the values correctly.
112 var multiset = {};
112 var multiset = {};
113 multiset.index = this.append_cell(
113 multiset.index = this.append_cell(
114 'from IPython.utils.traitlets import Unicode, CInt\n' +
114 'from IPython.utils.traitlets import Unicode, CInt\n' +
115 'class MultiSetWidget(widgets.Widget):\n' +
115 'class MultiSetWidget(widgets.Widget):\n' +
116 ' _view_name = Unicode("MultiSetView", sync=True)\n' +
116 ' _view_name = Unicode("MultiSetView", sync=True)\n' +
117 ' a = CInt(0, sync=True)\n' +
117 ' a = CInt(0, sync=True)\n' +
118 ' b = CInt(0, sync=True)\n' +
118 ' b = CInt(0, sync=True)\n' +
119 ' c = CInt(0, sync=True)\n' +
119 ' c = CInt(0, sync=True)\n' +
120 ' d = CInt(-1, sync=True)\n' + // See if it sends a full state.
120 ' d = CInt(-1, sync=True)\n' + // See if it sends a full state.
121 ' def _handle_receive_state(self, sync_data):\n' +
121 ' def _handle_receive_state(self, sync_data):\n' +
122 ' widgets.Widget._handle_receive_state(self, sync_data)\n'+
122 ' widgets.Widget._handle_receive_state(self, sync_data)\n'+
123 ' self.d = len(sync_data)\n' +
123 ' self.d = len(sync_data)\n' +
124 'multiset = MultiSetWidget()\n' +
124 'multiset = MultiSetWidget()\n' +
125 'display(multiset)\n' +
125 'display(multiset)\n' +
126 'print(multiset.model_id)');
126 'print(multiset.model_id)');
127 this.execute_cell_then(multiset.index, function(index) {
127 this.execute_cell_then(multiset.index, function(index) {
128 multiset.model_id = this.get_output_cell(index).text.trim();
128 multiset.model_id = this.get_output_cell(index).text.trim();
129 });
129 });
130
130
131 this.wait_for_widget(multiset);
131 this.wait_for_widget(multiset);
132
132
133 index = this.append_cell(
133 index = this.append_cell(
134 'print("%d%d%d" % (multiset.a, multiset.b, multiset.c))');
134 'print("%d%d%d" % (multiset.a, multiset.b, multiset.c))');
135 this.execute_cell_then(index, function(index) {
135 this.execute_cell_then(index, function(index) {
136 this.test.assertEquals(this.get_output_cell(index).text.trim(), '123',
136 this.test.assertEquals(this.get_output_cell(index).text.trim(), '123',
137 'Multiple model.set calls and one view.touch update state in back-end.');
137 'Multiple model.set calls and one view.touch update state in back-end.');
138 });
138 });
139
139
140 index = this.append_cell(
140 index = this.append_cell(
141 'print("%d" % (multiset.d))');
141 'print("%d" % (multiset.d))');
142 this.execute_cell_then(index, function(index) {
142 this.execute_cell_then(index, function(index) {
143 this.test.assertEquals(this.get_output_cell(index).text.trim(), '3',
143 this.test.assertEquals(this.get_output_cell(index).text.trim(), '3',
144 'Multiple model.set calls sent a partial state.');
144 'Multiple model.set calls sent a partial state.');
145 });
145 });
146
146
147 var textbox = {};
147 var textbox = {};
148 throttle_index = this.append_cell(
148 throttle_index = this.append_cell(
149 'import time\n' +
149 'import time\n' +
150 'textbox = widgets.TextWidget()\n' +
150 'textbox = widgets.Text()\n' +
151 'display(textbox)\n' +
151 'display(textbox)\n' +
152 'textbox.add_class("my-throttle-textbox", selector="input")\n' +
152 'textbox.add_class("my-throttle-textbox", selector="input")\n' +
153 'def handle_change(name, old, new):\n' +
153 'def handle_change(name, old, new):\n' +
154 ' display(len(new))\n' +
154 ' display(len(new))\n' +
155 ' time.sleep(0.5)\n' +
155 ' time.sleep(0.5)\n' +
156 'textbox.on_trait_change(handle_change, "value")\n' +
156 'textbox.on_trait_change(handle_change, "value")\n' +
157 'print(textbox.model_id)');
157 'print(textbox.model_id)');
158 this.execute_cell_then(throttle_index, function(index){
158 this.execute_cell_then(throttle_index, function(index){
159 textbox.model_id = this.get_output_cell(index).text.trim();
159 textbox.model_id = this.get_output_cell(index).text.trim();
160
160
161 this.test.assert(this.cell_element_exists(index,
161 this.test.assert(this.cell_element_exists(index,
162 '.widget-area .widget-subarea'),
162 '.widget-area .widget-subarea'),
163 'Widget subarea exists.');
163 'Widget subarea exists.');
164
164
165 this.test.assert(this.cell_element_exists(index,
165 this.test.assert(this.cell_element_exists(index,
166 '.my-throttle-textbox'), 'Textbox exists.');
166 '.my-throttle-textbox'), 'Textbox exists.');
167
167
168 // Send 20 characters
168 // Send 20 characters
169 this.sendKeys('.my-throttle-textbox', '....................');
169 this.sendKeys('.my-throttle-textbox', '....................');
170 });
170 });
171
171
172 this.wait_for_widget(textbox);
172 this.wait_for_widget(textbox);
173
173
174 this.then(function () {
174 this.then(function () {
175 var outputs = this.evaluate(function(i) {
175 var outputs = this.evaluate(function(i) {
176 return IPython.notebook.get_cell(i).output_area.outputs;
176 return IPython.notebook.get_cell(i).output_area.outputs;
177 }, {i : throttle_index});
177 }, {i : throttle_index});
178
178
179 // Only 4 outputs should have printed, but because of timing, sometimes
179 // Only 4 outputs should have printed, but because of timing, sometimes
180 // 5 outputs will print. All we need to do is verify num outputs <= 5
180 // 5 outputs will print. All we need to do is verify num outputs <= 5
181 // because that is much less than 20.
181 // because that is much less than 20.
182 this.test.assert(outputs.length <= 5, 'Messages throttled.');
182 this.test.assert(outputs.length <= 5, 'Messages throttled.');
183
183
184 // We also need to verify that the last state sent was correct.
184 // We also need to verify that the last state sent was correct.
185 var last_state = outputs[outputs.length-1]['text/plain'];
185 var last_state = outputs[outputs.length-1]['text/plain'];
186 this.test.assertEquals(last_state, "20", "Last state sent when throttling.");
186 this.test.assertEquals(last_state, "20", "Last state sent when throttling.");
187 });
187 });
188 });
188 });
@@ -1,86 +1,86 b''
1 // Test widget bool class
1 // Test widget bool class
2 casper.notebook_test(function () {
2 casper.notebook_test(function () {
3 index = this.append_cell(
3 index = this.append_cell(
4 'from IPython.html import widgets\n' +
4 'from IPython.html import widgets\n' +
5 'from IPython.display import display, clear_output\n' +
5 'from IPython.display import display, clear_output\n' +
6 'print("Success")');
6 'print("Success")');
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var bool_index = this.append_cell(
9 var bool_index = this.append_cell(
10 'bool_widgets = [widgets.CheckboxWidget(description="Title", value=True),\n' +
10 'bool_widgets = [widgets.Checkbox(description="Title", value=True),\n' +
11 ' widgets.ToggleButtonWidget(description="Title", value=True)]\n' +
11 ' widgets.ToggleButton(description="Title", value=True)]\n' +
12 'display(bool_widgets[0])\n' +
12 'display(bool_widgets[0])\n' +
13 'display(bool_widgets[1])\n' +
13 'display(bool_widgets[1])\n' +
14 'print("Success")');
14 'print("Success")');
15 this.execute_cell_then(bool_index, function(index){
15 this.execute_cell_then(bool_index, function(index){
16
16
17 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
17 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
18 'Create bool widget cell executed with correct output.');
18 'Create bool widget cell executed with correct output.');
19
19
20 this.test.assert(this.cell_element_exists(index,
20 this.test.assert(this.cell_element_exists(index,
21 '.widget-area .widget-subarea'),
21 '.widget-area .widget-subarea'),
22 'Widget subarea exists.');
22 'Widget subarea exists.');
23
23
24 this.test.assert(this.cell_element_exists(index,
24 this.test.assert(this.cell_element_exists(index,
25 '.widget-area .widget-subarea .widget-hbox-single input'),
25 '.widget-area .widget-subarea .widget-hbox-single input'),
26 'Checkbox exists.');
26 'Checkbox exists.');
27
27
28 this.test.assert(this.cell_element_function(index,
28 this.test.assert(this.cell_element_function(index,
29 '.widget-area .widget-subarea .widget-hbox-single input', 'prop', ['checked']),
29 '.widget-area .widget-subarea .widget-hbox-single input', 'prop', ['checked']),
30 'Checkbox is checked.');
30 'Checkbox is checked.');
31
31
32 this.test.assert(this.cell_element_exists(index,
32 this.test.assert(this.cell_element_exists(index,
33 '.widget-area .widget-subarea .widget-hbox-single .widget-hlabel'),
33 '.widget-area .widget-subarea .widget-hbox-single .widget-hlabel'),
34 'Checkbox label exists.');
34 'Checkbox label exists.');
35
35
36 this.test.assert(this.cell_element_function(index,
36 this.test.assert(this.cell_element_function(index,
37 '.widget-area .widget-subarea .widget-hbox-single .widget-hlabel', 'html')=="Title",
37 '.widget-area .widget-subarea .widget-hbox-single .widget-hlabel', 'html')=="Title",
38 'Checkbox labeled correctly.');
38 'Checkbox labeled correctly.');
39
39
40 this.test.assert(this.cell_element_exists(index,
40 this.test.assert(this.cell_element_exists(index,
41 '.widget-area .widget-subarea button'),
41 '.widget-area .widget-subarea button'),
42 'Toggle button exists.');
42 'Toggle button exists.');
43
43
44 this.test.assert(this.cell_element_function(index,
44 this.test.assert(this.cell_element_function(index,
45 '.widget-area .widget-subarea button', 'html')=="Title",
45 '.widget-area .widget-subarea button', 'html')=="Title",
46 'Toggle button labeled correctly.');
46 'Toggle button labeled correctly.');
47
47
48 this.test.assert(this.cell_element_function(index,
48 this.test.assert(this.cell_element_function(index,
49 '.widget-area .widget-subarea button', 'hasClass', ['active']),
49 '.widget-area .widget-subarea button', 'hasClass', ['active']),
50 'Toggle button is toggled.');
50 'Toggle button is toggled.');
51
51
52 });
52 });
53
53
54 index = this.append_cell(
54 index = this.append_cell(
55 'bool_widgets[0].value = False\n' +
55 'bool_widgets[0].value = False\n' +
56 'bool_widgets[1].value = False\n' +
56 'bool_widgets[1].value = False\n' +
57 'print("Success")');
57 'print("Success")');
58 this.execute_cell_then(index, function(index){
58 this.execute_cell_then(index, function(index){
59
59
60 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
60 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
61 'Change bool widget value cell executed with correct output.');
61 'Change bool widget value cell executed with correct output.');
62
62
63 this.test.assert(! this.cell_element_function(bool_index,
63 this.test.assert(! this.cell_element_function(bool_index,
64 '.widget-area .widget-subarea .widget-hbox-single input', 'prop', ['checked']),
64 '.widget-area .widget-subarea .widget-hbox-single input', 'prop', ['checked']),
65 'Checkbox is not checked. (1)');
65 'Checkbox is not checked. (1)');
66
66
67 this.test.assert(! this.cell_element_function(bool_index,
67 this.test.assert(! this.cell_element_function(bool_index,
68 '.widget-area .widget-subarea button', 'hasClass', ['active']),
68 '.widget-area .widget-subarea button', 'hasClass', ['active']),
69 'Toggle button is not toggled. (1)');
69 'Toggle button is not toggled. (1)');
70
70
71 // Try toggling the bool by clicking on the checkbox.
71 // Try toggling the bool by clicking on the checkbox.
72 this.cell_element_function(bool_index, '.widget-area .widget-subarea .widget-hbox-single input', 'click');
72 this.cell_element_function(bool_index, '.widget-area .widget-subarea .widget-hbox-single input', 'click');
73
73
74 this.test.assert(this.cell_element_function(bool_index,
74 this.test.assert(this.cell_element_function(bool_index,
75 '.widget-area .widget-subarea .widget-hbox-single input', 'prop', ['checked']),
75 '.widget-area .widget-subarea .widget-hbox-single input', 'prop', ['checked']),
76 'Checkbox is checked. (2)');
76 'Checkbox is checked. (2)');
77
77
78 // Try toggling the bool by clicking on the toggle button.
78 // Try toggling the bool by clicking on the toggle button.
79 this.cell_element_function(bool_index, '.widget-area .widget-subarea button', 'click');
79 this.cell_element_function(bool_index, '.widget-area .widget-subarea button', 'click');
80
80
81 this.test.assert(this.cell_element_function(bool_index,
81 this.test.assert(this.cell_element_function(bool_index,
82 '.widget-area .widget-subarea button', 'hasClass', ['active']),
82 '.widget-area .widget-subarea button', 'hasClass', ['active']),
83 'Toggle button is toggled. (3)');
83 'Toggle button is toggled. (3)');
84
84
85 });
85 });
86 }); No newline at end of file
86 });
@@ -1,43 +1,43 b''
1 // Test widget button class
1 // Test widget button class
2 casper.notebook_test(function () {
2 casper.notebook_test(function () {
3 index = this.append_cell(
3 index = this.append_cell(
4 'from IPython.html import widgets\n' +
4 'from IPython.html import widgets\n' +
5 'from IPython.display import display, clear_output\n' +
5 'from IPython.display import display, clear_output\n' +
6 'print("Success")');
6 'print("Success")');
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var button_index = this.append_cell(
9 var button_index = this.append_cell(
10 'button = widgets.ButtonWidget(description="Title")\n' +
10 'button = widgets.Button(description="Title")\n' +
11 'display(button)\n' +
11 'display(button)\n' +
12 'print("Success")\n' +
12 'print("Success")\n' +
13 'def handle_click(sender):\n' +
13 'def handle_click(sender):\n' +
14 ' display("Clicked")\n' +
14 ' display("Clicked")\n' +
15 'button.on_click(handle_click)');
15 'button.on_click(handle_click)');
16 this.execute_cell_then(button_index, function(index){
16 this.execute_cell_then(button_index, function(index){
17
17
18 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
18 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
19 'Create button cell executed with correct output.');
19 'Create button cell executed with correct output.');
20
20
21 this.test.assert(this.cell_element_exists(index,
21 this.test.assert(this.cell_element_exists(index,
22 '.widget-area .widget-subarea'),
22 '.widget-area .widget-subarea'),
23 'Widget subarea exists.');
23 'Widget subarea exists.');
24
24
25 this.test.assert(this.cell_element_exists(index,
25 this.test.assert(this.cell_element_exists(index,
26 '.widget-area .widget-subarea button'),
26 '.widget-area .widget-subarea button'),
27 'Widget button exists.');
27 'Widget button exists.');
28
28
29 this.test.assert(this.cell_element_function(index,
29 this.test.assert(this.cell_element_function(index,
30 '.widget-area .widget-subarea button', 'html')=='Title',
30 '.widget-area .widget-subarea button', 'html')=='Title',
31 'Set button description.');
31 'Set button description.');
32
32
33 this.cell_element_function(index,
33 this.cell_element_function(index,
34 '.widget-area .widget-subarea button', 'click');
34 '.widget-area .widget-subarea button', 'click');
35 });
35 });
36
36
37 this.wait_for_output(button_index, 1);
37 this.wait_for_output(button_index, 1);
38
38
39 this.then(function () {
39 this.then(function () {
40 this.test.assertEquals(this.get_output_cell(button_index, 1)['text/plain'], "'Clicked'",
40 this.test.assertEquals(this.get_output_cell(button_index, 1)['text/plain'], "'Clicked'",
41 'Button click event fires.');
41 'Button click event fires.');
42 });
42 });
43 }); No newline at end of file
43 });
@@ -1,80 +1,80 b''
1 // Test container class
1 // Test container class
2 casper.notebook_test(function () {
2 casper.notebook_test(function () {
3 index = this.append_cell(
3 index = this.append_cell(
4 'from IPython.html import widgets\n' +
4 'from IPython.html import widgets\n' +
5 'from IPython.display import display, clear_output\n' +
5 'from IPython.display import display, clear_output\n' +
6 'print("Success")');
6 'print("Success")');
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var container_index = this.append_cell(
9 var container_index = this.append_cell(
10 'container = widgets.ContainerWidget()\n' +
10 'container = widgets.Container()\n' +
11 'button = widgets.ButtonWidget()\n'+
11 'button = widgets.Button()\n'+
12 'container.children = [button]\n'+
12 'container.children = [button]\n'+
13 'display(container)\n'+
13 'display(container)\n'+
14 'container.add_class("my-test-class")\n'+
14 'container.add_class("my-test-class")\n'+
15 'print("Success")\n');
15 'print("Success")\n');
16 this.execute_cell_then(container_index, function(index){
16 this.execute_cell_then(container_index, function(index){
17
17
18 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
18 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
19 'Create container cell executed with correct output.');
19 'Create container cell executed with correct output.');
20
20
21 this.test.assert(this.cell_element_exists(index,
21 this.test.assert(this.cell_element_exists(index,
22 '.widget-area .widget-subarea'),
22 '.widget-area .widget-subarea'),
23 'Widget subarea exists.');
23 'Widget subarea exists.');
24
24
25 this.test.assert(this.cell_element_exists(index,
25 this.test.assert(this.cell_element_exists(index,
26 '.widget-area .widget-subarea .widget-container'),
26 '.widget-area .widget-subarea .widget-container'),
27 'Widget container exists.');
27 'Widget container exists.');
28
28
29 this.test.assert(this.cell_element_exists(index,
29 this.test.assert(this.cell_element_exists(index,
30 '.widget-area .widget-subarea .my-test-class'),
30 '.widget-area .widget-subarea .my-test-class'),
31 'add_class works.');
31 'add_class works.');
32
32
33 this.test.assert(this.cell_element_exists(index,
33 this.test.assert(this.cell_element_exists(index,
34 '.widget-area .widget-subarea .my-test-class button'),
34 '.widget-area .widget-subarea .my-test-class button'),
35 'Container parent/child relationship works.');
35 'Container parent/child relationship works.');
36 });
36 });
37
37
38 index = this.append_cell(
38 index = this.append_cell(
39 'container.set_css("float", "right")\n'+
39 'container.set_css("float", "right")\n'+
40 'print("Success")\n');
40 'print("Success")\n');
41 this.execute_cell_then(index, function(index){
41 this.execute_cell_then(index, function(index){
42
42
43 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
43 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
44 'Set container class CSS cell executed with correct output.');
44 'Set container class CSS cell executed with correct output.');
45
45
46 this.test.assert(this.cell_element_function(container_index,
46 this.test.assert(this.cell_element_function(container_index,
47 '.widget-area .widget-subarea .my-test-class', 'css', ['float'])=='right',
47 '.widget-area .widget-subarea .my-test-class', 'css', ['float'])=='right',
48 'set_css works.');
48 'set_css works.');
49 });
49 });
50
50
51 index = this.append_cell(
51 index = this.append_cell(
52 'container.remove_class("my-test-class")\n'+
52 'container.remove_class("my-test-class")\n'+
53 'print("Success")\n');
53 'print("Success")\n');
54 this.execute_cell_then(index, function(index){
54 this.execute_cell_then(index, function(index){
55
55
56 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
56 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
57 'Remove container class cell executed with correct output.');
57 'Remove container class cell executed with correct output.');
58
58
59 this.test.assert(! this.cell_element_exists(container_index,
59 this.test.assert(! this.cell_element_exists(container_index,
60 '.widget-area .widget-subarea .my-test-class'),
60 '.widget-area .widget-subarea .my-test-class'),
61 'remove_class works.');
61 'remove_class works.');
62 });
62 });
63
63
64 index = this.append_cell(
64 index = this.append_cell(
65 'display(button)\n'+
65 'display(button)\n'+
66 'print("Success")\n');
66 'print("Success")\n');
67 this.execute_cell_then(index, function(index){
67 this.execute_cell_then(index, function(index){
68
68
69 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
69 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
70 'Display container child executed with correct output.');
70 'Display container child executed with correct output.');
71
71
72 this.test.assert(! this.cell_element_exists(index,
72 this.test.assert(! this.cell_element_exists(index,
73 '.widget-area .widget-subarea .widget-container'),
73 '.widget-area .widget-subarea .widget-container'),
74 'Parent container not displayed.');
74 'Parent container not displayed.');
75
75
76 this.test.assert(this.cell_element_exists(index,
76 this.test.assert(this.cell_element_exists(index,
77 '.widget-area .widget-subarea button'),
77 '.widget-area .widget-subarea button'),
78 'Child displayed.');
78 'Child displayed.');
79 });
79 });
80 }); No newline at end of file
80 });
@@ -1,100 +1,100 b''
1 // Test widget float class
1 // Test widget float class
2 casper.notebook_test(function () {
2 casper.notebook_test(function () {
3 index = this.append_cell(
3 index = this.append_cell(
4 'from IPython.html import widgets\n' +
4 'from IPython.html import widgets\n' +
5 'from IPython.display import display, clear_output\n' +
5 'from IPython.display import display, clear_output\n' +
6 'print("Success")');
6 'print("Success")');
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var float_text = {};
9 var float_text = {};
10 float_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-float-text';
10 float_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-float-text';
11 float_text.index = this.append_cell(
11 float_text.index = this.append_cell(
12 'float_widget = widgets.FloatTextWidget()\n' +
12 'float_widget = widgets.FloatText()\n' +
13 'display(float_widget)\n' +
13 'display(float_widget)\n' +
14 'float_widget.add_class("my-second-float-text", selector="input")\n' +
14 'float_widget.add_class("my-second-float-text", selector="input")\n' +
15 'print(float_widget.model_id)\n');
15 'print(float_widget.model_id)\n');
16 this.execute_cell_then(float_text.index, function(index){
16 this.execute_cell_then(float_text.index, function(index){
17 float_text.model_id = this.get_output_cell(index).text.trim();
17 float_text.model_id = this.get_output_cell(index).text.trim();
18
18
19 this.test.assert(this.cell_element_exists(index,
19 this.test.assert(this.cell_element_exists(index,
20 '.widget-area .widget-subarea'),
20 '.widget-area .widget-subarea'),
21 'Widget subarea exists.');
21 'Widget subarea exists.');
22
22
23 this.test.assert(this.cell_element_exists(index, float_text.query),
23 this.test.assert(this.cell_element_exists(index, float_text.query),
24 'Widget float textbox exists.');
24 'Widget float textbox exists.');
25
25
26 this.cell_element_function(float_text.index, float_text.query, 'val', ['']);
26 this.cell_element_function(float_text.index, float_text.query, 'val', ['']);
27 this.sendKeys(float_text.query, '1.05');
27 this.sendKeys(float_text.query, '1.05');
28 });
28 });
29
29
30 this.wait_for_widget(float_text);
30 this.wait_for_widget(float_text);
31
31
32 index = this.append_cell('print(float_widget.value)\n');
32 index = this.append_cell('print(float_widget.value)\n');
33 this.execute_cell_then(index, function(index){
33 this.execute_cell_then(index, function(index){
34 this.test.assertEquals(this.get_output_cell(index).text, '1.05\n',
34 this.test.assertEquals(this.get_output_cell(index).text, '1.05\n',
35 'Float textbox value set.');
35 'Float textbox value set.');
36 this.cell_element_function(float_text.index, float_text.query, 'val', ['']);
36 this.cell_element_function(float_text.index, float_text.query, 'val', ['']);
37 this.sendKeys(float_text.query, '123456789.0');
37 this.sendKeys(float_text.query, '123456789.0');
38 });
38 });
39
39
40 this.wait_for_widget(float_text);
40 this.wait_for_widget(float_text);
41
41
42 index = this.append_cell('print(float_widget.value)\n');
42 index = this.append_cell('print(float_widget.value)\n');
43 this.execute_cell_then(index, function(index){
43 this.execute_cell_then(index, function(index){
44 this.test.assertEquals(this.get_output_cell(index).text, '123456789.0\n',
44 this.test.assertEquals(this.get_output_cell(index).text, '123456789.0\n',
45 'Long float textbox value set (probably triggers throttling).');
45 'Long float textbox value set (probably triggers throttling).');
46 this.cell_element_function(float_text.index, float_text.query, 'val', ['']);
46 this.cell_element_function(float_text.index, float_text.query, 'val', ['']);
47 this.sendKeys(float_text.query, '12hello');
47 this.sendKeys(float_text.query, '12hello');
48 });
48 });
49
49
50 this.wait_for_widget(float_text);
50 this.wait_for_widget(float_text);
51
51
52 index = this.append_cell('print(float_widget.value)\n');
52 index = this.append_cell('print(float_widget.value)\n');
53 this.execute_cell_then(index, function(index){
53 this.execute_cell_then(index, function(index){
54 this.test.assertEquals(this.get_output_cell(index).text, '12.0\n',
54 this.test.assertEquals(this.get_output_cell(index).text, '12.0\n',
55 'Invald float textbox value caught and filtered.');
55 'Invald float textbox value caught and filtered.');
56 });
56 });
57
57
58 var float_text_query = '.widget-area .widget-subarea .widget-hbox-single .widget-numeric-text';
58 var float_text_query = '.widget-area .widget-subarea .widget-hbox-single .widget-numeric-text';
59 var slider = {};
59 var slider = {};
60 slider.query = '.widget-area .widget-subarea .widget-hbox-single .slider';
60 slider.query = '.widget-area .widget-subarea .widget-hbox-single .slider';
61 slider.index = this.append_cell(
61 slider.index = this.append_cell(
62 'floatrange = [widgets.BoundedFloatTextWidget(), \n' +
62 'floatrange = [widgets.BoundedFloatText(), \n' +
63 ' widgets.FloatSliderWidget()]\n' +
63 ' widgets.FloatSlider()]\n' +
64 '[display(floatrange[i]) for i in range(2)]\n' +
64 '[display(floatrange[i]) for i in range(2)]\n' +
65 'print("Success")\n');
65 'print("Success")\n');
66 this.execute_cell_then(slider.index, function(index){
66 this.execute_cell_then(slider.index, function(index){
67
67
68 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
68 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
69 'Create float range cell executed with correct output.');
69 'Create float range cell executed with correct output.');
70
70
71 this.test.assert(this.cell_element_exists(index,
71 this.test.assert(this.cell_element_exists(index,
72 '.widget-area .widget-subarea'),
72 '.widget-area .widget-subarea'),
73 'Widget subarea exists.');
73 'Widget subarea exists.');
74
74
75 this.test.assert(this.cell_element_exists(index, slider.query),
75 this.test.assert(this.cell_element_exists(index, slider.query),
76 'Widget slider exists.');
76 'Widget slider exists.');
77
77
78 this.test.assert(this.cell_element_exists(index, float_text_query),
78 this.test.assert(this.cell_element_exists(index, float_text_query),
79 'Widget float textbox exists.');
79 'Widget float textbox exists.');
80 });
80 });
81
81
82 index = this.append_cell(
82 index = this.append_cell(
83 'for widget in floatrange:\n' +
83 'for widget in floatrange:\n' +
84 ' widget.max = 50.0\n' +
84 ' widget.max = 50.0\n' +
85 ' widget.min = -50.0\n' +
85 ' widget.min = -50.0\n' +
86 ' widget.value = 25.0\n' +
86 ' widget.value = 25.0\n' +
87 'print("Success")\n');
87 'print("Success")\n');
88 this.execute_cell_then(index, function(index){
88 this.execute_cell_then(index, function(index){
89
89
90 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
90 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
91 'Float range properties cell executed with correct output.');
91 'Float range properties cell executed with correct output.');
92
92
93 this.test.assert(this.cell_element_exists(slider.index, slider.query),
93 this.test.assert(this.cell_element_exists(slider.index, slider.query),
94 'Widget slider exists.');
94 'Widget slider exists.');
95
95
96 this.test.assert(this.cell_element_function(slider.index, slider.query,
96 this.test.assert(this.cell_element_function(slider.index, slider.query,
97 'slider', ['value']) == 25.0,
97 'slider', ['value']) == 25.0,
98 'Slider set to Python value.');
98 'Slider set to Python value.');
99 });
99 });
100 }); No newline at end of file
100 });
@@ -1,48 +1,48 b''
1 // Test image class
1 // Test image class
2 casper.notebook_test(function () {
2 casper.notebook_test(function () {
3 index = this.append_cell(
3 index = this.append_cell(
4 'from IPython.html import widgets\n' +
4 'from IPython.html import widgets\n' +
5 'from IPython.display import display, clear_output\n' +
5 'from IPython.display import display, clear_output\n' +
6 'print("Success")');
6 'print("Success")');
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 // Get the temporary directory that the test server is running in.
9 // Get the temporary directory that the test server is running in.
10 var cwd = '';
10 var cwd = '';
11 index = this.append_cell('!echo $(pwd)');
11 index = this.append_cell('!echo $(pwd)');
12 this.execute_cell_then(index, function(index){
12 this.execute_cell_then(index, function(index){
13 cwd = this.get_output_cell(index).text.trim();
13 cwd = this.get_output_cell(index).text.trim();
14 });
14 });
15
15
16 var test_jpg = '/9j/4AAQSkZJRgABAQEASABIAAD//gATQ3JlYXRlZCB3aXRoIEdJTVD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wgARCAABAAEDAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAAA//EABUBAQEAAAAAAAAAAAAAAAAAAAME/9oADAMBAAIQAxAAAAECv//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAQUCf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Bf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Bf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEABj8Cf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8hf//aAAwDAQACAAMAAAAQn//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Qf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Qf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8Qf//Z';
16 var test_jpg = '/9j/4AAQSkZJRgABAQEASABIAAD//gATQ3JlYXRlZCB3aXRoIEdJTVD/2wBDACAWGBwYFCAcGhwkIiAmMFA0MCwsMGJGSjpQdGZ6eHJmcG6AkLicgIiuim5woNqirr7EztDOfJri8uDI8LjKzsb/2wBDASIkJDAqMF40NF7GhHCExsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsbGxsb/wgARCAABAAEDAREAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAAA//EABUBAQEAAAAAAAAAAAAAAAAAAAME/9oADAMBAAIQAxAAAAECv//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAQUCf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Bf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Bf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEABj8Cf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8hf//aAAwDAQACAAMAAAAQn//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Qf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Qf//EABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8Qf//Z';
17
17
18 var image_index = this.append_cell(
18 var image_index = this.append_cell(
19 'import base64\n' +
19 'import base64\n' +
20 'data = base64.b64decode("' + test_jpg + '")\n' +
20 'data = base64.b64decode("' + test_jpg + '")\n' +
21 'image = widgets.ImageWidget()\n' +
21 'image = widgets.Image()\n' +
22 'image.format = "jpeg"\n' +
22 'image.format = "jpeg"\n' +
23 'image.value = data\n' +
23 'image.value = data\n' +
24 'image.width = "50px"\n' +
24 'image.width = "50px"\n' +
25 'image.height = "50px"\n' +
25 'image.height = "50px"\n' +
26 // Set css that will make the image render within the PhantomJS visible
26 // Set css that will make the image render within the PhantomJS visible
27 // window. If we don't do this, the captured image will be black.
27 // window. If we don't do this, the captured image will be black.
28 'image.set_css({"background": "blue", "z-index": "9999", "position": "fixed", "top": "0px", "left": "0px"})\n' +
28 'image.set_css({"background": "blue", "z-index": "9999", "position": "fixed", "top": "0px", "left": "0px"})\n' +
29 'display(image)\n' +
29 'display(image)\n' +
30 'image.add_class("my-test-image")\n' +
30 'image.add_class("my-test-image")\n' +
31 'print("Success")\n');
31 'print("Success")\n');
32 this.execute_cell_then(image_index, function(index){
32 this.execute_cell_then(image_index, function(index){
33
33
34 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
34 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
35 'Create image executed with correct output.');
35 'Create image executed with correct output.');
36
36
37 this.test.assert(this.cell_element_exists(index,
37 this.test.assert(this.cell_element_exists(index,
38 '.widget-area .widget-subarea'),
38 '.widget-area .widget-subarea'),
39 'Widget subarea exists.');
39 'Widget subarea exists.');
40
40
41 var img_sel = '.widget-area .widget-subarea img';
41 var img_sel = '.widget-area .widget-subarea img';
42 this.test.assert(this.cell_element_exists(index, img_sel), 'Image exists.');
42 this.test.assert(this.cell_element_exists(index, img_sel), 'Image exists.');
43
43
44 // Verify that the image's base64 data has made it into the DOM.
44 // Verify that the image's base64 data has made it into the DOM.
45 var img_src = this.cell_element_function(image_index, img_sel, 'attr', ['src']);
45 var img_src = this.cell_element_function(image_index, img_sel, 'attr', ['src']);
46 this.test.assert(img_src.indexOf(test_jpg) > -1, 'Image src data exists.');
46 this.test.assert(img_src.indexOf(test_jpg) > -1, 'Image src data exists.');
47 });
47 });
48 }); No newline at end of file
48 });
@@ -1,157 +1,157 b''
1 // Test widget int class
1 // Test widget int class
2 casper.notebook_test(function () {
2 casper.notebook_test(function () {
3 index = this.append_cell(
3 index = this.append_cell(
4 'from IPython.html import widgets\n' +
4 'from IPython.html import widgets\n' +
5 'from IPython.display import display, clear_output\n' +
5 'from IPython.display import display, clear_output\n' +
6 'print("Success")');
6 'print("Success")');
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var int_text = {};
9 var int_text = {};
10 int_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-int-text';
10 int_text.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-int-text';
11 int_text.index = this.append_cell(
11 int_text.index = this.append_cell(
12 'int_widget = widgets.IntTextWidget()\n' +
12 'int_widget = widgets.IntText()\n' +
13 'display(int_widget)\n' +
13 'display(int_widget)\n' +
14 'int_widget.add_class("my-second-int-text", selector="input")\n' +
14 'int_widget.add_class("my-second-int-text", selector="input")\n' +
15 'print(int_widget.model_id)\n');
15 'print(int_widget.model_id)\n');
16 this.execute_cell_then(int_text.index, function(index){
16 this.execute_cell_then(int_text.index, function(index){
17 int_text.model_id = this.get_output_cell(index).text.trim();
17 int_text.model_id = this.get_output_cell(index).text.trim();
18
18
19 this.test.assert(this.cell_element_exists(index,
19 this.test.assert(this.cell_element_exists(index,
20 '.widget-area .widget-subarea'),
20 '.widget-area .widget-subarea'),
21 'Widget subarea exists.');
21 'Widget subarea exists.');
22
22
23 this.test.assert(this.cell_element_exists(index, int_text.query),
23 this.test.assert(this.cell_element_exists(index, int_text.query),
24 'Widget int textbox exists.');
24 'Widget int textbox exists.');
25
25
26 this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
26 this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
27 this.sendKeys(int_text.query, '1.05');
27 this.sendKeys(int_text.query, '1.05');
28 });
28 });
29
29
30 this.wait_for_widget(int_text);
30 this.wait_for_widget(int_text);
31
31
32 index = this.append_cell('print(int_widget.value)\n');
32 index = this.append_cell('print(int_widget.value)\n');
33 this.execute_cell_then(index, function(index){
33 this.execute_cell_then(index, function(index){
34 this.test.assertEquals(this.get_output_cell(index).text, '1\n',
34 this.test.assertEquals(this.get_output_cell(index).text, '1\n',
35 'Int textbox value set.');
35 'Int textbox value set.');
36 this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
36 this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
37 this.sendKeys(int_text.query, '123456789');
37 this.sendKeys(int_text.query, '123456789');
38 });
38 });
39
39
40 this.wait_for_widget(int_text);
40 this.wait_for_widget(int_text);
41
41
42 index = this.append_cell('print(int_widget.value)\n');
42 index = this.append_cell('print(int_widget.value)\n');
43 this.execute_cell_then(index, function(index){
43 this.execute_cell_then(index, function(index){
44 this.test.assertEquals(this.get_output_cell(index).text, '123456789\n',
44 this.test.assertEquals(this.get_output_cell(index).text, '123456789\n',
45 'Long int textbox value set (probably triggers throttling).');
45 'Long int textbox value set (probably triggers throttling).');
46 this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
46 this.cell_element_function(int_text.index, int_text.query, 'val', ['']);
47 this.sendKeys(int_text.query, '12hello');
47 this.sendKeys(int_text.query, '12hello');
48 });
48 });
49
49
50 this.wait_for_widget(int_text);
50 this.wait_for_widget(int_text);
51
51
52 index = this.append_cell('print(int_widget.value)\n');
52 index = this.append_cell('print(int_widget.value)\n');
53 this.execute_cell_then(index, function(index){
53 this.execute_cell_then(index, function(index){
54 this.test.assertEquals(this.get_output_cell(index).text, '12\n',
54 this.test.assertEquals(this.get_output_cell(index).text, '12\n',
55 'Invald int textbox value caught and filtered.');
55 'Invald int textbox value caught and filtered.');
56 });
56 });
57
57
58 index = this.append_cell(
58 index = this.append_cell(
59 'from IPython.html import widgets\n' +
59 'from IPython.html import widgets\n' +
60 'from IPython.display import display, clear_output\n' +
60 'from IPython.display import display, clear_output\n' +
61 'print("Success")');
61 'print("Success")');
62 this.execute_cell_then(index);
62 this.execute_cell_then(index);
63
63
64
64
65 var slider_query = '.widget-area .widget-subarea .widget-hbox-single .slider';
65 var slider_query = '.widget-area .widget-subarea .widget-hbox-single .slider';
66 var int_text2 = {};
66 var int_text2 = {};
67 int_text2.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-num-test-text';
67 int_text2.query = '.widget-area .widget-subarea .widget-hbox-single .my-second-num-test-text';
68 int_text2.index = this.append_cell(
68 int_text2.index = this.append_cell(
69 'intrange = [widgets.BoundedIntTextWidget(),\n' +
69 'intrange = [widgets.BoundedIntTextWidget(),\n' +
70 ' widgets.IntSliderWidget()]\n' +
70 ' widgets.IntSliderWidget()]\n' +
71 '[display(intrange[i]) for i in range(2)]\n' +
71 '[display(intrange[i]) for i in range(2)]\n' +
72 'intrange[0].add_class("my-second-num-test-text", selector="input")\n' +
72 'intrange[0].add_class("my-second-num-test-text", selector="input")\n' +
73 'print(intrange[0].model_id)\n');
73 'print(intrange[0].model_id)\n');
74 this.execute_cell_then(int_text2.index, function(index){
74 this.execute_cell_then(int_text2.index, function(index){
75 int_text2.model_id = this.get_output_cell(index).text.trim();
75 int_text2.model_id = this.get_output_cell(index).text.trim();
76
76
77 this.test.assert(this.cell_element_exists(index,
77 this.test.assert(this.cell_element_exists(index,
78 '.widget-area .widget-subarea'),
78 '.widget-area .widget-subarea'),
79 'Widget subarea exists.');
79 'Widget subarea exists.');
80
80
81 this.test.assert(this.cell_element_exists(index, slider_query),
81 this.test.assert(this.cell_element_exists(index, slider_query),
82 'Widget slider exists.');
82 'Widget slider exists.');
83
83
84 this.test.assert(this.cell_element_exists(index, int_text2.query),
84 this.test.assert(this.cell_element_exists(index, int_text2.query),
85 'Widget int textbox exists.');
85 'Widget int textbox exists.');
86 });
86 });
87
87
88 index = this.append_cell(
88 index = this.append_cell(
89 'for widget in intrange:\n' +
89 'for widget in intrange:\n' +
90 ' widget.max = 50\n' +
90 ' widget.max = 50\n' +
91 ' widget.min = -50\n' +
91 ' widget.min = -50\n' +
92 ' widget.value = 25\n' +
92 ' widget.value = 25\n' +
93 'print("Success")\n');
93 'print("Success")\n');
94 this.execute_cell_then(index, function(index){
94 this.execute_cell_then(index, function(index){
95
95
96 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
96 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
97 'Int range properties cell executed with correct output.');
97 'Int range properties cell executed with correct output.');
98
98
99 this.test.assert(this.cell_element_exists(int_text2.index, slider_query),
99 this.test.assert(this.cell_element_exists(int_text2.index, slider_query),
100 'Widget slider exists.');
100 'Widget slider exists.');
101
101
102 this.test.assert(this.cell_element_function(int_text2.index, slider_query,
102 this.test.assert(this.cell_element_function(int_text2.index, slider_query,
103 'slider', ['value']) == 25,
103 'slider', ['value']) == 25,
104 'Slider set to Python value.');
104 'Slider set to Python value.');
105
105
106 this.test.assert(this.cell_element_function(int_text2.index, int_text2.query,
106 this.test.assert(this.cell_element_function(int_text2.index, int_text2.query,
107 'val') == 25, 'Int textbox set to Python value.');
107 'val') == 25, 'Int textbox set to Python value.');
108
108
109 // Clear the int textbox value and then set it to 1 by emulating
109 // Clear the int textbox value and then set it to 1 by emulating
110 // keyboard presses.
110 // keyboard presses.
111 this.evaluate(function(q){
111 this.evaluate(function(q){
112 var textbox = IPython.notebook.element.find(q);
112 var textbox = IPython.notebook.element.find(q);
113 textbox.val('1');
113 textbox.val('1');
114 textbox.trigger('keyup');
114 textbox.trigger('keyup');
115 }, {q: int_text2.query});
115 }, {q: int_text2.query});
116 });
116 });
117
117
118 this.wait_for_widget(int_text2);
118 this.wait_for_widget(int_text2);
119
119
120 index = this.append_cell('print(intrange[0].value)\n');
120 index = this.append_cell('print(intrange[0].value)\n');
121 this.execute_cell_then(index, function(index){
121 this.execute_cell_then(index, function(index){
122 this.test.assertEquals(this.get_output_cell(index).text, '1\n',
122 this.test.assertEquals(this.get_output_cell(index).text, '1\n',
123 'Int textbox set int range value');
123 'Int textbox set int range value');
124
124
125 // Clear the int textbox value and then set it to 120 by emulating
125 // Clear the int textbox value and then set it to 120 by emulating
126 // keyboard presses.
126 // keyboard presses.
127 this.evaluate(function(q){
127 this.evaluate(function(q){
128 var textbox = IPython.notebook.element.find(q);
128 var textbox = IPython.notebook.element.find(q);
129 textbox.val('120');
129 textbox.val('120');
130 textbox.trigger('keyup');
130 textbox.trigger('keyup');
131 }, {q: int_text2.query});
131 }, {q: int_text2.query});
132 });
132 });
133
133
134 this.wait_for_widget(int_text2);
134 this.wait_for_widget(int_text2);
135
135
136 index = this.append_cell('print(intrange[0].value)\n');
136 index = this.append_cell('print(intrange[0].value)\n');
137 this.execute_cell_then(index, function(index){
137 this.execute_cell_then(index, function(index){
138 this.test.assertEquals(this.get_output_cell(index).text, '50\n',
138 this.test.assertEquals(this.get_output_cell(index).text, '50\n',
139 'Int textbox value bound');
139 'Int textbox value bound');
140
140
141 // Clear the int textbox value and then set it to 'hello world' by
141 // Clear the int textbox value and then set it to 'hello world' by
142 // emulating keyboard presses. 'hello world' should get filtered...
142 // emulating keyboard presses. 'hello world' should get filtered...
143 this.evaluate(function(q){
143 this.evaluate(function(q){
144 var textbox = IPython.notebook.element.find(q);
144 var textbox = IPython.notebook.element.find(q);
145 textbox.val('hello world');
145 textbox.val('hello world');
146 textbox.trigger('keyup');
146 textbox.trigger('keyup');
147 }, {q: int_text2.query});
147 }, {q: int_text2.query});
148 });
148 });
149
149
150 this.wait_for_widget(int_text2);
150 this.wait_for_widget(int_text2);
151
151
152 index = this.append_cell('print(intrange[0].value)\n');
152 index = this.append_cell('print(intrange[0].value)\n');
153 this.execute_cell_then(index, function(index){
153 this.execute_cell_then(index, function(index){
154 this.test.assertEquals(this.get_output_cell(index).text, '50\n',
154 this.test.assertEquals(this.get_output_cell(index).text, '50\n',
155 'Invalid int textbox characters ignored');
155 'Invalid int textbox characters ignored');
156 });
156 });
157 }); No newline at end of file
157 });
@@ -1,138 +1,138 b''
1 // Test selection class
1 // Test selection class
2 casper.notebook_test(function () {
2 casper.notebook_test(function () {
3 index = this.append_cell(
3 index = this.append_cell(
4 'from IPython.html import widgets\n' +
4 'from IPython.html import widgets\n' +
5 'from IPython.display import display, clear_output\n' +
5 'from IPython.display import display, clear_output\n' +
6 'print("Success")');
6 'print("Success")');
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var combo_selector = '.widget-area .widget-subarea .widget-hbox-single .btn-group .widget-combo-btn';
9 var combo_selector = '.widget-area .widget-subarea .widget-hbox-single .btn-group .widget-combo-btn';
10 var multibtn_selector = '.widget-area .widget-subarea .widget-hbox-single .btn-group[data-toggle="buttons-radio"]';
10 var multibtn_selector = '.widget-area .widget-subarea .widget-hbox-single .btn-group[data-toggle="buttons-radio"]';
11 var radio_selector = '.widget-area .widget-subarea .widget-hbox .widget-radio-box';
11 var radio_selector = '.widget-area .widget-subarea .widget-hbox .widget-radio-box';
12 var list_selector = '.widget-area .widget-subarea .widget-hbox .widget-listbox';
12 var list_selector = '.widget-area .widget-subarea .widget-hbox .widget-listbox';
13
13
14 var selection_index;
14 var selection_index;
15 var selection_values = 'abcd';
15 var selection_values = 'abcd';
16 var check_state = function(context, index, state){
16 var check_state = function(context, index, state){
17 if (0 <= index && index < selection_values.length) {
17 if (0 <= index && index < selection_values.length) {
18 var multibtn_state = context.cell_element_function(selection_index, multibtn_selector + ' .btn:nth-child(' + (index + 1) + ')', 'hasClass', ['active']);
18 var multibtn_state = context.cell_element_function(selection_index, multibtn_selector + ' .btn:nth-child(' + (index + 1) + ')', 'hasClass', ['active']);
19 var radio_state = context.cell_element_function(selection_index, radio_selector + ' .radio:nth-child(' + (index + 1) + ') input', 'prop', ['checked']);
19 var radio_state = context.cell_element_function(selection_index, radio_selector + ' .radio:nth-child(' + (index + 1) + ') input', 'prop', ['checked']);
20 var list_val = context.cell_element_function(selection_index, list_selector, 'val');
20 var list_val = context.cell_element_function(selection_index, list_selector, 'val');
21 var combo_val = context.cell_element_function(selection_index, combo_selector, 'html');
21 var combo_val = context.cell_element_function(selection_index, combo_selector, 'html');
22
22
23 var val = selection_values.charAt(index);
23 var val = selection_values.charAt(index);
24 var list_state = (val == list_val);
24 var list_state = (val == list_val);
25 var combo_state = (val == combo_val);
25 var combo_state = (val == combo_val);
26
26
27 return multibtn_state == state &&
27 return multibtn_state == state &&
28 radio_state == state &&
28 radio_state == state &&
29 list_state == state &&
29 list_state == state &&
30 combo_state == state;
30 combo_state == state;
31 }
31 }
32 return true;
32 return true;
33 };
33 };
34
34
35 var verify_selection = function(context, index){
35 var verify_selection = function(context, index){
36 for (var i = 0; i < selection_values.length; i++) {
36 for (var i = 0; i < selection_values.length; i++) {
37 if (!check_state(context, i, i==index)) {
37 if (!check_state(context, i, i==index)) {
38 return false;
38 return false;
39 }
39 }
40 }
40 }
41 return true;
41 return true;
42 };
42 };
43
43
44 //values=["' + selection_values + '"[i] for i in range(4)]
44 //values=["' + selection_values + '"[i] for i in range(4)]
45 selection_index = this.append_cell(
45 selection_index = this.append_cell(
46 'values=["' + selection_values + '"[i] for i in range(4)]\n' +
46 'values=["' + selection_values + '"[i] for i in range(4)]\n' +
47 'selection = [widgets.DropdownWidget(values=values),\n' +
47 'selection = [widgets.Dropdown(values=values),\n' +
48 ' widgets.ToggleButtonsWidget(values=values),\n' +
48 ' widgets.ToggleButtons(values=values),\n' +
49 ' widgets.RadioButtonsWidget(values=values),\n' +
49 ' widgets.RadioButtons(values=values),\n' +
50 ' widgets.SelectWidget(values=values)]\n' +
50 ' widgets.Select(values=values)]\n' +
51 '[display(selection[i]) for i in range(4)]\n' +
51 '[display(selection[i]) for i in range(4)]\n' +
52 'for widget in selection:\n' +
52 'for widget in selection:\n' +
53 ' def handle_change(name,old,new):\n' +
53 ' def handle_change(name,old,new):\n' +
54 ' for other_widget in selection:\n' +
54 ' for other_widget in selection:\n' +
55 ' other_widget.value = new\n' +
55 ' other_widget.value = new\n' +
56 ' widget.on_trait_change(handle_change, "value")\n' +
56 ' widget.on_trait_change(handle_change, "value")\n' +
57 'print("Success")\n');
57 'print("Success")\n');
58 this.execute_cell_then(selection_index, function(index){
58 this.execute_cell_then(selection_index, function(index){
59 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
59 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
60 'Create selection cell executed with correct output.');
60 'Create selection cell executed with correct output.');
61
61
62 this.test.assert(this.cell_element_exists(index,
62 this.test.assert(this.cell_element_exists(index,
63 '.widget-area .widget-subarea'),
63 '.widget-area .widget-subarea'),
64 'Widget subarea exists.');
64 'Widget subarea exists.');
65
65
66 this.test.assert(this.cell_element_exists(index, combo_selector),
66 this.test.assert(this.cell_element_exists(index, combo_selector),
67 'Widget combobox exists.');
67 'Widget combobox exists.');
68
68
69 this.test.assert(this.cell_element_exists(index, multibtn_selector),
69 this.test.assert(this.cell_element_exists(index, multibtn_selector),
70 'Widget multibutton exists.');
70 'Widget multibutton exists.');
71
71
72 this.test.assert(this.cell_element_exists(index, radio_selector),
72 this.test.assert(this.cell_element_exists(index, radio_selector),
73 'Widget radio buttons exists.');
73 'Widget radio buttons exists.');
74
74
75 this.test.assert(this.cell_element_exists(index, list_selector),
75 this.test.assert(this.cell_element_exists(index, list_selector),
76 'Widget list exists.');
76 'Widget list exists.');
77
77
78 // Verify that no items are selected.
78 // Verify that no items are selected.
79 this.test.assert(verify_selection(this, 0), 'Default first item selected.');
79 this.test.assert(verify_selection(this, 0), 'Default first item selected.');
80 });
80 });
81
81
82 index = this.append_cell(
82 index = this.append_cell(
83 'for widget in selection:\n' +
83 'for widget in selection:\n' +
84 ' widget.value = "a"\n' +
84 ' widget.value = "a"\n' +
85 'print("Success")\n');
85 'print("Success")\n');
86 this.execute_cell_then(index, function(index){
86 this.execute_cell_then(index, function(index){
87 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
87 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
88 'Python select item executed with correct output.');
88 'Python select item executed with correct output.');
89
89
90 // Verify that the first item is selected.
90 // Verify that the first item is selected.
91 this.test.assert(verify_selection(this, 0), 'Python selected');
91 this.test.assert(verify_selection(this, 0), 'Python selected');
92
92
93 // Verify that selecting a radio button updates all of the others.
93 // Verify that selecting a radio button updates all of the others.
94 this.cell_element_function(selection_index, radio_selector + ' .radio:nth-child(2) input', 'click');
94 this.cell_element_function(selection_index, radio_selector + ' .radio:nth-child(2) input', 'click');
95 });
95 });
96 this.wait_for_idle();
96 this.wait_for_idle();
97 this.then(function () {
97 this.then(function () {
98 this.test.assert(verify_selection(this, 1), 'Radio button selection updated view states correctly.');
98 this.test.assert(verify_selection(this, 1), 'Radio button selection updated view states correctly.');
99
99
100 // Verify that selecting a list option updates all of the others.
100 // Verify that selecting a list option updates all of the others.
101 this.cell_element_function(selection_index, list_selector + ' option:nth-child(3)', 'click');
101 this.cell_element_function(selection_index, list_selector + ' option:nth-child(3)', 'click');
102 });
102 });
103 this.wait_for_idle();
103 this.wait_for_idle();
104 this.then(function () {
104 this.then(function () {
105 this.test.assert(verify_selection(this, 2), 'List selection updated view states correctly.');
105 this.test.assert(verify_selection(this, 2), 'List selection updated view states correctly.');
106
106
107 // Verify that selecting a multibutton option updates all of the others.
107 // Verify that selecting a multibutton option updates all of the others.
108 // Bootstrap3 has changed the toggle button group behavior. Two clicks
108 // Bootstrap3 has changed the toggle button group behavior. Two clicks
109 // are required to actually select an item.
109 // are required to actually select an item.
110 this.cell_element_function(selection_index, multibtn_selector + ' .btn:nth-child(4)', 'click');
110 this.cell_element_function(selection_index, multibtn_selector + ' .btn:nth-child(4)', 'click');
111 this.cell_element_function(selection_index, multibtn_selector + ' .btn:nth-child(4)', 'click');
111 this.cell_element_function(selection_index, multibtn_selector + ' .btn:nth-child(4)', 'click');
112 });
112 });
113 this.wait_for_idle();
113 this.wait_for_idle();
114 this.then(function () {
114 this.then(function () {
115 this.test.assert(verify_selection(this, 3), 'Multibutton selection updated view states correctly.');
115 this.test.assert(verify_selection(this, 3), 'Multibutton selection updated view states correctly.');
116
116
117 // Verify that selecting a combobox option updates all of the others.
117 // Verify that selecting a combobox option updates all of the others.
118 this.cell_element_function(selection_index, '.widget-area .widget-subarea .widget-hbox-single .btn-group ul.dropdown-menu li:nth-child(3) a', 'click');
118 this.cell_element_function(selection_index, '.widget-area .widget-subarea .widget-hbox-single .btn-group ul.dropdown-menu li:nth-child(3) a', 'click');
119 });
119 });
120 this.wait_for_idle();
120 this.wait_for_idle();
121 this.then(function () {
121 this.then(function () {
122 this.test.assert(verify_selection(this, 2), 'Combobox selection updated view states correctly.');
122 this.test.assert(verify_selection(this, 2), 'Combobox selection updated view states correctly.');
123 });
123 });
124
124
125 this.wait_for_idle();
125 this.wait_for_idle();
126
126
127 index = this.append_cell(
127 index = this.append_cell(
128 'for widget in selection:\n' +
128 'for widget in selection:\n' +
129 ' d = widget.values.copy()\n' +
129 ' d = widget.values.copy()\n' +
130 ' d["z"] = "z"\n' +
130 ' d["z"] = "z"\n' +
131 ' widget.values = d\n' +
131 ' widget.values = d\n' +
132 'selection[0].value = "z"');
132 'selection[0].value = "z"');
133 this.execute_cell_then(index, function(index){
133 this.execute_cell_then(index, function(index){
134
134
135 // Verify that selecting a combobox option updates all of the others.
135 // Verify that selecting a combobox option updates all of the others.
136 this.test.assert(verify_selection(this, 4), 'Item added to selection widget.');
136 this.test.assert(verify_selection(this, 4), 'Item added to selection widget.');
137 });
137 });
138 }); No newline at end of file
138 });
@@ -1,113 +1,113 b''
1 // Test multicontainer class
1 // Test multicontainer class
2 casper.notebook_test(function () {
2 casper.notebook_test(function () {
3 index = this.append_cell(
3 index = this.append_cell(
4 'from IPython.html import widgets\n' +
4 'from IPython.html import widgets\n' +
5 'from IPython.display import display, clear_output\n' +
5 'from IPython.display import display, clear_output\n' +
6 'print("Success")');
6 'print("Success")');
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 // Test tab view
9 // Test tab view
10 var multicontainer1_query = '.widget-area .widget-subarea div div.nav-tabs';
10 var multicontainer1_query = '.widget-area .widget-subarea div div.nav-tabs';
11 var multicontainer1_index = this.append_cell(
11 var multicontainer1_index = this.append_cell(
12 'multicontainer = widgets.TabWidget()\n' +
12 'multicontainer = widgets.Tab()\n' +
13 'page1 = widgets.TextWidget()\n' +
13 'page1 = widgets.Text()\n' +
14 'page2 = widgets.TextWidget()\n' +
14 'page2 = widgets.Text()\n' +
15 'page3 = widgets.TextWidget()\n' +
15 'page3 = widgets.Text()\n' +
16 'multicontainer.children = [page1, page2, page3]\n' +
16 'multicontainer.children = [page1, page2, page3]\n' +
17 'display(multicontainer)\n' +
17 'display(multicontainer)\n' +
18 'multicontainer.selected_index = 0\n' +
18 'multicontainer.selected_index = 0\n' +
19 'print("Success")\n');
19 'print("Success")\n');
20 this.execute_cell_then(multicontainer1_index, function(index){
20 this.execute_cell_then(multicontainer1_index, function(index){
21
21
22 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
22 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
23 'Create multicontainer cell executed with correct output. (1)');
23 'Create multicontainer cell executed with correct output. (1)');
24
24
25 this.test.assert(this.cell_element_exists(index,
25 this.test.assert(this.cell_element_exists(index,
26 '.widget-area .widget-subarea'),
26 '.widget-area .widget-subarea'),
27 'Widget subarea exists.');
27 'Widget subarea exists.');
28
28
29 this.test.assert(this.cell_element_exists(index, multicontainer1_query),
29 this.test.assert(this.cell_element_exists(index, multicontainer1_query),
30 'Widget tab list exists.');
30 'Widget tab list exists.');
31
31
32 this.test.assert(this.cell_element_exists(index, multicontainer1_query),
32 this.test.assert(this.cell_element_exists(index, multicontainer1_query),
33 'First widget tab list exists.');
33 'First widget tab list exists.');
34
34
35 // JQuery selector is 1 based
35 // JQuery selector is 1 based
36 this.click(multicontainer1_query + ' li:nth-child(2) a');
36 this.click(multicontainer1_query + ' li:nth-child(2) a');
37 });
37 });
38
38
39 this.wait_for_idle();
39 this.wait_for_idle();
40
40
41 index = this.append_cell(
41 index = this.append_cell(
42 'print(multicontainer.selected_index)\n' +
42 'print(multicontainer.selected_index)\n' +
43 'multicontainer.selected_index = 2'); // 0 based
43 'multicontainer.selected_index = 2'); // 0 based
44 this.execute_cell_then(index, function(index){
44 this.execute_cell_then(index, function(index){
45 this.test.assertEquals(this.get_output_cell(index).text, '1\n', // 0 based
45 this.test.assertEquals(this.get_output_cell(index).text, '1\n', // 0 based
46 'selected_index property updated with tab change.');
46 'selected_index property updated with tab change.');
47
47
48 // JQuery selector is 1 based
48 // JQuery selector is 1 based
49 this.test.assert(!this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(1)', 'hasClass', ['active']),
49 this.test.assert(!this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(1)', 'hasClass', ['active']),
50 "Tab 1 is not selected.");
50 "Tab 1 is not selected.");
51 this.test.assert(!this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(2)', 'hasClass', ['active']),
51 this.test.assert(!this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(2)', 'hasClass', ['active']),
52 "Tab 2 is not selected.");
52 "Tab 2 is not selected.");
53 this.test.assert(this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(3)', 'hasClass', ['active']),
53 this.test.assert(this.cell_element_function(multicontainer1_index, multicontainer1_query + ' li:nth-child(3)', 'hasClass', ['active']),
54 "Tab 3 is selected.");
54 "Tab 3 is selected.");
55 });
55 });
56
56
57 index = this.append_cell('multicontainer.set_title(1, "hello")\nprint("Success")'); // 0 based
57 index = this.append_cell('multicontainer.set_title(1, "hello")\nprint("Success")'); // 0 based
58 this.execute_cell_then(index, function(index){
58 this.execute_cell_then(index, function(index){
59 this.test.assert(this.cell_element_function(multicontainer1_index, multicontainer1_query +
59 this.test.assert(this.cell_element_function(multicontainer1_index, multicontainer1_query +
60 ' li:nth-child(2) a', 'html') == 'hello',
60 ' li:nth-child(2) a', 'html') == 'hello',
61 'Tab page title set (after display).');
61 'Tab page title set (after display).');
62 });
62 });
63
63
64 // Test accordion view
64 // Test accordion view
65 var multicontainer2_query = '.widget-area .widget-subarea .panel-group';
65 var multicontainer2_query = '.widget-area .widget-subarea .panel-group';
66 var multicontainer2_index = this.append_cell(
66 var multicontainer2_index = this.append_cell(
67 'multicontainer = widgets.AccordionWidget()\n' +
67 'multicontainer = widgets.Accordion()\n' +
68 'page1 = widgets.TextWidget()\n' +
68 'page1 = widgets.Text()\n' +
69 'page2 = widgets.TextWidget()\n' +
69 'page2 = widgets.Text()\n' +
70 'page3 = widgets.TextWidget()\n' +
70 'page3 = widgets.Text()\n' +
71 'multicontainer.children = [page1, page2, page3]\n' +
71 'multicontainer.children = [page1, page2, page3]\n' +
72 'multicontainer.set_title(2, "good")\n' +
72 'multicontainer.set_title(2, "good")\n' +
73 'display(multicontainer)\n' +
73 'display(multicontainer)\n' +
74 'multicontainer.selected_index = 0\n' +
74 'multicontainer.selected_index = 0\n' +
75 'print("Success")\n');
75 'print("Success")\n');
76 this.execute_cell_then(multicontainer2_index, function(index){
76 this.execute_cell_then(multicontainer2_index, function(index){
77
77
78 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
78 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
79 'Create multicontainer cell executed with correct output. (2)');
79 'Create multicontainer cell executed with correct output. (2)');
80
80
81 this.test.assert(this.cell_element_exists(index,
81 this.test.assert(this.cell_element_exists(index,
82 '.widget-area .widget-subarea'),
82 '.widget-area .widget-subarea'),
83 'Widget subarea exists.');
83 'Widget subarea exists.');
84
84
85 this.test.assert(this.cell_element_exists(index, multicontainer2_query),
85 this.test.assert(this.cell_element_exists(index, multicontainer2_query),
86 'Widget accordion exists.');
86 'Widget accordion exists.');
87
87
88 this.test.assert(this.cell_element_exists(index, multicontainer2_query +
88 this.test.assert(this.cell_element_exists(index, multicontainer2_query +
89 ' .panel:nth-child(1) .panel-collapse'),
89 ' .panel:nth-child(1) .panel-collapse'),
90 'First accordion page exists.');
90 'First accordion page exists.');
91
91
92 // JQuery selector is 1 based
92 // JQuery selector is 1 based
93 this.test.assert(this.cell_element_function(index, multicontainer2_query +
93 this.test.assert(this.cell_element_function(index, multicontainer2_query +
94 ' .panel.panel-default:nth-child(3) .panel-heading .accordion-toggle',
94 ' .panel.panel-default:nth-child(3) .panel-heading .accordion-toggle',
95 'html')=='good', 'Accordion page title set (before display).');
95 'html')=='good', 'Accordion page title set (before display).');
96
96
97 // JQuery selector is 1 based
97 // JQuery selector is 1 based
98 this.click(multicontainer2_query + ' .panel:nth-child(2) .panel-heading .accordion-toggle');
98 this.click(multicontainer2_query + ' .panel:nth-child(2) .panel-heading .accordion-toggle');
99 });
99 });
100
100
101 this.wait_for_idle();
101 this.wait_for_idle();
102
102
103 index = this.append_cell('print(multicontainer.selected_index)'); // 0 based
103 index = this.append_cell('print(multicontainer.selected_index)'); // 0 based
104 this.execute_cell_then(index, function(index){
104 this.execute_cell_then(index, function(index){
105 this.test.assertEquals(this.get_output_cell(index).text, '1\n', // 0 based
105 this.test.assertEquals(this.get_output_cell(index).text, '1\n', // 0 based
106 'selected_index property updated with tab change.');
106 'selected_index property updated with tab change.');
107
107
108 var is_collapsed = this.evaluate(function(s){
108 var is_collapsed = this.evaluate(function(s){
109 return $(s + ' div.panel:nth-child(2) a').hasClass('collapsed'); // 1 based
109 return $(s + ' div.panel:nth-child(2) a').hasClass('collapsed'); // 1 based
110 }, {s: multicontainer2_query});
110 }, {s: multicontainer2_query});
111 this.test.assertEquals(is_collapsed, false, 'Was tab actually opened?');
111 this.test.assertEquals(is_collapsed, false, 'Was tab actually opened?');
112 });
112 });
113 }); No newline at end of file
113 });
@@ -1,53 +1,53 b''
1 // Test widget string class
1 // Test widget string class
2 casper.notebook_test(function () {
2 casper.notebook_test(function () {
3 index = this.append_cell(
3 index = this.append_cell(
4 'from IPython.html import widgets\n' +
4 'from IPython.html import widgets\n' +
5 'from IPython.display import display, clear_output\n' +
5 'from IPython.display import display, clear_output\n' +
6 'print("Success")');
6 'print("Success")');
7 this.execute_cell_then(index);
7 this.execute_cell_then(index);
8
8
9 var string_index = this.append_cell(
9 var string_index = this.append_cell(
10 'string_widget = [widgets.TextWidget(value = "xyz", placeholder = "abc"),\n' +
10 'string_widget = [widgets.Text(value = "xyz", placeholder = "abc"),\n' +
11 ' widgets.TextareaWidget(value = "xyz", placeholder = "def"),\n' +
11 ' widgets.Textarea(value = "xyz", placeholder = "def"),\n' +
12 ' widgets.HTMLWidget(value = "xyz"),\n' +
12 ' widgets.HTML(value = "xyz"),\n' +
13 ' widgets.LatexWidget(value = "$\\\\LaTeX{}$")]\n' +
13 ' widgets.Latex(value = "$\\\\LaTeX{}$")]\n' +
14 '[display(widget) for widget in string_widget]\n'+
14 '[display(widget) for widget in string_widget]\n'+
15 'print("Success")');
15 'print("Success")');
16 this.execute_cell_then(string_index, function(index){
16 this.execute_cell_then(string_index, function(index){
17
17
18 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
18 this.test.assertEquals(this.get_output_cell(index).text, 'Success\n',
19 'Create string widget cell executed with correct output.');
19 'Create string widget cell executed with correct output.');
20
20
21 this.test.assert(this.cell_element_exists(index,
21 this.test.assert(this.cell_element_exists(index,
22 '.widget-area .widget-subarea'),
22 '.widget-area .widget-subarea'),
23 'Widget subarea exists.');
23 'Widget subarea exists.');
24
24
25 this.test.assert(this.cell_element_exists(index,
25 this.test.assert(this.cell_element_exists(index,
26 '.widget-area .widget-subarea .widget-hbox-single input[type=text]'),
26 '.widget-area .widget-subarea .widget-hbox-single input[type=text]'),
27 'Textbox exists.');
27 'Textbox exists.');
28
28
29 this.test.assert(this.cell_element_exists(index,
29 this.test.assert(this.cell_element_exists(index,
30 '.widget-area .widget-subarea .widget-hbox textarea'),
30 '.widget-area .widget-subarea .widget-hbox textarea'),
31 'Textarea exists.');
31 'Textarea exists.');
32
32
33 this.test.assert(this.cell_element_function(index,
33 this.test.assert(this.cell_element_function(index,
34 '.widget-area .widget-subarea .widget-hbox textarea', 'val')=='xyz',
34 '.widget-area .widget-subarea .widget-hbox textarea', 'val')=='xyz',
35 'Python set textarea value.');
35 'Python set textarea value.');
36
36
37 this.test.assert(this.cell_element_function(index,
37 this.test.assert(this.cell_element_function(index,
38 '.widget-area .widget-subarea .widget-hbox-single input[type=text]', 'val')=='xyz',
38 '.widget-area .widget-subarea .widget-hbox-single input[type=text]', 'val')=='xyz',
39 'Python set textbox value.');
39 'Python set textbox value.');
40
40
41 this.test.assert(this.cell_element_exists(string_index,
41 this.test.assert(this.cell_element_exists(string_index,
42 '.widget-area .widget-subarea div span.MathJax_Preview'),
42 '.widget-area .widget-subarea div span.MathJax_Preview'),
43 'MathJax parsed the LaTeX successfully.');
43 'MathJax parsed the LaTeX successfully.');
44
44
45 this.test.assert(this.cell_element_function(index,
45 this.test.assert(this.cell_element_function(index,
46 '.widget-area .widget-subarea .widget-hbox textarea', 'attr', ['placeholder'])=='def',
46 '.widget-area .widget-subarea .widget-hbox textarea', 'attr', ['placeholder'])=='def',
47 'Python set textarea placeholder.');
47 'Python set textarea placeholder.');
48
48
49 this.test.assert(this.cell_element_function(index,
49 this.test.assert(this.cell_element_function(index,
50 '.widget-area .widget-subarea .widget-hbox-single input[type=text]', 'attr', ['placeholder'])=='abc',
50 '.widget-area .widget-subarea .widget-hbox-single input[type=text]', 'attr', ['placeholder'])=='abc',
51 'Python set textbox placehoder.');
51 'Python set textbox placehoder.');
52 });
52 });
53 });
53 });
@@ -1,12 +1,24 b''
1 from .widget import Widget, DOMWidget, CallbackDispatcher
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_container import Container, Popup, FlexContainer, HBox, VBox
6 from .widget_float import FloatText, BoundedFloatText, FloatSlider, FloatProgress
7 from .widget_image import Image
8 from .widget_int import IntText, BoundedIntText, IntSlider, IntProgress
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 from .widget_bool import CheckboxWidget, ToggleButtonWidget
15 from .widget_bool import CheckboxWidget, ToggleButtonWidget
4 from .widget_button import ButtonWidget
16 from .widget_button import ButtonWidget
5 from .widget_container import ContainerWidget, PopupWidget, FlexContainerWidget, HBoxWidget, VBoxWidget
17 from .widget_container import ContainerWidget, PopupWidget
6 from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget
18 from .widget_float import FloatTextWidget, BoundedFloatTextWidget, FloatSliderWidget, FloatProgressWidget
7 from .widget_image import ImageWidget
19 from .widget_image import ImageWidget
8 from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget
20 from .widget_int import IntTextWidget, BoundedIntTextWidget, IntSliderWidget, IntProgressWidget
9 from .widget_selection import RadioButtonsWidget, ToggleButtonsWidget, DropdownWidget, SelectWidget
21 from .widget_selection import RadioButtonsWidget, ToggleButtonsWidget, DropdownWidget, SelectWidget
10 from .widget_selectioncontainer import TabWidget, AccordionWidget
22 from .widget_selectioncontainer import TabWidget, AccordionWidget
11 from .widget_string import HTMLWidget, LatexWidget, TextWidget, TextareaWidget
23 from .widget_string import HTMLWidget, LatexWidget, TextWidget, TextareaWidget
12 from .interaction import interact, interactive, fixed
24 from .interaction import interact, interactive, fixed
@@ -1,257 +1,257 b''
1 """Interact with functions using widgets."""
1 """Interact with functions using widgets."""
2
2
3 #-----------------------------------------------------------------------------
3 #-----------------------------------------------------------------------------
4 # Copyright (c) 2013, the IPython Development Team.
4 # Copyright (c) 2013, the IPython Development Team.
5 #
5 #
6 # Distributed under the terms of the Modified BSD License.
6 # Distributed under the terms of the Modified BSD License.
7 #
7 #
8 # The full license is in the file COPYING.txt, distributed with this software.
8 # The full license is in the file COPYING.txt, distributed with this software.
9 #-----------------------------------------------------------------------------
9 #-----------------------------------------------------------------------------
10
10
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12 # Imports
12 # Imports
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14
14
15 from __future__ import print_function
15 from __future__ import print_function
16
16
17 try: # Python >= 3.3
17 try: # Python >= 3.3
18 from inspect import signature, Parameter
18 from inspect import signature, Parameter
19 except ImportError:
19 except ImportError:
20 from IPython.utils.signatures import signature, Parameter
20 from IPython.utils.signatures import signature, Parameter
21 from inspect import getcallargs
21 from inspect import getcallargs
22
22
23 from IPython.core.getipython import get_ipython
23 from IPython.core.getipython import get_ipython
24 from IPython.html.widgets import (Widget, TextWidget,
24 from IPython.html.widgets import (Widget, Text,
25 FloatSliderWidget, IntSliderWidget, CheckboxWidget, DropdownWidget,
25 FloatSlider, IntSlider, Checkbox, Dropdown,
26 ContainerWidget, DOMWidget)
26 Container, DOMWidget)
27 from IPython.display import display, clear_output
27 from IPython.display import display, clear_output
28 from IPython.utils.py3compat import string_types, unicode_type
28 from IPython.utils.py3compat import string_types, unicode_type
29 from IPython.utils.traitlets import HasTraits, Any, Unicode
29 from IPython.utils.traitlets import HasTraits, Any, Unicode
30
30
31 empty = Parameter.empty
31 empty = Parameter.empty
32
32
33 #-----------------------------------------------------------------------------
33 #-----------------------------------------------------------------------------
34 # Classes and Functions
34 # Classes and Functions
35 #-----------------------------------------------------------------------------
35 #-----------------------------------------------------------------------------
36
36
37
37
38 def _matches(o, pattern):
38 def _matches(o, pattern):
39 """Match a pattern of types in a sequence."""
39 """Match a pattern of types in a sequence."""
40 if not len(o) == len(pattern):
40 if not len(o) == len(pattern):
41 return False
41 return False
42 comps = zip(o,pattern)
42 comps = zip(o,pattern)
43 return all(isinstance(obj,kind) for obj,kind in comps)
43 return all(isinstance(obj,kind) for obj,kind in comps)
44
44
45
45
46 def _get_min_max_value(min, max, value=None, step=None):
46 def _get_min_max_value(min, max, value=None, step=None):
47 """Return min, max, value given input values with possible None."""
47 """Return min, max, value given input values with possible None."""
48 if value is None:
48 if value is None:
49 if not max > min:
49 if not max > min:
50 raise ValueError('max must be greater than min: (min={0}, max={1})'.format(min, max))
50 raise ValueError('max must be greater than min: (min={0}, max={1})'.format(min, max))
51 value = min + abs(min-max)/2
51 value = min + abs(min-max)/2
52 value = type(min)(value)
52 value = type(min)(value)
53 elif min is None and max is None:
53 elif min is None and max is None:
54 if value == 0.0:
54 if value == 0.0:
55 min, max, value = 0.0, 1.0, 0.5
55 min, max, value = 0.0, 1.0, 0.5
56 elif value == 0:
56 elif value == 0:
57 min, max, value = 0, 1, 0
57 min, max, value = 0, 1, 0
58 elif isinstance(value, (int, float)):
58 elif isinstance(value, (int, float)):
59 min, max = (-value, 3*value) if value > 0 else (3*value, -value)
59 min, max = (-value, 3*value) if value > 0 else (3*value, -value)
60 else:
60 else:
61 raise TypeError('expected a number, got: %r' % value)
61 raise TypeError('expected a number, got: %r' % value)
62 else:
62 else:
63 raise ValueError('unable to infer range, value from: ({0}, {1}, {2})'.format(min, max, value))
63 raise ValueError('unable to infer range, value from: ({0}, {1}, {2})'.format(min, max, value))
64 if step is not None:
64 if step is not None:
65 # ensure value is on a step
65 # ensure value is on a step
66 r = (value - min) % step
66 r = (value - min) % step
67 value = value - r
67 value = value - r
68 return min, max, value
68 return min, max, value
69
69
70 def _widget_abbrev_single_value(o):
70 def _widget_abbrev_single_value(o):
71 """Make widgets from single values, which can be used as parameter defaults."""
71 """Make widgets from single values, which can be used as parameter defaults."""
72 if isinstance(o, string_types):
72 if isinstance(o, string_types):
73 return TextWidget(value=unicode_type(o))
73 return Text(value=unicode_type(o))
74 elif isinstance(o, dict):
74 elif isinstance(o, dict):
75 return DropdownWidget(values=o)
75 return Dropdown(values=o)
76 elif isinstance(o, bool):
76 elif isinstance(o, bool):
77 return CheckboxWidget(value=o)
77 return Checkbox(value=o)
78 elif isinstance(o, float):
78 elif isinstance(o, float):
79 min, max, value = _get_min_max_value(None, None, o)
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 elif isinstance(o, int):
81 elif isinstance(o, int):
82 min, max, value = _get_min_max_value(None, None, o)
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 else:
84 else:
85 return None
85 return None
86
86
87 def _widget_abbrev(o):
87 def _widget_abbrev(o):
88 """Make widgets from abbreviations: single values, lists or tuples."""
88 """Make widgets from abbreviations: single values, lists or tuples."""
89 float_or_int = (float, int)
89 float_or_int = (float, int)
90 if isinstance(o, (list, tuple)):
90 if isinstance(o, (list, tuple)):
91 if o and all(isinstance(x, string_types) for x in o):
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 elif _matches(o, (float_or_int, float_or_int)):
93 elif _matches(o, (float_or_int, float_or_int)):
94 min, max, value = _get_min_max_value(o[0], o[1])
94 min, max, value = _get_min_max_value(o[0], o[1])
95 if all(isinstance(_, int) for _ in o):
95 if all(isinstance(_, int) for _ in o):
96 cls = IntSliderWidget
96 cls = IntSlider
97 else:
97 else:
98 cls = FloatSliderWidget
98 cls = FloatSlider
99 return cls(value=value, min=min, max=max)
99 return cls(value=value, min=min, max=max)
100 elif _matches(o, (float_or_int, float_or_int, float_or_int)):
100 elif _matches(o, (float_or_int, float_or_int, float_or_int)):
101 step = o[2]
101 step = o[2]
102 if step <= 0:
102 if step <= 0:
103 raise ValueError("step must be >= 0, not %r" % step)
103 raise ValueError("step must be >= 0, not %r" % step)
104 min, max, value = _get_min_max_value(o[0], o[1], step=step)
104 min, max, value = _get_min_max_value(o[0], o[1], step=step)
105 if all(isinstance(_, int) for _ in o):
105 if all(isinstance(_, int) for _ in o):
106 cls = IntSliderWidget
106 cls = IntSlider
107 else:
107 else:
108 cls = FloatSliderWidget
108 cls = FloatSlider
109 return cls(value=value, min=min, max=max, step=step)
109 return cls(value=value, min=min, max=max, step=step)
110 else:
110 else:
111 return _widget_abbrev_single_value(o)
111 return _widget_abbrev_single_value(o)
112
112
113 def _widget_from_abbrev(abbrev, default=empty):
113 def _widget_from_abbrev(abbrev, default=empty):
114 """Build a Widget instance given an abbreviation or Widget."""
114 """Build a Widget instance given an abbreviation or Widget."""
115 if isinstance(abbrev, Widget) or isinstance(abbrev, fixed):
115 if isinstance(abbrev, Widget) or isinstance(abbrev, fixed):
116 return abbrev
116 return abbrev
117
117
118 widget = _widget_abbrev(abbrev)
118 widget = _widget_abbrev(abbrev)
119 if default is not empty and isinstance(abbrev, (list, tuple, dict)):
119 if default is not empty and isinstance(abbrev, (list, tuple, dict)):
120 # if it's not a single-value abbreviation,
120 # if it's not a single-value abbreviation,
121 # set the initial value from the default
121 # set the initial value from the default
122 try:
122 try:
123 widget.value = default
123 widget.value = default
124 except Exception:
124 except Exception:
125 # ignore failure to set default
125 # ignore failure to set default
126 pass
126 pass
127 if widget is None:
127 if widget is None:
128 raise ValueError("%r cannot be transformed to a Widget" % (abbrev,))
128 raise ValueError("%r cannot be transformed to a Widget" % (abbrev,))
129 return widget
129 return widget
130
130
131 def _yield_abbreviations_for_parameter(param, kwargs):
131 def _yield_abbreviations_for_parameter(param, kwargs):
132 """Get an abbreviation for a function parameter."""
132 """Get an abbreviation for a function parameter."""
133 name = param.name
133 name = param.name
134 kind = param.kind
134 kind = param.kind
135 ann = param.annotation
135 ann = param.annotation
136 default = param.default
136 default = param.default
137 not_found = (name, empty, empty)
137 not_found = (name, empty, empty)
138 if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY):
138 if kind in (Parameter.POSITIONAL_OR_KEYWORD, Parameter.KEYWORD_ONLY):
139 if name in kwargs:
139 if name in kwargs:
140 value = kwargs.pop(name)
140 value = kwargs.pop(name)
141 elif ann is not empty:
141 elif ann is not empty:
142 value = ann
142 value = ann
143 elif default is not empty:
143 elif default is not empty:
144 value = default
144 value = default
145 else:
145 else:
146 yield not_found
146 yield not_found
147 yield (name, value, default)
147 yield (name, value, default)
148 elif kind == Parameter.VAR_KEYWORD:
148 elif kind == Parameter.VAR_KEYWORD:
149 # In this case name=kwargs and we yield the items in kwargs with their keys.
149 # In this case name=kwargs and we yield the items in kwargs with their keys.
150 for k, v in kwargs.copy().items():
150 for k, v in kwargs.copy().items():
151 kwargs.pop(k)
151 kwargs.pop(k)
152 yield k, v, empty
152 yield k, v, empty
153
153
154 def _find_abbreviations(f, kwargs):
154 def _find_abbreviations(f, kwargs):
155 """Find the abbreviations for a function and kwargs passed to interact."""
155 """Find the abbreviations for a function and kwargs passed to interact."""
156 new_kwargs = []
156 new_kwargs = []
157 for param in signature(f).parameters.values():
157 for param in signature(f).parameters.values():
158 for name, value, default in _yield_abbreviations_for_parameter(param, kwargs):
158 for name, value, default in _yield_abbreviations_for_parameter(param, kwargs):
159 if value is empty:
159 if value is empty:
160 raise ValueError('cannot find widget or abbreviation for argument: {!r}'.format(name))
160 raise ValueError('cannot find widget or abbreviation for argument: {!r}'.format(name))
161 new_kwargs.append((name, value, default))
161 new_kwargs.append((name, value, default))
162 return new_kwargs
162 return new_kwargs
163
163
164 def _widgets_from_abbreviations(seq):
164 def _widgets_from_abbreviations(seq):
165 """Given a sequence of (name, abbrev) tuples, return a sequence of Widgets."""
165 """Given a sequence of (name, abbrev) tuples, return a sequence of Widgets."""
166 result = []
166 result = []
167 for name, abbrev, default in seq:
167 for name, abbrev, default in seq:
168 widget = _widget_from_abbrev(abbrev, default)
168 widget = _widget_from_abbrev(abbrev, default)
169 if not widget.description:
169 if not widget.description:
170 widget.description = name
170 widget.description = name
171 result.append(widget)
171 result.append(widget)
172 return result
172 return result
173
173
174 def interactive(__interact_f, **kwargs):
174 def interactive(__interact_f, **kwargs):
175 """Build a group of widgets to interact with a function."""
175 """Build a group of widgets to interact with a function."""
176 f = __interact_f
176 f = __interact_f
177 co = kwargs.pop('clear_output', True)
177 co = kwargs.pop('clear_output', True)
178 kwargs_widgets = []
178 kwargs_widgets = []
179 container = ContainerWidget()
179 container = Container()
180 container.result = None
180 container.result = None
181 container.args = []
181 container.args = []
182 container.kwargs = dict()
182 container.kwargs = dict()
183 kwargs = kwargs.copy()
183 kwargs = kwargs.copy()
184
184
185 new_kwargs = _find_abbreviations(f, kwargs)
185 new_kwargs = _find_abbreviations(f, kwargs)
186 # Before we proceed, let's make sure that the user has passed a set of args+kwargs
186 # Before we proceed, let's make sure that the user has passed a set of args+kwargs
187 # that will lead to a valid call of the function. This protects against unspecified
187 # that will lead to a valid call of the function. This protects against unspecified
188 # and doubly-specified arguments.
188 # and doubly-specified arguments.
189 getcallargs(f, **{n:v for n,v,_ in new_kwargs})
189 getcallargs(f, **{n:v for n,v,_ in new_kwargs})
190 # Now build the widgets from the abbreviations.
190 # Now build the widgets from the abbreviations.
191 kwargs_widgets.extend(_widgets_from_abbreviations(new_kwargs))
191 kwargs_widgets.extend(_widgets_from_abbreviations(new_kwargs))
192
192
193 # This has to be done as an assignment, not using container.children.append,
193 # This has to be done as an assignment, not using container.children.append,
194 # so that traitlets notices the update. We skip any objects (such as fixed) that
194 # so that traitlets notices the update. We skip any objects (such as fixed) that
195 # are not DOMWidgets.
195 # are not DOMWidgets.
196 c = [w for w in kwargs_widgets if isinstance(w, DOMWidget)]
196 c = [w for w in kwargs_widgets if isinstance(w, DOMWidget)]
197 container.children = c
197 container.children = c
198
198
199 # Build the callback
199 # Build the callback
200 def call_f(name, old, new):
200 def call_f(name, old, new):
201 container.kwargs = {}
201 container.kwargs = {}
202 for widget in kwargs_widgets:
202 for widget in kwargs_widgets:
203 value = widget.value
203 value = widget.value
204 container.kwargs[widget.description] = value
204 container.kwargs[widget.description] = value
205 if co:
205 if co:
206 clear_output(wait=True)
206 clear_output(wait=True)
207 try:
207 try:
208 container.result = f(**container.kwargs)
208 container.result = f(**container.kwargs)
209 except Exception as e:
209 except Exception as e:
210 ip = get_ipython()
210 ip = get_ipython()
211 if ip is None:
211 if ip is None:
212 container.log.warn("Exception in interact callback: %s", e, exc_info=True)
212 container.log.warn("Exception in interact callback: %s", e, exc_info=True)
213 else:
213 else:
214 ip.showtraceback()
214 ip.showtraceback()
215
215
216 # Wire up the widgets
216 # Wire up the widgets
217 for widget in kwargs_widgets:
217 for widget in kwargs_widgets:
218 widget.on_trait_change(call_f, 'value')
218 widget.on_trait_change(call_f, 'value')
219
219
220 container.on_displayed(lambda _: call_f(None, None, None))
220 container.on_displayed(lambda _: call_f(None, None, None))
221
221
222 return container
222 return container
223
223
224 def interact(__interact_f=None, **kwargs):
224 def interact(__interact_f=None, **kwargs):
225 """interact(f, **kwargs)
225 """interact(f, **kwargs)
226
226
227 Interact with a function using widgets."""
227 Interact with a function using widgets."""
228 # positional arg support in: https://gist.github.com/8851331
228 # positional arg support in: https://gist.github.com/8851331
229 if __interact_f is not None:
229 if __interact_f is not None:
230 # This branch handles the cases:
230 # This branch handles the cases:
231 # 1. interact(f, **kwargs)
231 # 1. interact(f, **kwargs)
232 # 2. @interact
232 # 2. @interact
233 # def f(*args, **kwargs):
233 # def f(*args, **kwargs):
234 # ...
234 # ...
235 f = __interact_f
235 f = __interact_f
236 w = interactive(f, **kwargs)
236 w = interactive(f, **kwargs)
237 f.widget = w
237 f.widget = w
238 display(w)
238 display(w)
239 return f
239 return f
240 else:
240 else:
241 # This branch handles the case:
241 # This branch handles the case:
242 # @interact(a=30, b=40)
242 # @interact(a=30, b=40)
243 # def f(*args, **kwargs):
243 # def f(*args, **kwargs):
244 # ...
244 # ...
245 def dec(f):
245 def dec(f):
246 w = interactive(f, **kwargs)
246 w = interactive(f, **kwargs)
247 f.widget = w
247 f.widget = w
248 display(w)
248 display(w)
249 return f
249 return f
250 return dec
250 return dec
251
251
252 class fixed(HasTraits):
252 class fixed(HasTraits):
253 """A pseudo-widget whose value is fixed and never synced to the client."""
253 """A pseudo-widget whose value is fixed and never synced to the client."""
254 value = Any(help="Any Python object")
254 value = Any(help="Any Python object")
255 description = Unicode('', help="Any Python object")
255 description = Unicode('', help="Any Python object")
256 def __init__(self, value, **kwargs):
256 def __init__(self, value, **kwargs):
257 super(fixed, self).__init__(value=value, **kwargs)
257 super(fixed, self).__init__(value=value, **kwargs)
@@ -1,34 +1,37 b''
1 """BoolWidget class.
1 """Bool class.
2
2
3 Represents a boolean using a widget.
3 Represents a boolean using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget
16 from .widget import DOMWidget
17 from IPython.utils.traitlets import Unicode, Bool
17 from IPython.utils.traitlets import Unicode, Bool
18 from IPython.utils.warn import DeprecatedClass
18
19
19 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
20 # Classes
21 # Classes
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 class _BoolWidget(DOMWidget):
23 class _Bool(DOMWidget):
23 value = Bool(False, help="Bool value", sync=True)
24 value = Bool(False, help="Bool value", sync=True)
24 description = Unicode('', help="Description of the boolean (label).", sync=True)
25 description = Unicode('', help="Description of the boolean (label).", sync=True)
25 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
26 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
26
27
27
28
28 class CheckboxWidget(_BoolWidget):
29 class Checkbox(_Bool):
29 _view_name = Unicode('CheckboxView', sync=True)
30 _view_name = Unicode('CheckboxView', sync=True)
30
31
31
32
32 class ToggleButtonWidget(_BoolWidget):
33 class ToggleButton(_Bool):
33 _view_name = Unicode('ToggleButtonView', sync=True)
34 _view_name = Unicode('ToggleButtonView', sync=True)
34
35
36 CheckboxWidget = DeprecatedClass(Checkbox, 'CheckboxWidget')
37 ToggleButtonWidget = DeprecatedClass(ToggleButton, 'ToggleButtonWidget')
@@ -1,56 +1,60 b''
1 """ButtonWidget class.
1 """Button class.
2
2
3 Represents a button in the frontend using a widget. Allows user to listen for
3 Represents a button in the frontend using a widget. Allows user to listen for
4 click events on the button and trigger backend code when the clicks are fired.
4 click events on the button and trigger backend code when the clicks are fired.
5 """
5 """
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (c) 2013, the IPython Development Team.
7 # Copyright (c) 2013, the IPython Development Team.
8 #
8 #
9 # Distributed under the terms of the Modified BSD License.
9 # Distributed under the terms of the Modified BSD License.
10 #
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 from .widget import DOMWidget, CallbackDispatcher
17 from .widget import DOMWidget, CallbackDispatcher
18 from IPython.utils.traitlets import Unicode, Bool
18 from IPython.utils.traitlets import Unicode, Bool
19 from IPython.utils.warn import DeprecatedClass
19
20
20 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
21 # Classes
22 # Classes
22 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
23 class ButtonWidget(DOMWidget):
24 class Button(DOMWidget):
24 _view_name = Unicode('ButtonView', sync=True)
25 _view_name = Unicode('ButtonView', sync=True)
25
26
26 # Keys
27 # Keys
27 description = Unicode('', help="Description of the button (label).", sync=True)
28 description = Unicode('', help="Description of the button (label).", sync=True)
28 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
29 disabled = Bool(False, help="Enable or disable user changes.", sync=True)
29
30
30 def __init__(self, **kwargs):
31 def __init__(self, **kwargs):
31 """Constructor"""
32 """Constructor"""
32 super(ButtonWidget, self).__init__(**kwargs)
33 super(Button, self).__init__(**kwargs)
33 self._click_handlers = CallbackDispatcher()
34 self._click_handlers = CallbackDispatcher()
34 self.on_msg(self._handle_button_msg)
35 self.on_msg(self._handle_button_msg)
35
36
36 def on_click(self, callback, remove=False):
37 def on_click(self, callback, remove=False):
37 """Register a callback to execute when the button is clicked.
38 """Register a callback to execute when the button is clicked.
38
39
39 The callback will be called with one argument,
40 The callback will be called with one argument,
40 the clicked button widget instance.
41 the clicked button widget instance.
41
42
42 Parameters
43 Parameters
43 ----------
44 ----------
44 remove : bool (optional)
45 remove : bool (optional)
45 Set to true to remove the callback from the list of callbacks."""
46 Set to true to remove the callback from the list of callbacks."""
46 self._click_handlers.register_callback(callback, remove=remove)
47 self._click_handlers.register_callback(callback, remove=remove)
47
48
48 def _handle_button_msg(self, _, content):
49 def _handle_button_msg(self, _, content):
49 """Handle a msg from the front-end.
50 """Handle a msg from the front-end.
50
51
51 Parameters
52 Parameters
52 ----------
53 ----------
53 content: dict
54 content: dict
54 Content of the msg."""
55 Content of the msg."""
55 if content.get('event', '') == 'click':
56 if content.get('event', '') == 'click':
56 self._click_handlers(self)
57 self._click_handlers(self)
58
59
60 ButtonWidget = DeprecatedClass(Button, 'ButtonWidget')
@@ -1,59 +1,64 b''
1 """ContainerWidget class.
1 """Container class.
2
2
3 Represents a container that can be used to group other widgets.
3 Represents a container that can be used to group other widgets.
4 """
4 """
5
5
6 # Copyright (c) IPython Development Team.
6 # Copyright (c) IPython Development Team.
7 # Distributed under the terms of the Modified BSD License.
7 # Distributed under the terms of the Modified BSD License.
8
8
9 from .widget import DOMWidget
9 from .widget import DOMWidget
10 from IPython.utils.traitlets import Unicode, Tuple, TraitError, Int, CaselessStrEnum
10 from IPython.utils.traitlets import Unicode, Tuple, TraitError, Int, CaselessStrEnum
11 from IPython.utils.warn import DeprecatedClass
11
12
12 class ContainerWidget(DOMWidget):
13 class Container(DOMWidget):
13 _view_name = Unicode('ContainerView', sync=True)
14 _view_name = Unicode('ContainerView', sync=True)
14
15
15 # Child widgets in the container.
16 # Child widgets in the container.
16 # Using a tuple here to force reassignment to update the list.
17 # Using a tuple here to force reassignment to update the list.
17 # When a proper notifying-list trait exists, that is what should be used here.
18 # When a proper notifying-list trait exists, that is what should be used here.
18 children = Tuple(sync=True, allow_none=False)
19 children = Tuple(sync=True, allow_none=False)
19
20
20 def __init__(self, children = (), **kwargs):
21 def __init__(self, children = (), **kwargs):
21 kwargs['children'] = children
22 kwargs['children'] = children
22 super(ContainerWidget, self).__init__(**kwargs)
23 super(Container, self).__init__(**kwargs)
23 self.on_displayed(ContainerWidget._fire_children_displayed)
24 self.on_displayed(Container._fire_children_displayed)
24
25
25 def _fire_children_displayed(self):
26 def _fire_children_displayed(self):
26 for child in self.children:
27 for child in self.children:
27 child._handle_displayed()
28 child._handle_displayed()
28
29
29
30
30 class PopupWidget(ContainerWidget):
31 class Popup(Container):
31 _view_name = Unicode('PopupView', sync=True)
32 _view_name = Unicode('PopupView', sync=True)
32
33
33 description = Unicode(sync=True)
34 description = Unicode(sync=True)
34 button_text = Unicode(sync=True)
35 button_text = Unicode(sync=True)
35
36
36
37
37 class FlexContainerWidget(ContainerWidget):
38 class FlexContainer(Container):
38 _view_name = Unicode('FlexContainerView', sync=True)
39 _view_name = Unicode('FlexContainerView', sync=True)
39 flex = Int(0, sync=True, help="""Specify the flexible-ness of the model.""")
40 flex = Int(0, sync=True, help="""Specify the flexible-ness of the model.""")
40 def _flex_changed(self, name, old, new):
41 def _flex_changed(self, name, old, new):
41 new = min(max(0, new), 2)
42 new = min(max(0, new), 2)
42 if self.flex != new:
43 if self.flex != new:
43 self.flex = new
44 self.flex = new
44
45
45 _locations = ['start', 'center', 'end', 'baseline', 'stretch']
46 _locations = ['start', 'center', 'end', 'baseline', 'stretch']
46 pack = CaselessStrEnum(
47 pack = CaselessStrEnum(
47 values=_locations,
48 values=_locations,
48 default_value='start', allow_none=False, sync=True)
49 default_value='start', allow_none=False, sync=True)
49 align = CaselessStrEnum(
50 align = CaselessStrEnum(
50 values=_locations,
51 values=_locations,
51 default_value='start', allow_none=False, sync=True)
52 default_value='start', allow_none=False, sync=True)
52
53
53
54
54 class VBoxWidget(FlexContainerWidget):
55 class VBox(FlexContainer):
55 _view_name = Unicode('VBoxContainerView', sync=True)
56 _view_name = Unicode('VBoxContainerView', sync=True)
56
57
57
58
58 class HBoxWidget(FlexContainerWidget):
59 class HBox(FlexContainer):
59 _view_name = Unicode('HBoxContainerView', sync=True)
60 _view_name = Unicode('HBoxContainerView', sync=True)
61
62 ContainerWidget = DeprecatedClass(Container, 'ContainerWidget')
63 PopupWidget = DeprecatedClass(Popup, 'PopupWidget')
64
@@ -1,61 +1,69 b''
1 """FloatWidget class.
1 """Float class.
2
2
3 Represents an unbounded float using a widget.
3 Represents an unbounded float using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget
16 from .widget import DOMWidget
17 from IPython.utils.traitlets import Unicode, CFloat, Bool, Enum
17 from IPython.utils.traitlets import Unicode, CFloat, Bool, Enum
18 from IPython.utils.warn import DeprecatedClass
18
19
19 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
20 # Classes
21 # Classes
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 class _FloatWidget(DOMWidget):
23 class _Float(DOMWidget):
23 value = CFloat(0.0, help="Float value", sync=True)
24 value = CFloat(0.0, help="Float value", sync=True)
24 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 description = Unicode(help="Description of the value this widget represents", sync=True)
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 max = CFloat(100.0, help="Max value", sync=True)
30 max = CFloat(100.0, help="Max value", sync=True)
30 min = CFloat(0.0, help="Min value", sync=True)
31 min = CFloat(0.0, help="Min value", sync=True)
31 step = CFloat(0.1, help="Minimum step that the value can take (ignored by some views)", sync=True)
32 step = CFloat(0.1, help="Minimum step that the value can take (ignored by some views)", sync=True)
32
33
33 def __init__(self, *pargs, **kwargs):
34 def __init__(self, *pargs, **kwargs):
34 """Constructor"""
35 """Constructor"""
35 DOMWidget.__init__(self, *pargs, **kwargs)
36 DOMWidget.__init__(self, *pargs, **kwargs)
36 self._validate('value', None, self.value)
37 self._validate('value', None, self.value)
37 self.on_trait_change(self._validate, ['value', 'min', 'max'])
38 self.on_trait_change(self._validate, ['value', 'min', 'max'])
38
39
39 def _validate(self, name, old, new):
40 def _validate(self, name, old, new):
40 """Validate value, max, min."""
41 """Validate value, max, min."""
41 if self.min > new or new > self.max:
42 if self.min > new or new > self.max:
42 self.value = min(max(new, self.min), self.max)
43 self.value = min(max(new, self.min), self.max)
43
44
44
45
45 class FloatTextWidget(_FloatWidget):
46 class FloatText(_Float):
46 _view_name = Unicode('FloatTextView', sync=True)
47 _view_name = Unicode('FloatTextView', sync=True)
47
48
48
49
49 class BoundedFloatTextWidget(_BoundedFloatWidget):
50 class BoundedFloatText(_BoundedFloat):
50 _view_name = Unicode('FloatTextView', sync=True)
51 _view_name = Unicode('FloatTextView', sync=True)
51
52
52
53
53 class FloatSliderWidget(_BoundedFloatWidget):
54 class FloatSlider(_BoundedFloat):
54 _view_name = Unicode('FloatSliderView', sync=True)
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 help="Vertical or horizontal.", sync=True)
57 help="Vertical or horizontal.", sync=True)
57 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
58 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
58
59
59
60
60 class FloatProgressWidget(_BoundedFloatWidget):
61 class FloatProgress(_BoundedFloat):
61 _view_name = Unicode('ProgressView', sync=True)
62 _view_name = Unicode('ProgressView', sync=True)
63
64 _FloatWidget = DeprecatedClass(_Float, '_FloatWidget')
65 _BoundedFloatWidget = DeprecatedClass(_BoundedFloat, '_BoundedFloatWidget')
66 FloatTextWidget = DeprecatedClass(FloatText, 'FloatTextWidget')
67 BoundedFloatTextWidget = DeprecatedClass(BoundedFloatText, 'BoundedFloatTextWidget')
68 FloatSliderWidget = DeprecatedClass(FloatSlider, 'FloatSliderWidget')
69 FloatProgressWidget = DeprecatedClass(FloatProgress, 'FloatProgressWidget')
@@ -1,35 +1,38 b''
1 """ImageWidget class.
1 """Image class.
2
2
3 Represents an image in the frontend using a widget.
3 Represents an image in the frontend using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 import base64
16 import base64
17
17
18 from .widget import DOMWidget
18 from .widget import DOMWidget
19 from IPython.utils.traitlets import Unicode, CUnicode, Bytes
19 from IPython.utils.traitlets import Unicode, CUnicode, Bytes
20 from IPython.utils.warn import DeprecatedClass
20
21
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 # Classes
23 # Classes
23 #-----------------------------------------------------------------------------
24 #-----------------------------------------------------------------------------
24 class ImageWidget(DOMWidget):
25 class Image(DOMWidget):
25 _view_name = Unicode('ImageView', sync=True)
26 _view_name = Unicode('ImageView', sync=True)
26
27
27 # Define the custom state properties to sync with the front-end
28 # Define the custom state properties to sync with the front-end
28 format = Unicode('png', sync=True)
29 format = Unicode('png', sync=True)
29 width = CUnicode(sync=True)
30 width = CUnicode(sync=True)
30 height = CUnicode(sync=True)
31 height = CUnicode(sync=True)
31 _b64value = Unicode(sync=True)
32 _b64value = Unicode(sync=True)
32
33
33 value = Bytes()
34 value = Bytes()
34 def _value_changed(self, name, old, new):
35 def _value_changed(self, name, old, new):
35 self._b64value = base64.b64encode(new)
36 self._b64value = base64.b64encode(new)
37
38 ImageWidget = DeprecatedClass(Image, 'ImageWidget')
@@ -1,60 +1,68 b''
1 """IntWidget class.
1 """Int class.
2
2
3 Represents an unbounded int using a widget.
3 Represents an unbounded int using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget
16 from .widget import DOMWidget
17 from IPython.utils.traitlets import Unicode, CInt, Bool, Enum
17 from IPython.utils.traitlets import Unicode, CInt, Bool, Enum
18 from IPython.utils.warn import DeprecatedClass
18
19
19 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
20 # Classes
21 # Classes
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 class _IntWidget(DOMWidget):
23 class _Int(DOMWidget):
23 value = CInt(0, help="Int value", sync=True)
24 value = CInt(0, help="Int value", sync=True)
24 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 description = Unicode(help="Description of the value this widget represents", sync=True)
26 description = Unicode(help="Description of the value this widget represents", sync=True)
26
27
27
28
28 class _BoundedIntWidget(_IntWidget):
29 class _BoundedInt(_Int):
29 step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
30 step = CInt(1, help="Minimum step that the value can take (ignored by some views)", sync=True)
30 max = CInt(100, help="Max value", sync=True)
31 max = CInt(100, help="Max value", sync=True)
31 min = CInt(0, help="Min value", sync=True)
32 min = CInt(0, help="Min value", sync=True)
32
33
33 def __init__(self, *pargs, **kwargs):
34 def __init__(self, *pargs, **kwargs):
34 """Constructor"""
35 """Constructor"""
35 DOMWidget.__init__(self, *pargs, **kwargs)
36 DOMWidget.__init__(self, *pargs, **kwargs)
36 self.on_trait_change(self._validate, ['value', 'min', 'max'])
37 self.on_trait_change(self._validate, ['value', 'min', 'max'])
37
38
38 def _validate(self, name, old, new):
39 def _validate(self, name, old, new):
39 """Validate value, max, min."""
40 """Validate value, max, min."""
40 if self.min > new or new > self.max:
41 if self.min > new or new > self.max:
41 self.value = min(max(new, self.min), self.max)
42 self.value = min(max(new, self.min), self.max)
42
43
43
44
44 class IntTextWidget(_IntWidget):
45 class IntText(_Int):
45 _view_name = Unicode('IntTextView', sync=True)
46 _view_name = Unicode('IntTextView', sync=True)
46
47
47
48
48 class BoundedIntTextWidget(_BoundedIntWidget):
49 class BoundedIntText(_BoundedInt):
49 _view_name = Unicode('IntTextView', sync=True)
50 _view_name = Unicode('IntTextView', sync=True)
50
51
51
52
52 class IntSliderWidget(_BoundedIntWidget):
53 class IntSlider(_BoundedInt):
53 _view_name = Unicode('IntSliderView', sync=True)
54 _view_name = Unicode('IntSliderView', sync=True)
54 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
55 orientation = Enum([u'horizontal', u'vertical'], u'horizontal',
55 help="Vertical or horizontal.", sync=True)
56 help="Vertical or horizontal.", sync=True)
56 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
57 readout = Bool(True, help="Display the current value of the slider next to it.", sync=True)
57
58
58
59
59 class IntProgressWidget(_BoundedIntWidget):
60 class IntProgress(_BoundedInt):
60 _view_name = Unicode('ProgressView', sync=True)
61 _view_name = Unicode('ProgressView', sync=True)
62
63 _IntWidget = DeprecatedClass(_Int, '_IntWidget')
64 _BoundedIntWidget = DeprecatedClass(_BoundedInt, '_BoundedIntWidget')
65 IntTextWidget = DeprecatedClass(IntText, 'IntTextWidget')
66 BoundedIntTextWidget = DeprecatedClass(BoundedIntText, 'BoundedIntTextWidget')
67 IntSliderWidget = DeprecatedClass(IntSlider, 'IntSliderWidget')
68 IntProgressWidget = DeprecatedClass(IntProgress, 'IntProgressWidget')
@@ -1,125 +1,132 b''
1 """SelectionWidget classes.
1 """Selection classes.
2
2
3 Represents an enumeration using a widget.
3 Represents an enumeration using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16
16
17 from collections import OrderedDict
17 from collections import OrderedDict
18 from threading import Lock
18 from threading import Lock
19
19
20 from .widget import DOMWidget
20 from .widget import DOMWidget
21 from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict, TraitError
21 from IPython.utils.traitlets import Unicode, List, Bool, Any, Dict, TraitError
22 from IPython.utils.py3compat import unicode_type
22 from IPython.utils.py3compat import unicode_type
23 from IPython.utils.warn import DeprecatedClass
23
24
24 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
25 # SelectionWidget
26 # SelectionWidget
26 #-----------------------------------------------------------------------------
27 #-----------------------------------------------------------------------------
27 class _SelectionWidget(DOMWidget):
28 class _Selection(DOMWidget):
28 """Base class for Selection widgets
29 """Base class for Selection widgets
29
30
30 ``values`` can be specified as a list or dict. If given as a list,
31 ``values`` can be specified as a list or dict. If given as a list,
31 it will be transformed to a dict of the form ``{str(value):value}``.
32 it will be transformed to a dict of the form ``{str(value):value}``.
32 """
33 """
33
34
34 value = Any(help="Selected value")
35 value = Any(help="Selected value")
35 values = Dict(help="""Dictionary of {name: value} the user can select.
36 values = Dict(help="""Dictionary of {name: value} the user can select.
36
37
37 The keys of this dictionary are the strings that will be displayed in the UI,
38 The keys of this dictionary are the strings that will be displayed in the UI,
38 representing the actual Python choices.
39 representing the actual Python choices.
39
40
40 The keys of this dictionary are also available as value_names.
41 The keys of this dictionary are also available as value_names.
41 """)
42 """)
42 value_name = Unicode(help="The name of the selected value", sync=True)
43 value_name = Unicode(help="The name of the selected value", sync=True)
43 value_names = List(Unicode, help="""Read-only list of names for each value.
44 value_names = List(Unicode, help="""Read-only list of names for each value.
44
45
45 If values is specified as a list, this is the string representation of each element.
46 If values is specified as a list, this is the string representation of each element.
46 Otherwise, it is the keys of the values dictionary.
47 Otherwise, it is the keys of the values dictionary.
47
48
48 These strings are used to display the choices in the front-end.""", sync=True)
49 These strings are used to display the choices in the front-end.""", sync=True)
49 disabled = Bool(False, help="Enable or disable user changes", sync=True)
50 disabled = Bool(False, help="Enable or disable user changes", sync=True)
50 description = Unicode(help="Description of the value this widget represents", sync=True)
51 description = Unicode(help="Description of the value this widget represents", sync=True)
51
52
52
53
53 def __init__(self, *args, **kwargs):
54 def __init__(self, *args, **kwargs):
54 self.value_lock = Lock()
55 self.value_lock = Lock()
55 self._in_values_changed = False
56 self._in_values_changed = False
56 if 'values' in kwargs:
57 if 'values' in kwargs:
57 values = kwargs['values']
58 values = kwargs['values']
58 # convert list values to an dict of {str(v):v}
59 # convert list values to an dict of {str(v):v}
59 if isinstance(values, list):
60 if isinstance(values, list):
60 # preserve list order with an OrderedDict
61 # preserve list order with an OrderedDict
61 kwargs['values'] = OrderedDict((unicode_type(v), v) for v in values)
62 kwargs['values'] = OrderedDict((unicode_type(v), v) for v in values)
62 # python3.3 turned on hash randomization by default - this means that sometimes, randomly
63 # python3.3 turned on hash randomization by default - this means that sometimes, randomly
63 # we try to set value before setting values, due to dictionary ordering. To fix this, force
64 # we try to set value before setting values, due to dictionary ordering. To fix this, force
64 # the setting of self.values right now, before anything else runs
65 # the setting of self.values right now, before anything else runs
65 self.values = kwargs.pop('values')
66 self.values = kwargs.pop('values')
66 DOMWidget.__init__(self, *args, **kwargs)
67 DOMWidget.__init__(self, *args, **kwargs)
67
68
68 def _values_changed(self, name, old, new):
69 def _values_changed(self, name, old, new):
69 """Handles when the values dict has been changed.
70 """Handles when the values dict has been changed.
70
71
71 Setting values implies setting value names from the keys of the dict.
72 Setting values implies setting value names from the keys of the dict.
72 """
73 """
73 self._in_values_changed = True
74 self._in_values_changed = True
74 try:
75 try:
75 self.value_names = list(new.keys())
76 self.value_names = list(new.keys())
76 finally:
77 finally:
77 self._in_values_changed = False
78 self._in_values_changed = False
78
79
79 # ensure that the chosen value is one of the choices
80 # ensure that the chosen value is one of the choices
80 if self.value not in new.values():
81 if self.value not in new.values():
81 self.value = next(iter(new.values()))
82 self.value = next(iter(new.values()))
82
83
83 def _value_names_changed(self, name, old, new):
84 def _value_names_changed(self, name, old, new):
84 if not self._in_values_changed:
85 if not self._in_values_changed:
85 raise TraitError("value_names is a read-only proxy to values.keys(). Use the values dict instead.")
86 raise TraitError("value_names is a read-only proxy to values.keys(). Use the values dict instead.")
86
87
87 def _value_changed(self, name, old, new):
88 def _value_changed(self, name, old, new):
88 """Called when value has been changed"""
89 """Called when value has been changed"""
89 if self.value_lock.acquire(False):
90 if self.value_lock.acquire(False):
90 try:
91 try:
91 # Reverse dictionary lookup for the value name
92 # Reverse dictionary lookup for the value name
92 for k,v in self.values.items():
93 for k,v in self.values.items():
93 if new == v:
94 if new == v:
94 # set the selected value name
95 # set the selected value name
95 self.value_name = k
96 self.value_name = k
96 return
97 return
97 # undo the change, and raise KeyError
98 # undo the change, and raise KeyError
98 self.value = old
99 self.value = old
99 raise KeyError(new)
100 raise KeyError(new)
100 finally:
101 finally:
101 self.value_lock.release()
102 self.value_lock.release()
102
103
103 def _value_name_changed(self, name, old, new):
104 def _value_name_changed(self, name, old, new):
104 """Called when the value name has been changed (typically by the frontend)."""
105 """Called when the value name has been changed (typically by the frontend)."""
105 if self.value_lock.acquire(False):
106 if self.value_lock.acquire(False):
106 try:
107 try:
107 self.value = self.values[new]
108 self.value = self.values[new]
108 finally:
109 finally:
109 self.value_lock.release()
110 self.value_lock.release()
110
111
111
112
112 class ToggleButtonsWidget(_SelectionWidget):
113 class ToggleButtons(_Selection):
113 _view_name = Unicode('ToggleButtonsView', sync=True)
114 _view_name = Unicode('ToggleButtonsView', sync=True)
114
115
115
116
116 class DropdownWidget(_SelectionWidget):
117 class Dropdown(_Selection):
117 _view_name = Unicode('DropdownView', sync=True)
118 _view_name = Unicode('DropdownView', sync=True)
118
119
119
120
120 class RadioButtonsWidget(_SelectionWidget):
121 class RadioButtons(_Selection):
121 _view_name = Unicode('RadioButtonsView', sync=True)
122 _view_name = Unicode('RadioButtonsView', sync=True)
122
123
123
124
124 class SelectWidget(_SelectionWidget):
125 class Select(_Selection):
125 _view_name = Unicode('SelectView', sync=True)
126 _view_name = Unicode('SelectView', sync=True)
127
128 _SelectionWidget = DeprecatedClass(_Selection, '_SelectionWidget')
129 ToggleButtonsWidget = DeprecatedClass(ToggleButtons, 'ToggleButtonsWidget')
130 DropdownWidget = DeprecatedClass(Dropdown, 'DropdownWidget')
131 RadioButtonsWidget = DeprecatedClass(RadioButtons, 'RadioButtonsWidget')
132 SelectWidget = DeprecatedClass(Select, 'SelectWidget')
@@ -1,58 +1,63 b''
1 """SelectionContainerWidget class.
1 """SelectionContainer class.
2
2
3 Represents a multipage container that can be used to group other widgets into
3 Represents a multipage container that can be used to group other widgets into
4 pages.
4 pages.
5 """
5 """
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (c) 2013, the IPython Development Team.
7 # Copyright (c) 2013, the IPython Development Team.
8 #
8 #
9 # Distributed under the terms of the Modified BSD License.
9 # Distributed under the terms of the Modified BSD License.
10 #
10 #
11 # The full license is in the file COPYING.txt, distributed with this software.
11 # The full license is in the file COPYING.txt, distributed with this software.
12 #-----------------------------------------------------------------------------
12 #-----------------------------------------------------------------------------
13
13
14 #-----------------------------------------------------------------------------
14 #-----------------------------------------------------------------------------
15 # Imports
15 # Imports
16 #-----------------------------------------------------------------------------
16 #-----------------------------------------------------------------------------
17 from .widget_container import ContainerWidget
17 from .widget_container import ContainerWidget
18 from IPython.utils.traitlets import Unicode, Dict, CInt
18 from IPython.utils.traitlets import Unicode, Dict, CInt
19 from IPython.utils.warn import DeprecatedClass
19
20
20 #-----------------------------------------------------------------------------
21 #-----------------------------------------------------------------------------
21 # Classes
22 # Classes
22 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
23 class _SelectionContainerWidget(ContainerWidget):
24 class _SelectionContainer(ContainerWidget):
24 _titles = Dict(help="Titles of the pages", sync=True)
25 _titles = Dict(help="Titles of the pages", sync=True)
25 selected_index = CInt(0, sync=True)
26 selected_index = CInt(0, sync=True)
26
27
27 # Public methods
28 # Public methods
28 def set_title(self, index, title):
29 def set_title(self, index, title):
29 """Sets the title of a container page.
30 """Sets the title of a container page.
30
31
31 Parameters
32 Parameters
32 ----------
33 ----------
33 index : int
34 index : int
34 Index of the container page
35 Index of the container page
35 title : unicode
36 title : unicode
36 New title"""
37 New title"""
37 self._titles[index] = title
38 self._titles[index] = title
38 self.send_state('_titles')
39 self.send_state('_titles')
39
40
40 def get_title(self, index):
41 def get_title(self, index):
41 """Gets the title of a container pages.
42 """Gets the title of a container pages.
42
43
43 Parameters
44 Parameters
44 ----------
45 ----------
45 index : int
46 index : int
46 Index of the container page"""
47 Index of the container page"""
47 if index in self._titles:
48 if index in self._titles:
48 return self._titles[index]
49 return self._titles[index]
49 else:
50 else:
50 return None
51 return None
51
52
52
53
53 class AccordionWidget(_SelectionContainerWidget):
54 class Accordion(_SelectionContainer):
54 _view_name = Unicode('AccordionView', sync=True)
55 _view_name = Unicode('AccordionView', sync=True)
55
56
56
57
57 class TabWidget(_SelectionContainerWidget):
58 class Tab(_SelectionContainer):
58 _view_name = Unicode('TabView', sync=True)
59 _view_name = Unicode('TabView', sync=True)
60
61 _SelectionContainerWidget = DeprecatedClass(_SelectionContainer, '_SelectionContainerWidget')
62 AccordionWidget = DeprecatedClass(Accordion, 'AccordionWidget')
63 TabWidget = DeprecatedClass(Tab, 'TabWidget')
@@ -1,73 +1,80 b''
1 """StringWidget class.
1 """String class.
2
2
3 Represents a unicode string using a widget.
3 Represents a unicode string using a widget.
4 """
4 """
5 #-----------------------------------------------------------------------------
5 #-----------------------------------------------------------------------------
6 # Copyright (c) 2013, the IPython Development Team.
6 # Copyright (c) 2013, the IPython Development Team.
7 #
7 #
8 # Distributed under the terms of the Modified BSD License.
8 # Distributed under the terms of the Modified BSD License.
9 #
9 #
10 # The full license is in the file COPYING.txt, distributed with this software.
10 # The full license is in the file COPYING.txt, distributed with this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from .widget import DOMWidget, CallbackDispatcher
16 from .widget import DOMWidget, CallbackDispatcher
17 from IPython.utils.traitlets import Unicode, Bool
17 from IPython.utils.traitlets import Unicode, Bool
18 from IPython.utils.warn import DeprecatedClass
18
19
19 #-----------------------------------------------------------------------------
20 #-----------------------------------------------------------------------------
20 # Classes
21 # Classes
21 #-----------------------------------------------------------------------------
22 #-----------------------------------------------------------------------------
22 class _StringWidget(DOMWidget):
23 class _String(DOMWidget):
23 value = Unicode(help="String value", sync=True)
24 value = Unicode(help="String value", sync=True)
24 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 disabled = Bool(False, help="Enable or disable user changes", sync=True)
25 description = Unicode(help="Description of the value this widget represents", sync=True)
26 description = Unicode(help="Description of the value this widget represents", sync=True)
26 placeholder = Unicode("", help="Placeholder text to display when nothing has been typed", sync=True)
27 placeholder = Unicode("", help="Placeholder text to display when nothing has been typed", sync=True)
27
28
28
29
29 class HTMLWidget(_StringWidget):
30 class HTML(_String):
30 _view_name = Unicode('HTMLView', sync=True)
31 _view_name = Unicode('HTMLView', sync=True)
31
32
32
33
33 class LatexWidget(_StringWidget):
34 class Latex(_String):
34 _view_name = Unicode('LatexView', sync=True)
35 _view_name = Unicode('LatexView', sync=True)
35
36
36
37
37 class TextareaWidget(_StringWidget):
38 class Textarea(_String):
38 _view_name = Unicode('TextareaView', sync=True)
39 _view_name = Unicode('TextareaView', sync=True)
39
40
40 def scroll_to_bottom(self):
41 def scroll_to_bottom(self):
41 self.send({"method": "scroll_to_bottom"})
42 self.send({"method": "scroll_to_bottom"})
42
43
43
44
44 class TextWidget(_StringWidget):
45 class Text(_String):
45 _view_name = Unicode('TextView', sync=True)
46 _view_name = Unicode('TextView', sync=True)
46
47
47 def __init__(self, **kwargs):
48 def __init__(self, **kwargs):
48 super(TextWidget, self).__init__(**kwargs)
49 super(Text, self).__init__(**kwargs)
49 self._submission_callbacks = CallbackDispatcher()
50 self._submission_callbacks = CallbackDispatcher()
50 self.on_msg(self._handle_string_msg)
51 self.on_msg(self._handle_string_msg)
51
52
52 def _handle_string_msg(self, _, content):
53 def _handle_string_msg(self, _, content):
53 """Handle a msg from the front-end.
54 """Handle a msg from the front-end.
54
55
55 Parameters
56 Parameters
56 ----------
57 ----------
57 content: dict
58 content: dict
58 Content of the msg."""
59 Content of the msg."""
59 if content.get('event', '') == 'submit':
60 if content.get('event', '') == 'submit':
60 self._submission_callbacks(self)
61 self._submission_callbacks(self)
61
62
62 def on_submit(self, callback, remove=False):
63 def on_submit(self, callback, remove=False):
63 """(Un)Register a callback to handle text submission.
64 """(Un)Register a callback to handle text submission.
64
65
65 Triggered when the user clicks enter.
66 Triggered when the user clicks enter.
66
67
67 Parameters
68 Parameters
68 ----------
69 ----------
69 callback: callable
70 callback: callable
70 Will be called with exactly one argument: the Widget instance
71 Will be called with exactly one argument: the Widget instance
71 remove: bool (optional)
72 remove: bool (optional)
72 Whether to unregister the callback"""
73 Whether to unregister the callback"""
73 self._submission_callbacks.register_callback(callback, remove=remove)
74 self._submission_callbacks.register_callback(callback, remove=remove)
75
76 _StringWidget = DeprecatedClass(_String, '_StringWidget')
77 HTMLWidget = DeprecatedClass(HTML, 'HTMLWidget')
78 LatexWidget = DeprecatedClass(Latex, 'LatexWidget')
79 TextareaWidget = DeprecatedClass(Textarea, 'TextareaWidget')
80 TextWidget = DeprecatedClass(Text, 'TextWidget')
@@ -1,67 +1,81 b''
1 # encoding: utf-8
1 # encoding: utf-8
2 """
2 """
3 Utilities for warnings. Shoudn't we just use the built in warnings module.
3 Utilities for warnings. Shoudn't we just use the built in warnings module.
4 """
4 """
5
5
6 #-----------------------------------------------------------------------------
6 #-----------------------------------------------------------------------------
7 # Copyright (C) 2008-2011 The IPython Development Team
7 # Copyright (C) 2008-2011 The IPython Development Team
8 #
8 #
9 # Distributed under the terms of the BSD License. The full license is in
9 # Distributed under the terms of the BSD License. The full license is in
10 # the file COPYING, distributed as part of this software.
10 # the file COPYING, distributed as part of this software.
11 #-----------------------------------------------------------------------------
11 #-----------------------------------------------------------------------------
12
12
13 #-----------------------------------------------------------------------------
13 #-----------------------------------------------------------------------------
14 # Imports
14 # Imports
15 #-----------------------------------------------------------------------------
15 #-----------------------------------------------------------------------------
16 from __future__ import print_function
16 from __future__ import print_function
17
17
18 import sys
18 import sys
19 import warnings
19
20
20 from IPython.utils import io
21 from IPython.utils import io
21
22
22 #-----------------------------------------------------------------------------
23 #-----------------------------------------------------------------------------
23 # Code
24 # Code
24 #-----------------------------------------------------------------------------
25 #-----------------------------------------------------------------------------
25
26
26 def warn(msg,level=2,exit_val=1):
27 def warn(msg,level=2,exit_val=1):
27 """Standard warning printer. Gives formatting consistency.
28 """Standard warning printer. Gives formatting consistency.
28
29
29 Output is sent to io.stderr (sys.stderr by default).
30 Output is sent to io.stderr (sys.stderr by default).
30
31
31 Options:
32 Options:
32
33
33 -level(2): allows finer control:
34 -level(2): allows finer control:
34 0 -> Do nothing, dummy function.
35 0 -> Do nothing, dummy function.
35 1 -> Print message.
36 1 -> Print message.
36 2 -> Print 'WARNING:' + message. (Default level).
37 2 -> Print 'WARNING:' + message. (Default level).
37 3 -> Print 'ERROR:' + message.
38 3 -> Print 'ERROR:' + message.
38 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
39 4 -> Print 'FATAL ERROR:' + message and trigger a sys.exit(exit_val).
39
40
40 -exit_val (1): exit value returned by sys.exit() for a level 4
41 -exit_val (1): exit value returned by sys.exit() for a level 4
41 warning. Ignored for all other levels."""
42 warning. Ignored for all other levels."""
42
43
43 if level>0:
44 if level>0:
44 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
45 header = ['','','WARNING: ','ERROR: ','FATAL ERROR: ']
45 print(header[level], msg, sep='', file=io.stderr)
46 print(header[level], msg, sep='', file=io.stderr)
46 if level == 4:
47 if level == 4:
47 print('Exiting.\n', file=io.stderr)
48 print('Exiting.\n', file=io.stderr)
48 sys.exit(exit_val)
49 sys.exit(exit_val)
49
50
50
51
51 def info(msg):
52 def info(msg):
52 """Equivalent to warn(msg,level=1)."""
53 """Equivalent to warn(msg,level=1)."""
53
54
54 warn(msg,level=1)
55 warn(msg,level=1)
55
56
56
57
57 def error(msg):
58 def error(msg):
58 """Equivalent to warn(msg,level=3)."""
59 """Equivalent to warn(msg,level=3)."""
59
60
60 warn(msg,level=3)
61 warn(msg,level=3)
61
62
62
63
63 def fatal(msg,exit_val=1):
64 def fatal(msg,exit_val=1):
64 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
65 """Equivalent to warn(msg,exit_val=exit_val,level=4)."""
65
66
66 warn(msg,exit_val=exit_val,level=4)
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 = []
General Comments 0
You need to be logged in to leave comments. Login now