cornellGrading 2.20.1__tar.gz → 2.22.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {cornellgrading-2.20.1/cornellGrading.egg-info → cornellgrading-2.22.0}/PKG-INFO +1 -1
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading/__init__.py +1 -1
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading/cornellGrading.py +176 -13
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading/cornellQualtrics.py +74 -1
- {cornellgrading-2.20.1 → cornellgrading-2.22.0/cornellGrading.egg-info}/PKG-INFO +1 -1
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/LICENSE +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/MANIFEST.in +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/README.md +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading/cornellInterface.py +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading/dueDatesFromCSV.py +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading/pandocHTMLParser.py +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading/upload_MC_questions.py +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading/utils.py +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading.egg-info/SOURCES.txt +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading.egg-info/dependency_links.txt +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading.egg-info/entry_points.txt +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading.egg-info/requires.txt +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading.egg-info/top_level.txt +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/pyproject.toml +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/scripts/canvastex.py +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/scripts/matlabgrader.py +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/scripts/setupSelfGrading.py +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/setup.cfg +0 -0
- {cornellgrading-2.20.1 → cornellgrading-2.22.0}/setup.py +0 -0
|
@@ -284,9 +284,9 @@ class cornellGrading:
|
|
|
284
284
|
"""Locate folder by name
|
|
285
285
|
|
|
286
286
|
Args:
|
|
287
|
-
|
|
287
|
+
folderName (str):
|
|
288
288
|
Name of folder to return. Must be exact match.
|
|
289
|
-
To see all
|
|
289
|
+
To see all folders do:
|
|
290
290
|
>> for a in c.course.get_folders(): print(a.name)
|
|
291
291
|
|
|
292
292
|
Returns:
|
|
@@ -2086,6 +2086,7 @@ class cornellGrading:
|
|
|
2086
2086
|
preamble="",
|
|
2087
2087
|
selfGradeDueDelta=7,
|
|
2088
2088
|
selfGradeReleasedDelta=3,
|
|
2089
|
+
extraQuestions=[],
|
|
2089
2090
|
):
|
|
2090
2091
|
"""Create a page with reference solutions and a New Quiz linking to the page for
|
|
2091
2092
|
student self-assemssent.
|
|
@@ -2108,6 +2109,8 @@ class cornellGrading:
|
|
|
2108
2109
|
selfGradeReleasedDelta (float):
|
|
2109
2110
|
Days after initial hw duedate that self-grading (and solutions) are
|
|
2110
2111
|
released.
|
|
2112
|
+
extraQuestions (list(dict)):
|
|
2113
|
+
List of dicts defining additional questions to ask
|
|
2111
2114
|
|
|
2112
2115
|
Returns:
|
|
2113
2116
|
None
|
|
@@ -2167,9 +2170,13 @@ class cornellGrading:
|
|
|
2167
2170
|
for j in range(nprobs):
|
|
2168
2171
|
tmp = item.copy()
|
|
2169
2172
|
tmp["position"] = j + 1
|
|
2170
|
-
tmp["entry"]["title"] = f"Problem {j+1} score"
|
|
2173
|
+
tmp["entry"]["title"] = f"Problem {j + 1} score"
|
|
2171
2174
|
self.addNewQuizItem(nq.id, tmp)
|
|
2172
2175
|
|
|
2176
|
+
for j, q in enumerate(extraQuestions):
|
|
2177
|
+
q["position"] = nprobs + j + 1
|
|
2178
|
+
self.addNewQuizItem(nq.id, q)
|
|
2179
|
+
|
|
2173
2180
|
# publish quiz
|
|
2174
2181
|
ass = self.getAssignment(nq.title)
|
|
2175
2182
|
ass.edit(assignment={"published": True})
|
|
@@ -2288,7 +2295,7 @@ class cornellGrading:
|
|
|
2288
2295
|
|
|
2289
2296
|
return submittedScoreNoAssignment, submittedAssignmentNoScore
|
|
2290
2297
|
|
|
2291
|
-
def genNpointNewQuizItem(self, n, item_body=None, title=None,
|
|
2298
|
+
def genNpointNewQuizItem(self, n, item_body=None, title=None, position=0):
|
|
2292
2299
|
"""Generate a New Quiz multiple choice, variable point question with answers
|
|
2293
2300
|
ranging from 0 to n and each answer worth the equivalent number of points.
|
|
2294
2301
|
|
|
@@ -2357,8 +2364,69 @@ class cornellGrading:
|
|
|
2357
2364
|
|
|
2358
2365
|
return q
|
|
2359
2366
|
|
|
2367
|
+
def genBinaryNewQuizItem(self, n, item_body, title, position=0):
|
|
2368
|
+
"""Generate a New Quiz multiple choice, variable point question with answers
|
|
2369
|
+
'Yes' (earning n points) and 'No' (earning 0 points).
|
|
2370
|
+
|
|
2371
|
+
Args:
|
|
2372
|
+
n (int):
|
|
2373
|
+
Number of points possible. Question will have n+1 options (from 0 to n)
|
|
2374
|
+
with each response worth the equivalent number of points
|
|
2375
|
+
item_body (str):
|
|
2376
|
+
Question text (html formatted). This will automatically be wrapped in
|
|
2377
|
+
<p>...</p>
|
|
2378
|
+
title (str):
|
|
2379
|
+
Question title
|
|
2380
|
+
position (int):
|
|
2381
|
+
Position of question in quiz. Defaults to 0
|
|
2382
|
+
|
|
2383
|
+
Returns:
|
|
2384
|
+
dict:
|
|
2385
|
+
New Quiz Multiple choice question definition
|
|
2386
|
+
|
|
2387
|
+
"""
|
|
2388
|
+
|
|
2389
|
+
# generate UUIDs
|
|
2390
|
+
uuids = [uuid.uuid4() for _ in range(2)]
|
|
2391
|
+
|
|
2392
|
+
# create choices and values dict list
|
|
2393
|
+
choices = []
|
|
2394
|
+
values = []
|
|
2395
|
+
for j, val in enumerate(["Yes", "No"]):
|
|
2396
|
+
choices.append(
|
|
2397
|
+
{"id": f"{uuids[j]}", "position": j + 1, "item_body": f"<p>{val}</p>"}
|
|
2398
|
+
)
|
|
2399
|
+
values.append({"value": f"{uuids[j]}", "points": int(val == "Yes") * n})
|
|
2400
|
+
|
|
2401
|
+
q = {
|
|
2402
|
+
"position": position,
|
|
2403
|
+
"points_possible": float(n),
|
|
2404
|
+
"entry_type": "Item",
|
|
2405
|
+
"status": "immutable",
|
|
2406
|
+
"entry": {
|
|
2407
|
+
"title": title,
|
|
2408
|
+
"item_body": f"<p>{item_body}</p>",
|
|
2409
|
+
"calculator_type": "none",
|
|
2410
|
+
"interaction_data": {"choices": choices},
|
|
2411
|
+
"properties": {
|
|
2412
|
+
"shuffle_rules": {"choices": {"to_lock": [], "shuffled": False}},
|
|
2413
|
+
"vary_points_by_answer": True,
|
|
2414
|
+
},
|
|
2415
|
+
"scoring_data": {
|
|
2416
|
+
"value": f"{uuids[0]}",
|
|
2417
|
+
"values": values,
|
|
2418
|
+
},
|
|
2419
|
+
"answer_feedback": {},
|
|
2420
|
+
"scoring_algorithm": "VaryPointsByAnswer",
|
|
2421
|
+
"interaction_type_slug": "choice",
|
|
2422
|
+
"feedback": {},
|
|
2423
|
+
},
|
|
2424
|
+
}
|
|
2425
|
+
|
|
2426
|
+
return q
|
|
2427
|
+
|
|
2360
2428
|
def genNewQuizMultipleChoice(
|
|
2361
|
-
self, question, options, correct_ind, points=1, position=0
|
|
2429
|
+
self, question, options, correct_ind, points=1, position=0, fightml=None
|
|
2362
2430
|
):
|
|
2363
2431
|
"""Generate a new quiz-style multiple choice question dictionary
|
|
2364
2432
|
|
|
@@ -2373,6 +2441,8 @@ class cornellGrading:
|
|
|
2373
2441
|
Number of points for correct answer (defaults to 1).
|
|
2374
2442
|
position (int):
|
|
2375
2443
|
Position of question in quiz. Defaults to 0
|
|
2444
|
+
fightml (str, optional):
|
|
2445
|
+
HTML string from figure upload. Defaults to None.
|
|
2376
2446
|
|
|
2377
2447
|
Returns:
|
|
2378
2448
|
dict:
|
|
@@ -2394,6 +2464,10 @@ class cornellGrading:
|
|
|
2394
2464
|
}
|
|
2395
2465
|
)
|
|
2396
2466
|
|
|
2467
|
+
qtxt = f"<p>{convalllatex(question)}</p>"
|
|
2468
|
+
if fightml is not None:
|
|
2469
|
+
qtxt = f"{qtxt}\n<p>{fightml}</p>"
|
|
2470
|
+
|
|
2397
2471
|
q = {
|
|
2398
2472
|
"position": position,
|
|
2399
2473
|
"points_possible": float(points),
|
|
@@ -2404,7 +2478,7 @@ class cornellGrading:
|
|
|
2404
2478
|
"status": "mutable",
|
|
2405
2479
|
"entry": {
|
|
2406
2480
|
"title": question,
|
|
2407
|
-
"item_body":
|
|
2481
|
+
"item_body": qtxt,
|
|
2408
2482
|
"calculator_type": "none",
|
|
2409
2483
|
"interaction_data": {"choices": choices},
|
|
2410
2484
|
"properties": {
|
|
@@ -2422,7 +2496,7 @@ class cornellGrading:
|
|
|
2422
2496
|
return q
|
|
2423
2497
|
|
|
2424
2498
|
def genQuizMultipleChoice(
|
|
2425
|
-
self, question, options, correct_ind, points=1, position=0
|
|
2499
|
+
self, question, options, correct_ind, points=1, position=0, fightml=None
|
|
2426
2500
|
):
|
|
2427
2501
|
""" "Generate a classic quiz-style multiple choice question dictionary
|
|
2428
2502
|
|
|
@@ -2437,6 +2511,8 @@ class cornellGrading:
|
|
|
2437
2511
|
Number of points for correct answer (defaults to 1).
|
|
2438
2512
|
position (int):
|
|
2439
2513
|
Position of question in quiz. Defaults to 0
|
|
2514
|
+
fightml (str, optional):
|
|
2515
|
+
HTML string from figure upload. Defaults to None.
|
|
2440
2516
|
|
|
2441
2517
|
Returns:
|
|
2442
2518
|
dict:
|
|
@@ -2454,9 +2530,13 @@ class cornellGrading:
|
|
|
2454
2530
|
}
|
|
2455
2531
|
)
|
|
2456
2532
|
|
|
2533
|
+
qtxt = f"<p>{convalllatex(question)}</p>"
|
|
2534
|
+
if fightml is not None:
|
|
2535
|
+
qtxt = f"{qtxt}\n<p>{fightml}</p>"
|
|
2536
|
+
|
|
2457
2537
|
q = {
|
|
2458
2538
|
"question_name": question,
|
|
2459
|
-
"question_text":
|
|
2539
|
+
"question_text": qtxt,
|
|
2460
2540
|
"question_type": "multiple_choice_question",
|
|
2461
2541
|
"position": 0,
|
|
2462
2542
|
"points_possible": points,
|
|
@@ -2465,7 +2545,7 @@ class cornellGrading:
|
|
|
2465
2545
|
|
|
2466
2546
|
return q
|
|
2467
2547
|
|
|
2468
|
-
def
|
|
2548
|
+
def genQuizFromPollEv(self, allqs, quiz, imagePath=None, imageFolder="QuizImages"):
|
|
2469
2549
|
"""Generate quiz items from a PollEv formatted CSV input file
|
|
2470
2550
|
|
|
2471
2551
|
Args:
|
|
@@ -2473,6 +2553,11 @@ class cornellGrading:
|
|
|
2473
2553
|
Table of questions and answers, formatted in PolEV CSV upload style
|
|
2474
2554
|
quiz (canvasapi.new_quiz.NewQuiz or canvasapi.quiz.Quiz):
|
|
2475
2555
|
Quiz object
|
|
2556
|
+
imagePath (str, optional):
|
|
2557
|
+
Full path to location on disk of any image files to use in questions.
|
|
2558
|
+
imageFolder (str):
|
|
2559
|
+
Name of Canvas folder to upload images to. Defaults to 'QuizImages'. If
|
|
2560
|
+
folder does not exist, it will be created as a hidden folder.
|
|
2476
2561
|
|
|
2477
2562
|
Returns:
|
|
2478
2563
|
None
|
|
@@ -2480,6 +2565,10 @@ class cornellGrading:
|
|
|
2480
2565
|
.. note::
|
|
2481
2566
|
Poll Everywhere upload format documentation is available here:
|
|
2482
2567
|
https://support.polleverywhere.com/hc/en-us/articles/1260801546530-Import-questions
|
|
2568
|
+
The format is expanded by adding a 'Figure' column. The contents of this
|
|
2569
|
+
column should be the filename (without extension) of a figure associated
|
|
2570
|
+
with the question. If any figures are present, input `imagePath` must be
|
|
2571
|
+
set. Images must be in png format with extension .png.
|
|
2483
2572
|
|
|
2484
2573
|
"""
|
|
2485
2574
|
|
|
@@ -2493,11 +2582,22 @@ class cornellGrading:
|
|
|
2493
2582
|
if col.startswith("Option"):
|
|
2494
2583
|
optcols.append(col)
|
|
2495
2584
|
|
|
2585
|
+
# check for any figures and make sure we have enough information to upload them
|
|
2586
|
+
if np.any(~allqs["Figure"].isna()):
|
|
2587
|
+
assert (
|
|
2588
|
+
imagePath is not None
|
|
2589
|
+
), "imagePath must be set if questions include figures."
|
|
2590
|
+
try:
|
|
2591
|
+
figFolder = self.getFolder(imageFolder)
|
|
2592
|
+
except AssertionError:
|
|
2593
|
+
figFolder = self.createFolder(imageFolder, hidden=True)
|
|
2594
|
+
|
|
2496
2595
|
# iterate through rows, creating the questions
|
|
2497
|
-
for
|
|
2596
|
+
for k, row in allqs.iterrows():
|
|
2597
|
+
# process question and responses
|
|
2498
2598
|
question = row.Title
|
|
2499
2599
|
opts = row[optcols].values
|
|
2500
|
-
opts = opts[~pandas.isna(opts)]
|
|
2600
|
+
opts = opts[~pandas.isna(opts)].astype(str)
|
|
2501
2601
|
correct_ind = [
|
|
2502
2602
|
j
|
|
2503
2603
|
for j, s in enumerate(opts)
|
|
@@ -2507,15 +2607,78 @@ class cornellGrading:
|
|
|
2507
2607
|
correct_ind = correct_ind[0]
|
|
2508
2608
|
opts[correct_ind] = opts[correct_ind].strip("***")
|
|
2509
2609
|
|
|
2610
|
+
# process figure (if any)
|
|
2611
|
+
if not (pandas.isna(row.Figure)):
|
|
2612
|
+
impath = os.path.join(imagePath, f"{row.Figure}.png")
|
|
2613
|
+
fightml = self.uploadFigure(impath, figFolder)
|
|
2614
|
+
else:
|
|
2615
|
+
fightml = None
|
|
2616
|
+
|
|
2510
2617
|
# create and add the question depending on quiz type
|
|
2511
2618
|
if isinstance(quiz, canvasapi.new_quiz.NewQuiz):
|
|
2512
2619
|
q = self.genNewQuizMultipleChoice(
|
|
2513
|
-
question,
|
|
2620
|
+
question,
|
|
2621
|
+
opts.astype(str),
|
|
2622
|
+
correct_ind,
|
|
2623
|
+
position=k + 1,
|
|
2624
|
+
fightml=fightml,
|
|
2514
2625
|
)
|
|
2515
2626
|
|
|
2516
2627
|
self.addNewQuizItem(quiz.id, q)
|
|
2517
2628
|
else:
|
|
2518
2629
|
q = self.genQuizMultipleChoice(
|
|
2519
|
-
question,
|
|
2630
|
+
question,
|
|
2631
|
+
opts.astype(str),
|
|
2632
|
+
correct_ind,
|
|
2633
|
+
position=k + 1,
|
|
2634
|
+
fightml=fightml,
|
|
2520
2635
|
)
|
|
2521
2636
|
quiz.create_question(question=q)
|
|
2637
|
+
|
|
2638
|
+
def uploadFigure(self, impath, figFolder):
|
|
2639
|
+
"""Upload a figure and generate an HTML string for embedding it. If filename
|
|
2640
|
+
already exists in the folder, use that rather than overwriting.
|
|
2641
|
+
|
|
2642
|
+
Args:
|
|
2643
|
+
impath (str):
|
|
2644
|
+
Full path of disk to figure file
|
|
2645
|
+
figFolder (canvasapi.folder.Folder):
|
|
2646
|
+
Canvas folder to upload to
|
|
2647
|
+
|
|
2648
|
+
Returns:
|
|
2649
|
+
str:
|
|
2650
|
+
HTML string representing the figure
|
|
2651
|
+
"""
|
|
2652
|
+
|
|
2653
|
+
filename = os.path.split(impath)[-1]
|
|
2654
|
+
haveFile = False
|
|
2655
|
+
for file in figFolder.get_files():
|
|
2656
|
+
if file.filename == filename:
|
|
2657
|
+
haveFile = True
|
|
2658
|
+
fig = {
|
|
2659
|
+
"id": file.id,
|
|
2660
|
+
"uuid": file.uuid,
|
|
2661
|
+
"display_name": file.display_name,
|
|
2662
|
+
}
|
|
2663
|
+
break
|
|
2664
|
+
|
|
2665
|
+
if not haveFile:
|
|
2666
|
+
assert os.path.exists(impath), f"Can not locate {impath}."
|
|
2667
|
+
status, fig = figFolder.upload(impath)
|
|
2668
|
+
assert status, f"Failed to upload {impath}."
|
|
2669
|
+
|
|
2670
|
+
figsrc = (
|
|
2671
|
+
f"{self.canvas._Canvas__requester.original_url}/courses/"
|
|
2672
|
+
f"{self.course.id}/files/{fig['id']}/preview?verifier={fig['uuid']}"
|
|
2673
|
+
)
|
|
2674
|
+
apisrc = (
|
|
2675
|
+
f"{self.canvas._Canvas__requester.base_url}courses/"
|
|
2676
|
+
f"{self.course.id}/files/{fig['id']}"
|
|
2677
|
+
)
|
|
2678
|
+
|
|
2679
|
+
fightml = (
|
|
2680
|
+
f'<img id="{fig["id"]}" src="{figsrc}" alt="{fig["display_name"]}" '
|
|
2681
|
+
f'width="600" data-api-endpoint="{apisrc}" data-api-returntype="File">'
|
|
2682
|
+
)
|
|
2683
|
+
|
|
2684
|
+
return fightml
|
|
@@ -690,6 +690,79 @@ class cornellQualtrics:
|
|
|
690
690
|
|
|
691
691
|
return response.json()["result"]
|
|
692
692
|
|
|
693
|
+
def exportUploadedFiles(self, surveyId, DataExportTags, saveDir=None):
|
|
694
|
+
"""Download all user uploaded files associated with specific questions from one
|
|
695
|
+
survey
|
|
696
|
+
|
|
697
|
+
Args:
|
|
698
|
+
surveyId (str):
|
|
699
|
+
Unique id string of survey. Get either from web interface or via
|
|
700
|
+
getSurveyId
|
|
701
|
+
DataExportTags (list):
|
|
702
|
+
Data Export Tags for all questions with uploaded files
|
|
703
|
+
saveDir (str, optional):
|
|
704
|
+
Full path to save location. If None (default) uses system tmp dir
|
|
705
|
+
|
|
706
|
+
Returns:
|
|
707
|
+
str:
|
|
708
|
+
Full path to directory where the survey results and all files are saved.
|
|
709
|
+
The survey results will be a CSV file with a filename that is the same
|
|
710
|
+
as the survey name, except with any colons replaced with underscores.
|
|
711
|
+
The files will be named as: ResponseId-FileId-fileName where ResponseId
|
|
712
|
+
and FileId match the entries in the survey results and fileName is the
|
|
713
|
+
original fileName of the upload.
|
|
714
|
+
|
|
715
|
+
Notes:
|
|
716
|
+
https://api.qualtrics.com/1071635f5a615-retrieve-a-user-uploaded-file
|
|
717
|
+
|
|
718
|
+
"""
|
|
719
|
+
|
|
720
|
+
# get survey name from ID
|
|
721
|
+
if surveyId not in self.surveyIds:
|
|
722
|
+
self.listSurveys()
|
|
723
|
+
assert surveyId in self.surveyIds, f"Survey ID {surveyId} not found."
|
|
724
|
+
|
|
725
|
+
surveyname = self.surveyNames[self.surveyIds == surveyId][0]
|
|
726
|
+
|
|
727
|
+
# synthesize base URL
|
|
728
|
+
baseUrl = (
|
|
729
|
+
f"https://{self.dataCenter}{self.qualtricsapi}surveys/{surveyId}/responses/"
|
|
730
|
+
)
|
|
731
|
+
|
|
732
|
+
# export survey results and read output
|
|
733
|
+
tmpdir = self.exportSurvey(surveyId, saveDir=saveDir)
|
|
734
|
+
if ":" in surveyname:
|
|
735
|
+
surveyname = surveyname.replace(":", "_")
|
|
736
|
+
surveyfile = os.path.join(tmpdir, surveyname + ".csv")
|
|
737
|
+
assert os.path.isfile(surveyfile), "Survey results not where expected."
|
|
738
|
+
surveyres = pandas.read_csv(surveyfile, header=[0, 1, 2])
|
|
739
|
+
|
|
740
|
+
# get all response IDs
|
|
741
|
+
responseIds = surveyres["ResponseId"].values.flatten()
|
|
742
|
+
|
|
743
|
+
# loop through each data export tag and download the associated file for each
|
|
744
|
+
# response
|
|
745
|
+
for DataExportTag in DataExportTags:
|
|
746
|
+
# get all ids and filenames for current tag
|
|
747
|
+
fids = surveyres[f"{DataExportTag}_Id"].values.flatten()
|
|
748
|
+
fnames = surveyres[f"{DataExportTag}_Name"].values.flatten()
|
|
749
|
+
|
|
750
|
+
# loop through everything
|
|
751
|
+
for rid, fid, fname in zip(responseIds, fids, fnames):
|
|
752
|
+
durl = f"{baseUrl}{rid}/uploaded-files/{fid}"
|
|
753
|
+
requestDownload = requests.request(
|
|
754
|
+
"GET", durl, headers=self.headers_post, stream=True
|
|
755
|
+
)
|
|
756
|
+
assert (
|
|
757
|
+
requestDownload.status_code == 200
|
|
758
|
+
), f"Download failed for file {fid} on response {rid}."
|
|
759
|
+
|
|
760
|
+
outname = os.path.join(tmpdir, f"{rid}-{fid}-{fname}")
|
|
761
|
+
with open(outname, "wb") as ff:
|
|
762
|
+
ff.write(requestDownload.content)
|
|
763
|
+
|
|
764
|
+
return tmpdir
|
|
765
|
+
|
|
693
766
|
def exportSurvey(self, surveyId, fileFormat="csv", useLabels="true", saveDir=None):
|
|
694
767
|
"""Download and extract survey results
|
|
695
768
|
|
|
@@ -701,7 +774,7 @@ class cornellQualtrics:
|
|
|
701
774
|
Format to download (must be csv, tsv, or spss)
|
|
702
775
|
useLabels (str):
|
|
703
776
|
Use choice labels ("true" or "false", defaults "true")
|
|
704
|
-
saveDir (str):
|
|
777
|
+
saveDir (str, optional):
|
|
705
778
|
Full path to save location. If None (default) uses system tmp dir
|
|
706
779
|
|
|
707
780
|
Returns:
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{cornellgrading-2.20.1 → cornellgrading-2.22.0}/cornellGrading.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|