Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit 3a2bd15

Browse files
author
Brad Miller
committed
Add options and test
1 parent 05089c9 commit 3a2bd15

6 files changed

Lines changed: 264 additions & 13 deletions

File tree

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
div.runestone .jexcel_container {
2+
max-height: 550px;
3+
overflow: scroll;
4+
max-width: 800px;
5+
overflow: scroll;
6+
}

runestone/spreadsheet/js/spreadsheet.js

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,11 @@ class SpreadSheet extends RunestoneBase {
99
this.data = eval(`${this.div_id}_data`);
1010
this.autograde = $(orig).data("autograde");
1111
this.suffix = window[`${this.div_id}_asserts`];
12+
this.mindimensions = $(orig).data("mindimensions");
13+
this.colwidths = $(orig).data("colwidths");
14+
this.coltitles = eval($(orig).data("coltitles"));
15+
this.maxHeight = 50;
16+
// Render the components
1217
this.renderSheet();
1318

1419
if (this.autograde) {
@@ -19,7 +24,29 @@ class SpreadSheet extends RunestoneBase {
1924

2025
renderSheet() {
2126
let div = document.getElementById(this.sheet_id);
22-
this.table = jexcel(div, {data:this.data});
27+
let opts = {data:this.data,
28+
tableHeight: this.maxHeight
29+
};
30+
if (this.mindimensions) {
31+
opts.minDimensions = this.mindimensions;
32+
}
33+
opts.columns = [];
34+
if (this.colwidths) {
35+
for (let w of this.colwidths) {
36+
opts.columns.push({width:w});
37+
}
38+
}
39+
if (this.coltitles) {
40+
for (let i in this.coltitles) {
41+
if (opts.columns[i]) {
42+
opts.columns[i].title = this.coltitles[i];
43+
} else {
44+
opts.columns.push({title:this.coltitles[i]});
45+
}
46+
}
47+
}
48+
49+
this.table = jexcel(div, opts);
2350
}
2451

2552
addAutoGradeButton() {
@@ -31,11 +58,12 @@ class SpreadSheet extends RunestoneBase {
3158
this.gradeButton = butt;
3259
$(butt).click(this.doAutoGrade.bind(this));
3360
$(butt).attr("type","button");
61+
$(butt).css("display","block");
3462
}
3563

3664
addOutput() {
3765
this.output = document.createElement('pre');
38-
this.output.id = this.divid+'_stdout';
66+
this.output.id = `${this.div_id}_stdout`;
3967
$(this.output).css("visibility","hidden");
4068
let div = document.getElementById(this.div_id);
4169
div.appendChild(this.output);
@@ -62,7 +90,7 @@ class SpreadSheet extends RunestoneBase {
6290
pct = pct.toLocaleString(undefined, { maximumFractionDigits: 2});
6391
result += `You passed ${this.passed} out of ${this.passed+this.failed} tests for ${pct}%`;
6492
this.logBookEvent({event: 'unittest',
65-
div_id: this.divid,
93+
div_id: this.div_id,
6694
course: eBookConfig.course,
6795
act: `percent:${pct}:passed:${this.passed}:failed:${this.failed}`
6896
});

runestone/spreadsheet/spreadsheet.py

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
#
1616
__author__ = 'bmiller'
1717

18-
import re
18+
import re, os
1919
from docutils import nodes
2020
from docutils.parsers.rst import directives
2121
from runestone.common.runestonedirective import RunestoneNode, RunestoneIdDirective, get_node_line
@@ -66,7 +66,6 @@ class SpreadSheet(RunestoneIdDirective):
6666
:fromcsv: path/to/csv/file
6767
:colwidths: list of column widths
6868
:coltitles: list of column names
69-
:coltypes: list of column types
7069
:mindimensions: mincols, minrows -- minDimensions:[10,5]
7170
7271
A1,B1,C1,D1...
@@ -80,7 +79,7 @@ class SpreadSheet(RunestoneIdDirective):
8079
'fromcsv': directives.unchanged,
8180
'colwidths': directives.unchanged,
8281
'coltitles': directives.unchanged,
83-
'coltypes': directives.unchanged
82+
'mindimensions': directives.unchanged
8483
})
8584

8685

@@ -96,18 +95,34 @@ def run(self):
9695
self.options['asserts'] = suffix
9796
self.options['autograde'] = 'data-autograde="true"'
9897
else:
98+
self.options['asserts'] = '""'
9999
self.options['autograde'] = ''
100100

101101
if 'fromcsv' in self.options:
102-
self.content = self.body_from_csv(self.options['fromcsv'])
102+
self.content = self.body_from_csv(env, self.options['fromcsv'])
103103
else:
104104
if self.content:
105-
self.content = self.body_to_csv()
105+
self.content = self.body_to_csv(self.content)
106106
else:
107107
raise ValueError("You must specify either from csv or provide content in the body")
108108

109109
self.options['data'] = self.content
110110

111+
if 'coltitles' not in self.options:
112+
self.options['coltitles'] = ""
113+
else:
114+
self.options['coltitles'] = "data-coltitles=[{}]".format(self.options['coltitles'])
115+
116+
if 'mindimensions' not in self.options:
117+
self.options['mindimensions'] = ""
118+
else:
119+
self.options['mindimensions'] = "data-mindimensions=[{}]".format(self.options['mindimensions'])
120+
121+
if 'colwidths' not in self.options:
122+
self.options['colwidths'] = ""
123+
else:
124+
self.options['colwidths'] = "data-colwidths=[{}]".format(self.options['colwidths'])
125+
111126
ssnode = SpreadSheetNode(self.options, rawsource=self.block_text)
112127
ssnode.source, ssnode.line = self.state_machine.get_source_and_line(self.lineno)
113128
self.add_name(ssnode) # make this divid available as a target for :ref:
@@ -116,9 +131,9 @@ def run(self):
116131

117132

118133

119-
def body_to_csv(self):
134+
def body_to_csv(self, row_list):
120135
csvlist = []
121-
for row in self.content:
136+
for row in row_list:
122137
if re.match(r'^\s*====', row):
123138
break
124139
items = row.split(',')
@@ -134,8 +149,16 @@ def body_to_csv(self):
134149
csvlist.append(ilist)
135150
return csvlist
136151

137-
def body_from_csv(self, csvfile):
138-
return "to do"
152+
def body_from_csv(self, env, csvfile):
153+
ffpath = os.path.dirname(self.srcpath)
154+
print(self.srcpath, os.getcwd())
155+
filename = os.path.join(env.srcdir, ffpath, csvfile)
156+
157+
print("\n\nPATH=", self.srcpath)
158+
with open(filename,'r') as csv:
159+
content = csv.readlines()
160+
161+
return self.body_to_csv(content)
139162

140163
def is_float(s):
141164
try:
@@ -154,7 +177,7 @@ def as_int_or_float(s):
154177

155178

156179
TEMPLATE = """
157-
<div id="{divid}" data-component="spreadsheet" class="runestone" {autograde}>
180+
<div id="{divid}" data-component="spreadsheet" class="runestone" {autograde} {mindimensions} {colwidths} {coltitles}>
158181
<div id="{divid}_sheet"></div>
159182
160183
<script>
Lines changed: 151 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
Id,SepalLengthCm,SepalWidthCm,PetalLengthCm,PetalWidthCm,
2+
1,5.1,3.5,1.4,0.2,
3+
2,4.9,3,1.4,0.2,
4+
3,4.7,3.2,1.3,0.2,
5+
4,4.6,3.1,1.5,0.2,
6+
5,5,3.6,1.4,0.2,
7+
6,5.4,3.9,1.7,0.4,
8+
7,4.6,3.4,1.4,0.3,
9+
8,5,3.4,1.5,0.2,
10+
9,4.4,2.9,1.4,0.2,
11+
10,4.9,3.1,1.5,0.1,
12+
11,5.4,3.7,1.5,0.2,
13+
12,4.8,3.4,1.6,0.2,
14+
13,4.8,3,1.4,0.1,
15+
14,4.3,3,1.1,0.1,
16+
15,5.8,4,1.2,0.2,
17+
16,5.7,4.4,1.5,0.4,
18+
17,5.4,3.9,1.3,0.4,
19+
18,5.1,3.5,1.4,0.3,
20+
19,5.7,3.8,1.7,0.3,
21+
20,5.1,3.8,1.5,0.3,
22+
21,5.4,3.4,1.7,0.2,
23+
22,5.1,3.7,1.5,0.4,
24+
23,4.6,3.6,1,0.2,
25+
24,5.1,3.3,1.7,0.5,
26+
25,4.8,3.4,1.9,0.2,
27+
26,5,3,1.6,0.2,
28+
27,5,3.4,1.6,0.4,
29+
28,5.2,3.5,1.5,0.2,
30+
29,5.2,3.4,1.4,0.2,
31+
30,4.7,3.2,1.6,0.2,
32+
31,4.8,3.1,1.6,0.2,
33+
32,5.4,3.4,1.5,0.4,
34+
33,5.2,4.1,1.5,0.1,
35+
34,5.5,4.2,1.4,0.2,
36+
35,4.9,3.1,1.5,0.1,
37+
36,5,3.2,1.2,0.2,
38+
37,5.5,3.5,1.3,0.2,
39+
38,4.9,3.1,1.5,0.1,
40+
39,4.4,3,1.3,0.2,
41+
40,5.1,3.4,1.5,0.2,
42+
41,5,3.5,1.3,0.3,
43+
42,4.5,2.3,1.3,0.3,
44+
43,4.4,3.2,1.3,0.2,
45+
44,5,3.5,1.6,0.6,
46+
45,5.1,3.8,1.9,0.4,
47+
46,4.8,3,1.4,0.3,
48+
47,5.1,3.8,1.6,0.2,
49+
48,4.6,3.2,1.4,0.2,
50+
49,5.3,3.7,1.5,0.2,
51+
50,5,3.3,1.4,0.2,
52+
51,7,3.2,4.7,1.4,
53+
52,6.4,3.2,4.5,1.5,
54+
53,6.9,3.1,4.9,1.5,
55+
54,5.5,2.3,4,1.3,
56+
55,6.5,2.8,4.6,1.5,
57+
56,5.7,2.8,4.5,1.3,
58+
57,6.3,3.3,4.7,1.6,
59+
58,4.9,2.4,3.3,1,
60+
59,6.6,2.9,4.6,1.3,
61+
60,5.2,2.7,3.9,1.4,
62+
61,5,2,3.5,1,
63+
62,5.9,3,4.2,1.5,
64+
63,6,2.2,4,1,
65+
64,6.1,2.9,4.7,1.4,
66+
65,5.6,2.9,3.6,1.3,
67+
66,6.7,3.1,4.4,1.4,
68+
67,5.6,3,4.5,1.5,
69+
68,5.8,2.7,4.1,1,
70+
69,6.2,2.2,4.5,1.5,
71+
70,5.6,2.5,3.9,1.1,
72+
71,5.9,3.2,4.8,1.8,
73+
72,6.1,2.8,4,1.3,
74+
73,6.3,2.5,4.9,1.5,
75+
74,6.1,2.8,4.7,1.2,
76+
75,6.4,2.9,4.3,1.3,
77+
76,6.6,3,4.4,1.4,
78+
77,6.8,2.8,4.8,1.4,
79+
78,6.7,3,5,1.7,
80+
79,6,2.9,4.5,1.5,
81+
80,5.7,2.6,3.5,1,
82+
81,5.5,2.4,3.8,1.1,
83+
82,5.5,2.4,3.7,1,
84+
83,5.8,2.7,3.9,1.2,
85+
84,6,2.7,5.1,1.6,
86+
85,5.4,3,4.5,1.5,
87+
86,6,3.4,4.5,1.6,
88+
87,6.7,3.1,4.7,1.5,
89+
88,6.3,2.3,4.4,1.3,
90+
89,5.6,3,4.1,1.3,
91+
90,5.5,2.5,4,1.3,
92+
91,5.5,2.6,4.4,1.2,
93+
92,6.1,3,4.6,1.4,
94+
93,5.8,2.6,4,1.2,
95+
94,5,2.3,3.3,1,
96+
95,5.6,2.7,4.2,1.3,
97+
96,5.7,3,4.2,1.2,
98+
97,5.7,2.9,4.2,1.3,
99+
98,6.2,2.9,4.3,1.3,
100+
99,5.1,2.5,3,1.1,
101+
100,5.7,2.8,4.1,1.3,
102+
101,6.3,3.3,6,2.5,
103+
102,5.8,2.7,5.1,1.9,
104+
103,7.1,3,5.9,2.1,
105+
104,6.3,2.9,5.6,1.8,
106+
105,6.5,3,5.8,2.2,
107+
106,7.6,3,6.6,2.1,
108+
107,4.9,2.5,4.5,1.7,
109+
108,7.3,2.9,6.3,1.8,
110+
109,6.7,2.5,5.8,1.8,
111+
110,7.2,3.6,6.1,2.5,
112+
111,6.5,3.2,5.1,2,
113+
112,6.4,2.7,5.3,1.9,
114+
113,6.8,3,5.5,2.1,
115+
114,5.7,2.5,5,2,
116+
115,5.8,2.8,5.1,2.4,
117+
116,6.4,3.2,5.3,2.3,
118+
117,6.5,3,5.5,1.8,
119+
118,7.7,3.8,6.7,2.2,
120+
119,7.7,2.6,6.9,2.3,
121+
120,6,2.2,5,1.5,
122+
121,6.9,3.2,5.7,2.3,
123+
122,5.6,2.8,4.9,2,
124+
123,7.7,2.8,6.7,2,
125+
124,6.3,2.7,4.9,1.8,
126+
125,6.7,3.3,5.7,2.1,
127+
126,7.2,3.2,6,1.8,
128+
127,6.2,2.8,4.8,1.8,
129+
128,6.1,3,4.9,1.8,
130+
129,6.4,2.8,5.6,2.1,
131+
130,7.2,3,5.8,1.6,
132+
131,7.4,2.8,6.1,1.9,
133+
132,7.9,3.8,6.4,2,
134+
133,6.4,2.8,5.6,2.2,
135+
134,6.3,2.8,5.1,1.5,
136+
135,6.1,2.6,5.6,1.4,
137+
136,7.7,3,6.1,2.3,
138+
137,6.3,3.4,5.6,2.4,
139+
138,6.4,3.1,5.5,1.8,
140+
139,6,3,4.8,1.8,
141+
140,6.9,3.1,5.4,2.1,
142+
141,6.7,3.1,5.6,2.4,
143+
142,6.9,3.1,5.1,2.3,
144+
143,5.8,2.7,5.1,1.9,
145+
144,6.8,3.2,5.9,2.3,
146+
145,6.7,3.3,5.7,2.5,
147+
146,6.7,3,5.2,2.3,
148+
147,6.3,2.5,5,1.9,
149+
148,6.5,3,5.2,2,
150+
149,6.2,3.4,5.4,2.3,
151+
150,5.9,3,5.1,1.8,

runestone/spreadsheet/test/_sources/index.rst

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,9 @@ SECTION 1: Spreadsheets
1717
:::::::::::::::::::::::
1818

1919
.. spreadsheet:: ss1
20+
:mindimensions: 6,5
21+
:colwidths: 200,100,100
22+
:coltitles: 'name','year','price','foo'
2023

2124
Google, 1998, 807.80
2225
Apple, 1976, 116.52
@@ -27,3 +30,11 @@ SECTION 1: Spreadsheets
2730
assert A3 == Yahoo
2831
assert B3 == 1994
2932

33+
34+
.. spreadsheet:: ss2
35+
:fromcsv: Iris.csv
36+
:colwidths: 50,100,100,100,100
37+
38+
====
39+
assert A151 == 150
40+
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
from selenium.webdriver import ActionChains
2+
from selenium.webdriver.support import expected_conditions as EC
3+
from selenium.webdriver.support.ui import WebDriverWait
4+
from selenium.webdriver.common.by import By
5+
import time
6+
from runestone.unittest_base import module_fixture_maker, RunestoneTestCase
7+
8+
setUpModule, tearDownModule = module_fixture_maker(__file__)
9+
10+
11+
class SpreadsheetTests(RunestoneTestCase):
12+
13+
def test_ss_autograde(self):
14+
self.driver.get(self.host + "/index.html")
15+
t2 = self.driver.find_element_by_id("ss1")
16+
self.assertIsNotNone(t2)
17+
time.sleep(1)
18+
rb = t2.find_element_by_class_name("run-button")
19+
self.assertIsNotNone(rb)
20+
rb.click()
21+
out = self.driver.find_element_by_id("ss1_stdout")
22+
self.assertTrue('You passed 2 out of 2 tests' in out.text)
23+
24+
t2 = self.driver.find_element_by_id("ss2")
25+
self.assertIsNotNone(t2)
26+
time.sleep(1)
27+
rb = t2.find_element_by_class_name("run-button")
28+
self.assertIsNotNone(rb)
29+
rb.click()
30+
out = self.driver.find_element_by_id("ss2_stdout")
31+
print(out.text)
32+
self.assertTrue('You passed 1 out of 1 tests' in out.text)

0 commit comments

Comments
 (0)