polygon-api 1.1.0a2__tar.gz → 1.1.0a3__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.
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/PKG-INFO +1 -1
- polygon_api-1.1.0a3/polygon_api/__init__.py +30 -0
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/polygon_api/api.py +388 -128
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/polygon_api.egg-info/PKG-INFO +1 -1
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/setup.py +1 -1
- polygon_api-1.1.0a2/polygon_api/__init__.py +0 -16
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/LICENSE +0 -0
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/README.md +0 -0
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/polygon_api.egg-info/SOURCES.txt +0 -0
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/polygon_api.egg-info/dependency_links.txt +0 -0
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/polygon_api.egg-info/requires.txt +0 -0
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/polygon_api.egg-info/top_level.txt +0 -0
- {polygon_api-1.1.0a2 → polygon_api-1.1.0a3}/setup.cfg +0 -0
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
from .api import (
|
|
2
|
+
Polygon,
|
|
3
|
+
Problem,
|
|
4
|
+
ProblemInfo,
|
|
5
|
+
Test,
|
|
6
|
+
ManualTest,
|
|
7
|
+
GeneratedTest,
|
|
8
|
+
TestGroup,
|
|
9
|
+
Statement,
|
|
10
|
+
Package,
|
|
11
|
+
Solution,
|
|
12
|
+
File,
|
|
13
|
+
ResourceAdvancedProperties,
|
|
14
|
+
ValidatorTest,
|
|
15
|
+
CheckerTest,
|
|
16
|
+
PolygonRequestFailedException,
|
|
17
|
+
HTTPRequestFailedException,
|
|
18
|
+
PointsPolicy,
|
|
19
|
+
FeedbackPolicy,
|
|
20
|
+
FileType,
|
|
21
|
+
SolutionTag,
|
|
22
|
+
Stage,
|
|
23
|
+
Asset,
|
|
24
|
+
PackageState,
|
|
25
|
+
PackageType,
|
|
26
|
+
ValidatorTestVerdict,
|
|
27
|
+
CheckerTestVerdict
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
__version__ = "1.1.0"
|
|
@@ -4,9 +4,25 @@ import random
|
|
|
4
4
|
import requests
|
|
5
5
|
import string
|
|
6
6
|
import time
|
|
7
|
+
from collections.abc import Iterable
|
|
7
8
|
from enum import Enum
|
|
8
9
|
|
|
9
10
|
|
|
11
|
+
def _comma_separated(value):
|
|
12
|
+
"""
|
|
13
|
+
Formats a value for an API parameter accepting a comma-separated list.
|
|
14
|
+
|
|
15
|
+
A string is passed through unchanged, any other iterable is joined with
|
|
16
|
+
commas, and anything else is stringified. None is returned as is, so that
|
|
17
|
+
Request omits the parameter altogether.
|
|
18
|
+
"""
|
|
19
|
+
if value is None or isinstance(value, str):
|
|
20
|
+
return value
|
|
21
|
+
if isinstance(value, Iterable):
|
|
22
|
+
return ",".join(map(str, value))
|
|
23
|
+
return str(value)
|
|
24
|
+
|
|
25
|
+
|
|
10
26
|
class Polygon:
|
|
11
27
|
"""
|
|
12
28
|
"""
|
|
@@ -26,7 +42,12 @@ class Polygon:
|
|
|
26
42
|
_PROBLEM_CREATE = 'problem.create'
|
|
27
43
|
_PROBLEM_CHECKER = 'problem.checker'
|
|
28
44
|
_PROBLEM_VALIDATOR = 'problem.validator'
|
|
45
|
+
_PROBLEM_EXTRA_VALIDATORS = 'problem.extraValidators'
|
|
29
46
|
_PROBLEM_INTERACTOR = 'problem.interactor'
|
|
47
|
+
_PROBLEM_VALIDATOR_TESTS = 'problem.validatorTests'
|
|
48
|
+
_PROBLEM_SAVE_VALIDATOR_TEST = 'problem.saveValidatorTest'
|
|
49
|
+
_PROBLEM_CHECKER_TESTS = 'problem.checkerTests'
|
|
50
|
+
_PROBLEM_SAVE_CHECKER_TEST = 'problem.saveCheckerTest'
|
|
30
51
|
_PROBLEM_FILES = 'problem.files'
|
|
31
52
|
_PROBLEM_SOLUTIONS = 'problem.solutions'
|
|
32
53
|
_PROBLEM_VIEW_FILE = 'problem.viewFile'
|
|
@@ -43,9 +64,9 @@ class Polygon:
|
|
|
43
64
|
_PROBLEM_EDIT_SOLUTION_EXTRA_TAGS = 'problem.editSolutionExtraTags'
|
|
44
65
|
_PROBLEM_SAVE_SCRIPT = 'problem.saveScript'
|
|
45
66
|
_PROBLEM_SAVE_TEST = 'problem.saveTest'
|
|
67
|
+
_PROBLEM_SET_TEST_GROUP = 'problem.setTestGroup'
|
|
46
68
|
_PROBLEM_ENABLE_GROUPS = 'problem.enableGroups'
|
|
47
69
|
_PROBLEM_ENABLE_POINTS = 'problem.enablePoints'
|
|
48
|
-
_PROBLEM_SET_TEST_GROUP = 'problem.setTestGroup'
|
|
49
70
|
_PROBLEM_VIEW_TEST_GROUP = 'problem.viewTestGroup'
|
|
50
71
|
_PROBLEM_SAVE_TEST_GROUP = 'problem.saveTestGroup'
|
|
51
72
|
_PROBLEM_VIEW_TAGS = 'problem.viewTags'
|
|
@@ -54,9 +75,9 @@ class Polygon:
|
|
|
54
75
|
_PROBLEM_SAVE_GENERAL_DESCRIPTION = 'problem.saveGeneralDescription'
|
|
55
76
|
_PROBLEM_VIEW_GENERAL_TUTORIAL = 'problem.viewGeneralTutorial'
|
|
56
77
|
_PROBLEM_SAVE_GENERAL_TUTORIAL = 'problem.saveGeneralTutorial'
|
|
57
|
-
_PROBLEM_BUILD_PACKAGE = 'problem.buildPackage'
|
|
58
78
|
_PROBLEM_PACKAGES = 'problem.packages'
|
|
59
79
|
_PROBLEM_PACKAGE = 'problem.package'
|
|
80
|
+
_PROBLEM_BUILD_PACKAGE = 'problem.buildPackage'
|
|
60
81
|
|
|
61
82
|
def __init__(self, api_url, api_key, api_secret):
|
|
62
83
|
self.request_config = RequestConfig(api_url, api_key, api_secret)
|
|
@@ -287,44 +308,6 @@ class Polygon:
|
|
|
287
308
|
)
|
|
288
309
|
return response.result
|
|
289
310
|
|
|
290
|
-
def problem_set_test_group(self, problem_id, testset, test_group, test_index=None, test_indices=None):
|
|
291
|
-
"""
|
|
292
|
-
"""
|
|
293
|
-
if isinstance(test_indices, list):
|
|
294
|
-
test_indices = ",".join(map(str, test_indices))
|
|
295
|
-
response = self._request_ok_or_raise(
|
|
296
|
-
self._PROBLEM_SET_TEST_GROUP,
|
|
297
|
-
args={
|
|
298
|
-
'problemId': problem_id,
|
|
299
|
-
'testset': testset,
|
|
300
|
-
'testGroup': test_group,
|
|
301
|
-
'testIndex': test_index,
|
|
302
|
-
'testIndices': test_indices,
|
|
303
|
-
},
|
|
304
|
-
)
|
|
305
|
-
return response.result
|
|
306
|
-
|
|
307
|
-
def problem_script(self, problem_id, testset):
|
|
308
|
-
response = self._request_ok_or_raise(
|
|
309
|
-
self._PROBLEM_SCRIPT,
|
|
310
|
-
args={
|
|
311
|
-
'problemId': problem_id,
|
|
312
|
-
'testset': testset,
|
|
313
|
-
},
|
|
314
|
-
)
|
|
315
|
-
return response.result
|
|
316
|
-
|
|
317
|
-
def problem_save_script(self, problem_id, testset, source):
|
|
318
|
-
response = self._request_ok_or_raise(
|
|
319
|
-
self._PROBLEM_SAVE_SCRIPT,
|
|
320
|
-
args={
|
|
321
|
-
'problemId': problem_id,
|
|
322
|
-
'testset': testset,
|
|
323
|
-
'source': source,
|
|
324
|
-
}
|
|
325
|
-
)
|
|
326
|
-
return response.result
|
|
327
|
-
|
|
328
311
|
def problem_save_test(self, problem_id, testset, test_index, test_input, test_group=None, test_points=None,
|
|
329
312
|
test_description=None, test_use_in_statements=None, test_input_for_statements=None,
|
|
330
313
|
test_output_for_statements=None, verify_input_output_for_statements=None,
|
|
@@ -350,6 +333,26 @@ class Polygon:
|
|
|
350
333
|
)
|
|
351
334
|
return response.result
|
|
352
335
|
|
|
336
|
+
def problem_set_test_group(self, problem_id, testset, test_group, test_index=None, test_indices=None):
|
|
337
|
+
if test_index is None and test_indices is None:
|
|
338
|
+
raise ValueError("Either test_index or test_indices must be specified")
|
|
339
|
+
if test_index is not None and test_indices is not None:
|
|
340
|
+
raise ValueError("Only one of test_index or test_indices must be specified")
|
|
341
|
+
|
|
342
|
+
test_indices = _comma_separated(test_indices)
|
|
343
|
+
|
|
344
|
+
response = self._request_ok_or_raise(
|
|
345
|
+
self._PROBLEM_SET_TEST_GROUP,
|
|
346
|
+
args={
|
|
347
|
+
'problemId': problem_id,
|
|
348
|
+
'testset': testset,
|
|
349
|
+
'testGroup': test_group,
|
|
350
|
+
'testIndex': test_index,
|
|
351
|
+
'testIndices': test_indices,
|
|
352
|
+
}
|
|
353
|
+
)
|
|
354
|
+
return response.result
|
|
355
|
+
|
|
353
356
|
def problem_solutions(self, problem_id):
|
|
354
357
|
response = self._request_ok_or_raise(
|
|
355
358
|
self._PROBLEM_SOLUTIONS,
|
|
@@ -379,34 +382,52 @@ class Polygon:
|
|
|
379
382
|
)
|
|
380
383
|
return [Test.from_json(self, problem_id, testset, js) for js in response.result]
|
|
381
384
|
|
|
382
|
-
def
|
|
383
|
-
|
|
385
|
+
def problem_script(self, problem_id, testset):
|
|
386
|
+
"""
|
|
387
|
+
Returns test generation script
|
|
388
|
+
"""
|
|
389
|
+
response = self._request_text(
|
|
390
|
+
self._PROBLEM_SCRIPT,
|
|
391
|
+
args={
|
|
392
|
+
'problemId': problem_id,
|
|
393
|
+
'testset': testset,
|
|
394
|
+
}
|
|
395
|
+
)
|
|
396
|
+
return response
|
|
397
|
+
|
|
398
|
+
def problem_test_input(self, problem_id, testset, test_index, binary=False):
|
|
399
|
+
"""
|
|
400
|
+
Returns generated test input, as bytes if binary is true
|
|
401
|
+
"""
|
|
402
|
+
response = self._request_body(
|
|
384
403
|
self._PROBLEM_TEST_INPUT,
|
|
385
404
|
args={
|
|
386
405
|
'problemId': problem_id,
|
|
387
406
|
'testset': testset,
|
|
388
407
|
'testIndex': test_index,
|
|
389
|
-
}
|
|
408
|
+
},
|
|
409
|
+
binary=binary
|
|
390
410
|
)
|
|
391
411
|
return response
|
|
392
412
|
|
|
393
|
-
def problem_test_answer(self, problem_id, testset, test_index):
|
|
394
|
-
|
|
413
|
+
def problem_test_answer(self, problem_id, testset, test_index, binary=False):
|
|
414
|
+
"""
|
|
415
|
+
Returns generated test answer, as bytes if binary is true
|
|
416
|
+
"""
|
|
417
|
+
response = self._request_body(
|
|
395
418
|
self._PROBLEM_TEST_ANSWER,
|
|
396
419
|
args={
|
|
397
420
|
'problemId': problem_id,
|
|
398
421
|
'testset': testset,
|
|
399
422
|
'testIndex': test_index,
|
|
400
|
-
}
|
|
423
|
+
},
|
|
424
|
+
binary=binary
|
|
401
425
|
)
|
|
402
426
|
return response
|
|
403
427
|
|
|
404
428
|
def problem_save_test_group(self, problem_id, testset, group, points_policy=None, feedback_policy=None,
|
|
405
429
|
dependencies=None):
|
|
406
|
-
|
|
407
|
-
dependencies = ",".join(map(str, dependencies))
|
|
408
|
-
elif dependencies is not None:
|
|
409
|
-
dependencies = str(dependencies)
|
|
430
|
+
dependencies = _comma_separated(dependencies)
|
|
410
431
|
if points_policy is not None and not isinstance(points_policy, PointsPolicy):
|
|
411
432
|
raise ValueError(
|
|
412
433
|
"Expected PointsPolicy instance for points_policy argument, but %s found" % type(points_policy))
|
|
@@ -426,34 +447,37 @@ class Polygon:
|
|
|
426
447
|
)
|
|
427
448
|
return response.result
|
|
428
449
|
|
|
429
|
-
def problem_view_test_group(self, testset, group):
|
|
450
|
+
def problem_view_test_group(self, problem_id, testset, group=None):
|
|
430
451
|
response = self._request_ok_or_raise(
|
|
431
452
|
self._PROBLEM_VIEW_TEST_GROUP,
|
|
432
453
|
args={
|
|
454
|
+
'problemId': problem_id,
|
|
433
455
|
'testset': testset,
|
|
434
456
|
'group': group,
|
|
435
457
|
},
|
|
436
458
|
)
|
|
437
|
-
return TestGroup.from_json(response.result
|
|
459
|
+
return [TestGroup.from_json(js) for js in response.result]
|
|
438
460
|
|
|
439
|
-
def problem_view_file(self, problem_id, type, name):
|
|
440
|
-
response = self.
|
|
461
|
+
def problem_view_file(self, problem_id, type, name, binary=False):
|
|
462
|
+
response = self._request_body(
|
|
441
463
|
self._PROBLEM_VIEW_FILE,
|
|
442
464
|
args={
|
|
443
465
|
'problemId': problem_id,
|
|
444
466
|
'type': type,
|
|
445
467
|
'name': name
|
|
446
|
-
}
|
|
468
|
+
},
|
|
469
|
+
binary=binary
|
|
447
470
|
)
|
|
448
471
|
return response
|
|
449
472
|
|
|
450
|
-
def problem_view_solution(self, problem_id, name):
|
|
451
|
-
response = self.
|
|
473
|
+
def problem_view_solution(self, problem_id, name, binary=False):
|
|
474
|
+
response = self._request_body(
|
|
452
475
|
self._PROBLEM_VIEW_SOLUTION,
|
|
453
476
|
args={
|
|
454
477
|
'problemId': problem_id,
|
|
455
478
|
'name': name
|
|
456
|
-
}
|
|
479
|
+
},
|
|
480
|
+
binary=binary
|
|
457
481
|
)
|
|
458
482
|
return response
|
|
459
483
|
|
|
@@ -479,7 +503,7 @@ class Polygon:
|
|
|
479
503
|
)
|
|
480
504
|
return response.result
|
|
481
505
|
|
|
482
|
-
def problem_save_solution(self, problem_id, name, file,
|
|
506
|
+
def problem_save_solution(self, problem_id, name, file, tag, source_type=None, check_existing=None):
|
|
483
507
|
response = self._request_ok_or_raise(
|
|
484
508
|
self._PROBLEM_SAVE_SOLUTION,
|
|
485
509
|
args={
|
|
@@ -493,6 +517,39 @@ class Polygon:
|
|
|
493
517
|
)
|
|
494
518
|
return response.result
|
|
495
519
|
|
|
520
|
+
def problem_save_script(self, problem_id, testset, source):
|
|
521
|
+
"""
|
|
522
|
+
Edit test generation script
|
|
523
|
+
"""
|
|
524
|
+
response = self._request_ok_or_raise(
|
|
525
|
+
self._PROBLEM_SAVE_SCRIPT,
|
|
526
|
+
args={
|
|
527
|
+
'problemId': problem_id,
|
|
528
|
+
'testset': testset,
|
|
529
|
+
'source': source,
|
|
530
|
+
}
|
|
531
|
+
)
|
|
532
|
+
return response.result
|
|
533
|
+
|
|
534
|
+
def problem_edit_solution_extra_tags(self, problem_id, remove, name, testset=None, test_group=None, tag=None):
|
|
535
|
+
if (testset is None) == (test_group is None):
|
|
536
|
+
raise ValueError("Exactly one of testset or test_group must be specified")
|
|
537
|
+
if tag is not None and not isinstance(tag, SolutionTag):
|
|
538
|
+
raise ValueError(
|
|
539
|
+
"Expected SolutionTag instance for tag argument, but %s found" % type(tag))
|
|
540
|
+
response = self._request_ok_or_raise(
|
|
541
|
+
self._PROBLEM_EDIT_SOLUTION_EXTRA_TAGS,
|
|
542
|
+
args={
|
|
543
|
+
'problemId': problem_id,
|
|
544
|
+
'remove': remove,
|
|
545
|
+
'name': name,
|
|
546
|
+
'testset': testset,
|
|
547
|
+
'testGroup': test_group,
|
|
548
|
+
'tag': tag,
|
|
549
|
+
}
|
|
550
|
+
)
|
|
551
|
+
return response.result
|
|
552
|
+
|
|
496
553
|
def problem_checker(self, problem_id):
|
|
497
554
|
response = self._request_ok_or_raise(
|
|
498
555
|
self._PROBLEM_CHECKER,
|
|
@@ -512,6 +569,34 @@ class Polygon:
|
|
|
512
569
|
)
|
|
513
570
|
return response.result
|
|
514
571
|
|
|
572
|
+
def problem_checker_tests(self, problem_id):
|
|
573
|
+
response = self._request_ok_or_raise(
|
|
574
|
+
self._PROBLEM_CHECKER_TESTS,
|
|
575
|
+
args={
|
|
576
|
+
'problemId': problem_id,
|
|
577
|
+
},
|
|
578
|
+
)
|
|
579
|
+
return [CheckerTest.from_json(js) for js in response.result]
|
|
580
|
+
|
|
581
|
+
def problem_save_checker_test(self, problem_id, test_index, test_input=None, test_output=None,
|
|
582
|
+
test_answer=None, test_verdict=None, check_existing=None):
|
|
583
|
+
if test_verdict is not None and not isinstance(test_verdict, CheckerTestVerdict):
|
|
584
|
+
raise ValueError(
|
|
585
|
+
"Expected CheckerTestVerdict instance for test_verdict argument, but %s found" % type(test_verdict))
|
|
586
|
+
response = self._request_ok_or_raise(
|
|
587
|
+
self._PROBLEM_SAVE_CHECKER_TEST,
|
|
588
|
+
args={
|
|
589
|
+
'problemId': problem_id,
|
|
590
|
+
'testIndex': test_index,
|
|
591
|
+
'testInput': test_input,
|
|
592
|
+
'testOutput': test_output,
|
|
593
|
+
'testAnswer': test_answer,
|
|
594
|
+
'testVerdict': test_verdict,
|
|
595
|
+
'checkExisting': check_existing,
|
|
596
|
+
},
|
|
597
|
+
)
|
|
598
|
+
return response.result
|
|
599
|
+
|
|
515
600
|
def problem_validator(self, problem_id):
|
|
516
601
|
response = self._request_ok_or_raise(
|
|
517
602
|
self._PROBLEM_VALIDATOR,
|
|
@@ -531,6 +616,43 @@ class Polygon:
|
|
|
531
616
|
)
|
|
532
617
|
return response.result
|
|
533
618
|
|
|
619
|
+
def problem_extra_validators(self, problem_id):
|
|
620
|
+
response = self._request_ok_or_raise(
|
|
621
|
+
self._PROBLEM_EXTRA_VALIDATORS,
|
|
622
|
+
args={
|
|
623
|
+
'problemId': problem_id,
|
|
624
|
+
},
|
|
625
|
+
)
|
|
626
|
+
return response.result
|
|
627
|
+
|
|
628
|
+
def problem_validator_tests(self, problem_id):
|
|
629
|
+
response = self._request_ok_or_raise(
|
|
630
|
+
self._PROBLEM_VALIDATOR_TESTS,
|
|
631
|
+
args={
|
|
632
|
+
'problemId': problem_id,
|
|
633
|
+
},
|
|
634
|
+
)
|
|
635
|
+
return [ValidatorTest.from_json(js) for js in response.result]
|
|
636
|
+
|
|
637
|
+
def problem_save_validator_test(self, problem_id, test_index, test_input=None, test_verdict=None,
|
|
638
|
+
test_group=None, testset=None, check_existing=None):
|
|
639
|
+
if test_verdict is not None and not isinstance(test_verdict, ValidatorTestVerdict):
|
|
640
|
+
raise ValueError(
|
|
641
|
+
"Expected ValidatorTestVerdict instance for test_verdict argument, but %s found" % type(test_verdict))
|
|
642
|
+
response = self._request_ok_or_raise(
|
|
643
|
+
self._PROBLEM_SAVE_VALIDATOR_TEST,
|
|
644
|
+
args={
|
|
645
|
+
'problemId': problem_id,
|
|
646
|
+
'testIndex': test_index,
|
|
647
|
+
'testInput': test_input,
|
|
648
|
+
'testVerdict': test_verdict,
|
|
649
|
+
'testGroup': test_group,
|
|
650
|
+
'testset': testset,
|
|
651
|
+
'checkExisting': check_existing,
|
|
652
|
+
},
|
|
653
|
+
)
|
|
654
|
+
return response.result
|
|
655
|
+
|
|
534
656
|
def problem_interactor(self, problem_id):
|
|
535
657
|
response = self._request_ok_or_raise(
|
|
536
658
|
self._PROBLEM_INTERACTOR,
|
|
@@ -551,13 +673,14 @@ class Polygon:
|
|
|
551
673
|
return response.result
|
|
552
674
|
|
|
553
675
|
def problem_packages(self, problem_id):
|
|
676
|
+
"""
|
|
677
|
+
Returns list of packages
|
|
678
|
+
"""
|
|
554
679
|
response = self._request_ok_or_raise(
|
|
555
680
|
self._PROBLEM_PACKAGES,
|
|
556
|
-
args={
|
|
557
|
-
'problemId': problem_id,
|
|
558
|
-
},
|
|
681
|
+
args={'problemId': problem_id},
|
|
559
682
|
)
|
|
560
|
-
return [Package.from_json(
|
|
683
|
+
return [Package.from_json(js) for js in response.result]
|
|
561
684
|
|
|
562
685
|
def problem_package(self, problem_id, package_id, type=None):
|
|
563
686
|
return self._request_raw(
|
|
@@ -569,14 +692,17 @@ class Polygon:
|
|
|
569
692
|
},
|
|
570
693
|
)
|
|
571
694
|
|
|
572
|
-
def problem_build_package(self, problem_id,
|
|
695
|
+
def problem_build_package(self, problem_id, verify, full):
|
|
696
|
+
"""
|
|
697
|
+
Start building a package
|
|
698
|
+
"""
|
|
573
699
|
response = self._request_ok_or_raise(
|
|
574
700
|
self._PROBLEM_BUILD_PACKAGE,
|
|
575
701
|
args={
|
|
576
702
|
'problemId': problem_id,
|
|
577
|
-
'full': full,
|
|
578
703
|
'verify': verify,
|
|
579
|
-
|
|
704
|
+
'full': full,
|
|
705
|
+
}
|
|
580
706
|
)
|
|
581
707
|
return response.result
|
|
582
708
|
|
|
@@ -602,10 +728,19 @@ class Polygon:
|
|
|
602
728
|
request = Request(self.request_config, method_name, args)
|
|
603
729
|
return request.issue()
|
|
604
730
|
|
|
731
|
+
def _request_text(self, method_name, args=None):
|
|
732
|
+
request = Request(self.request_config, method_name, args)
|
|
733
|
+
return request.issue_text()
|
|
734
|
+
|
|
605
735
|
def _request_raw(self, method_name, args=None):
|
|
606
736
|
request = Request(self.request_config, method_name, args)
|
|
607
737
|
return request.issue_raw()
|
|
608
738
|
|
|
739
|
+
def _request_body(self, method_name, args=None, binary=False):
|
|
740
|
+
if binary:
|
|
741
|
+
return self._request_raw(method_name, args)
|
|
742
|
+
return self._request_text(method_name, args)
|
|
743
|
+
|
|
609
744
|
|
|
610
745
|
class Problem:
|
|
611
746
|
"""
|
|
@@ -706,15 +841,6 @@ class Problem:
|
|
|
706
841
|
def enable_points(self, enable):
|
|
707
842
|
return self._polygon.problem_enable_points(self.id, enable)
|
|
708
843
|
|
|
709
|
-
def set_test_group(self, testset, test_group, test_index=None, test_indices=None):
|
|
710
|
-
return self._polygon.problem_set_test_group(self.id, testset, test_group, test_index, test_indices)
|
|
711
|
-
|
|
712
|
-
def script(self, testset):
|
|
713
|
-
return self._polygon.problem_script(self.id, testset)
|
|
714
|
-
|
|
715
|
-
def save_script(self, testset, source):
|
|
716
|
-
return self._polygon.problem_save_script(self.id, testset, source)
|
|
717
|
-
|
|
718
844
|
def save_test(self, testset, test_index, test_input, test_group=None, test_points=None, test_description=None,
|
|
719
845
|
test_use_in_statements=None, test_input_for_statements=None, test_output_for_statements=None,
|
|
720
846
|
verify_input_output_for_statements=None, check_existing=None):
|
|
@@ -723,34 +849,34 @@ class Problem:
|
|
|
723
849
|
test_output_for_statements, verify_input_output_for_statements,
|
|
724
850
|
check_existing)
|
|
725
851
|
|
|
852
|
+
def set_test_group(self, testset, test_group, test_index=None, test_indices=None):
|
|
853
|
+
return self._polygon.problem_set_test_group(self.id, testset, test_group, test_index, test_indices)
|
|
854
|
+
|
|
726
855
|
def tests(self, testset, no_inputs=None):
|
|
727
856
|
return self._polygon.problem_tests(self.id, testset, no_inputs)
|
|
728
857
|
|
|
729
|
-
def test_input(self, testset, test_index):
|
|
730
|
-
return self._polygon.problem_test_input(self.id, testset, test_index)
|
|
731
|
-
|
|
732
|
-
def test_answer(self, testset, test_index):
|
|
733
|
-
return self._polygon.problem_test_answer(self.id, testset, test_index)
|
|
734
|
-
|
|
735
858
|
def save_test_group(self, testset, group, points_policy=None, feedback_policy=None, dependencies=None):
|
|
736
859
|
return self._polygon.problem_save_test_group(self.id, testset, group,
|
|
737
860
|
points_policy, feedback_policy, dependencies)
|
|
738
861
|
|
|
739
|
-
def view_test_group(self, testset, group):
|
|
740
|
-
return self._polygon.problem_view_test_group(testset, group)
|
|
862
|
+
def view_test_group(self, testset, group=None):
|
|
863
|
+
return self._polygon.problem_view_test_group(self.id, testset, group)
|
|
741
864
|
|
|
742
|
-
def view_file(self, type, name):
|
|
743
|
-
return self._polygon.problem_view_file(self.id, type, name)
|
|
865
|
+
def view_file(self, type, name, binary=False):
|
|
866
|
+
return self._polygon.problem_view_file(self.id, type, name, binary)
|
|
744
867
|
|
|
745
|
-
def view_solution(self, name):
|
|
746
|
-
return self._polygon.problem_view_solution(self.id, name)
|
|
868
|
+
def view_solution(self, name, binary=False):
|
|
869
|
+
return self._polygon.problem_view_solution(self.id, name, binary)
|
|
747
870
|
|
|
748
871
|
def save_file(self, type, name, file, source_type=None, resource_advanced_properties=None, check_existing=None):
|
|
749
872
|
return self._polygon.problem_save_file(self.id, type, name, file, source_type,
|
|
750
873
|
resource_advanced_properties, check_existing)
|
|
751
874
|
|
|
752
|
-
def save_solution(self, name, file,
|
|
753
|
-
return self._polygon.problem_save_solution(self.id, name, file,
|
|
875
|
+
def save_solution(self, name, file, tag, source_type=None, check_existing=None):
|
|
876
|
+
return self._polygon.problem_save_solution(self.id, name, file, tag, source_type, check_existing)
|
|
877
|
+
|
|
878
|
+
def edit_solution_extra_tags(self, remove, name, testset=None, test_group=None, tag=None):
|
|
879
|
+
return self._polygon.problem_edit_solution_extra_tags(self.id, remove, name, testset, test_group, tag)
|
|
754
880
|
|
|
755
881
|
def checker(self):
|
|
756
882
|
return self._polygon.problem_checker(self.id)
|
|
@@ -758,12 +884,31 @@ class Problem:
|
|
|
758
884
|
def set_checker(self, checker):
|
|
759
885
|
return self._polygon.problem_set_checker(self.id, checker)
|
|
760
886
|
|
|
887
|
+
def checker_tests(self):
|
|
888
|
+
return self._polygon.problem_checker_tests(self.id)
|
|
889
|
+
|
|
890
|
+
def save_checker_test(self, test_index, test_input=None, test_output=None,
|
|
891
|
+
test_answer=None, test_verdict=None, check_existing=None):
|
|
892
|
+
return self._polygon.problem_save_checker_test(self.id, test_index, test_input, test_output,
|
|
893
|
+
test_answer, test_verdict, check_existing)
|
|
894
|
+
|
|
761
895
|
def validator(self):
|
|
762
896
|
return self._polygon.problem_validator(self.id)
|
|
763
897
|
|
|
764
898
|
def set_validator(self, validator):
|
|
765
899
|
return self._polygon.problem_set_validator(self.id, validator)
|
|
766
900
|
|
|
901
|
+
def validator_tests(self):
|
|
902
|
+
return self._polygon.problem_validator_tests(self.id)
|
|
903
|
+
|
|
904
|
+
def save_validator_test(self, test_index, test_input=None, test_verdict=None,
|
|
905
|
+
test_group=None, testset=None, check_existing=None):
|
|
906
|
+
return self._polygon.problem_save_validator_test(self.id, test_index, test_input, test_verdict,
|
|
907
|
+
test_group, testset, check_existing)
|
|
908
|
+
|
|
909
|
+
def extra_validators(self):
|
|
910
|
+
return self._polygon.problem_extra_validators(self.id)
|
|
911
|
+
|
|
767
912
|
def interactor(self):
|
|
768
913
|
return self._polygon.problem_interactor(self.id)
|
|
769
914
|
|
|
@@ -785,14 +930,26 @@ class Problem:
|
|
|
785
930
|
def files_aux(self):
|
|
786
931
|
return self.files()[FileType.AUX]
|
|
787
932
|
|
|
933
|
+
def script(self, testset):
|
|
934
|
+
return self._polygon.problem_script(self.id, testset)
|
|
935
|
+
|
|
936
|
+
def test_input(self, testset, test_index, binary=False):
|
|
937
|
+
return self._polygon.problem_test_input(self.id, testset, test_index, binary)
|
|
938
|
+
|
|
939
|
+
def test_answer(self, testset, test_index, binary=False):
|
|
940
|
+
return self._polygon.problem_test_answer(self.id, testset, test_index, binary)
|
|
941
|
+
|
|
942
|
+
def save_script(self, testset, source):
|
|
943
|
+
return self._polygon.problem_save_script(self.id, testset, source)
|
|
944
|
+
|
|
788
945
|
def packages(self):
|
|
789
946
|
return self._polygon.problem_packages(self.id)
|
|
790
947
|
|
|
791
|
-
def package(self,
|
|
792
|
-
return self._polygon.problem_package(self.id,
|
|
948
|
+
def package(self, package_id, type=None):
|
|
949
|
+
return self._polygon.problem_package(self.id, package_id, type)
|
|
793
950
|
|
|
794
|
-
def build_package(self,
|
|
795
|
-
return self._polygon.problem_build_package(self.id,
|
|
951
|
+
def build_package(self, verify, full):
|
|
952
|
+
return self._polygon.problem_build_package(self.id, verify, full)
|
|
796
953
|
|
|
797
954
|
|
|
798
955
|
class ProblemInfo:
|
|
@@ -991,6 +1148,37 @@ class Statement:
|
|
|
991
1148
|
self.tutorial = tutorial
|
|
992
1149
|
|
|
993
1150
|
|
|
1151
|
+
class Package:
|
|
1152
|
+
"""
|
|
1153
|
+
Object: representing Polygon package
|
|
1154
|
+
"""
|
|
1155
|
+
_ID = "id"
|
|
1156
|
+
_REVISION = "revision"
|
|
1157
|
+
_CREATION_TIME_SECONDS = "creationTimeSeconds"
|
|
1158
|
+
_STATE = "state"
|
|
1159
|
+
_COMMENT = "comment"
|
|
1160
|
+
_TYPE = "type"
|
|
1161
|
+
|
|
1162
|
+
@classmethod
|
|
1163
|
+
def from_json(cls, package_json):
|
|
1164
|
+
return cls(
|
|
1165
|
+
id=package_json[Package._ID],
|
|
1166
|
+
revision=package_json[Package._REVISION],
|
|
1167
|
+
creation_time_seconds=package_json[Package._CREATION_TIME_SECONDS],
|
|
1168
|
+
state=PackageState[package_json[Package._STATE]],
|
|
1169
|
+
comment=package_json[Package._COMMENT],
|
|
1170
|
+
type=PackageType[package_json[Package._TYPE].upper()]
|
|
1171
|
+
)
|
|
1172
|
+
|
|
1173
|
+
def __init__(self, id, revision, creation_time_seconds, state, comment, type):
|
|
1174
|
+
self.id = id
|
|
1175
|
+
self.revision = revision
|
|
1176
|
+
self.creation_time_seconds = creation_time_seconds
|
|
1177
|
+
self.state = state
|
|
1178
|
+
self.comment = comment
|
|
1179
|
+
self.type = type
|
|
1180
|
+
|
|
1181
|
+
|
|
994
1182
|
class Solution:
|
|
995
1183
|
"""
|
|
996
1184
|
Object: representing Polygon problem solution
|
|
@@ -1048,37 +1236,6 @@ class File:
|
|
|
1048
1236
|
self.resource_advanced_properties = resource_advanced_properties
|
|
1049
1237
|
|
|
1050
1238
|
|
|
1051
|
-
class Package:
|
|
1052
|
-
"""
|
|
1053
|
-
Object: representing Polygon package
|
|
1054
|
-
"""
|
|
1055
|
-
_ID = "id"
|
|
1056
|
-
_REVISION = "revision"
|
|
1057
|
-
_CREATION_TIME_SECONDS = "creationTimeSeconds"
|
|
1058
|
-
_STATE = "state"
|
|
1059
|
-
_COMMENT = "comment"
|
|
1060
|
-
_TYPE = "type"
|
|
1061
|
-
|
|
1062
|
-
@classmethod
|
|
1063
|
-
def from_json(cls, file_json):
|
|
1064
|
-
return cls(
|
|
1065
|
-
id=file_json[Package._ID],
|
|
1066
|
-
revision=file_json[Package._REVISION],
|
|
1067
|
-
creation_time_seconds=file_json[Package._CREATION_TIME_SECONDS],
|
|
1068
|
-
state=file_json[Package._STATE],
|
|
1069
|
-
comment=file_json[Package._COMMENT],
|
|
1070
|
-
type=file_json.get(Package._TYPE, None)
|
|
1071
|
-
)
|
|
1072
|
-
|
|
1073
|
-
def __init__(self, id, revision, creation_time_seconds, state, comment, type):
|
|
1074
|
-
self.id = id
|
|
1075
|
-
self.revision = revision
|
|
1076
|
-
self.creation_time_seconds = creation_time_seconds
|
|
1077
|
-
self.state = state
|
|
1078
|
-
self.comment = comment
|
|
1079
|
-
self.type = type
|
|
1080
|
-
|
|
1081
|
-
|
|
1082
1239
|
class ResourceAdvancedProperties:
|
|
1083
1240
|
"""
|
|
1084
1241
|
"""
|
|
@@ -1106,6 +1263,62 @@ class ResourceAdvancedProperties:
|
|
|
1106
1263
|
ResourceAdvancedProperties.DELETE = ResourceAdvancedProperties(for_types="")
|
|
1107
1264
|
|
|
1108
1265
|
|
|
1266
|
+
class ValidatorTest:
|
|
1267
|
+
"""
|
|
1268
|
+
Object: representing Polygon validator test
|
|
1269
|
+
"""
|
|
1270
|
+
_INDEX = "index"
|
|
1271
|
+
_INPUT = "input"
|
|
1272
|
+
_EXPECTED_VERDICT = "expectedVerdict"
|
|
1273
|
+
_TESTSET = "testset"
|
|
1274
|
+
_GROUP = "group"
|
|
1275
|
+
|
|
1276
|
+
@classmethod
|
|
1277
|
+
def from_json(cls, validator_test_json):
|
|
1278
|
+
return cls(
|
|
1279
|
+
index=validator_test_json[ValidatorTest._INDEX],
|
|
1280
|
+
input=validator_test_json[ValidatorTest._INPUT],
|
|
1281
|
+
expected_verdict=ValidatorTestVerdict[validator_test_json[ValidatorTest._EXPECTED_VERDICT]],
|
|
1282
|
+
testset=validator_test_json.get(ValidatorTest._TESTSET, None),
|
|
1283
|
+
group=validator_test_json.get(ValidatorTest._GROUP, None),
|
|
1284
|
+
)
|
|
1285
|
+
|
|
1286
|
+
def __init__(self, index, input, expected_verdict, testset=None, group=None):
|
|
1287
|
+
self.index = index
|
|
1288
|
+
self.input = input
|
|
1289
|
+
self.expected_verdict = expected_verdict
|
|
1290
|
+
self.testset = testset
|
|
1291
|
+
self.group = group
|
|
1292
|
+
|
|
1293
|
+
|
|
1294
|
+
class CheckerTest:
|
|
1295
|
+
"""
|
|
1296
|
+
Object: representing Polygon checker test
|
|
1297
|
+
"""
|
|
1298
|
+
_INDEX = "index"
|
|
1299
|
+
_INPUT = "input"
|
|
1300
|
+
_OUTPUT = "output"
|
|
1301
|
+
_ANSWER = "answer"
|
|
1302
|
+
_EXPECTED_VERDICT = "expectedVerdict"
|
|
1303
|
+
|
|
1304
|
+
@classmethod
|
|
1305
|
+
def from_json(cls, checker_test_json):
|
|
1306
|
+
return cls(
|
|
1307
|
+
index=checker_test_json[CheckerTest._INDEX],
|
|
1308
|
+
input=checker_test_json[CheckerTest._INPUT],
|
|
1309
|
+
output=checker_test_json[CheckerTest._OUTPUT],
|
|
1310
|
+
answer=checker_test_json[CheckerTest._ANSWER],
|
|
1311
|
+
expected_verdict=CheckerTestVerdict[checker_test_json[CheckerTest._EXPECTED_VERDICT]],
|
|
1312
|
+
)
|
|
1313
|
+
|
|
1314
|
+
def __init__(self, index, input, output, answer, expected_verdict):
|
|
1315
|
+
self.index = index
|
|
1316
|
+
self.input = input
|
|
1317
|
+
self.output = output
|
|
1318
|
+
self.answer = answer
|
|
1319
|
+
self.expected_verdict = expected_verdict
|
|
1320
|
+
|
|
1321
|
+
|
|
1109
1322
|
class Request:
|
|
1110
1323
|
"""
|
|
1111
1324
|
Request to Polygon API.
|
|
@@ -1150,15 +1363,25 @@ class Request:
|
|
|
1150
1363
|
def issue(self):
|
|
1151
1364
|
"""Issues request and returns parsed JSON response"""
|
|
1152
1365
|
|
|
1153
|
-
|
|
1366
|
+
response_text = self.issue_text()
|
|
1154
1367
|
try:
|
|
1155
|
-
response_json = json.loads(
|
|
1368
|
+
response_json = json.loads(response_text)
|
|
1156
1369
|
except json.decoder.JSONDecodeError as exc:
|
|
1157
1370
|
raise HTTPRequestFailedException(f'Method {self.method_name} has not returned a valid JSON.') from exc
|
|
1158
1371
|
return Response(response_json)
|
|
1159
1372
|
|
|
1373
|
+
def issue_text(self):
|
|
1374
|
+
"""Issues request and returns the response body as text (useful e.g. for scripts and tests)"""
|
|
1375
|
+
|
|
1376
|
+
return self._issue().text
|
|
1377
|
+
|
|
1160
1378
|
def issue_raw(self):
|
|
1161
|
-
"""Issues request and returns
|
|
1379
|
+
"""Issues request and returns the response body as bytes (useful e.g. for packages)"""
|
|
1380
|
+
|
|
1381
|
+
return self._issue().content
|
|
1382
|
+
|
|
1383
|
+
def _issue(self):
|
|
1384
|
+
"""Issues request and returns the requests.Response as is"""
|
|
1162
1385
|
|
|
1163
1386
|
args = list(self.args)
|
|
1164
1387
|
args.append(('apiKey', self.config.api_key))
|
|
@@ -1172,7 +1395,7 @@ class Request:
|
|
|
1172
1395
|
response.raise_for_status()
|
|
1173
1396
|
except requests.exceptions.HTTPError as exc:
|
|
1174
1397
|
raise HTTPRequestFailedException(f'Method {self.method_name} returned HTTP code {response.status_code}') from exc
|
|
1175
|
-
return response
|
|
1398
|
+
return response
|
|
1176
1399
|
|
|
1177
1400
|
def get_api_signature(self, args, api_secret):
|
|
1178
1401
|
rand_bit = Request._value_to_utf8_bytes(''.join(
|
|
@@ -1295,3 +1518,40 @@ class Stage(Enum):
|
|
|
1295
1518
|
|
|
1296
1519
|
def __str__(self):
|
|
1297
1520
|
return self.name
|
|
1521
|
+
|
|
1522
|
+
|
|
1523
|
+
class PackageState(Enum):
|
|
1524
|
+
PENDING = 0
|
|
1525
|
+
RUNNING = 1
|
|
1526
|
+
READY = 2
|
|
1527
|
+
FAILED = 3
|
|
1528
|
+
|
|
1529
|
+
def __str__(self):
|
|
1530
|
+
return self.name
|
|
1531
|
+
|
|
1532
|
+
|
|
1533
|
+
class PackageType(Enum):
|
|
1534
|
+
STANDARD = 0
|
|
1535
|
+
LINUX = 1
|
|
1536
|
+
WINDOWS = 2
|
|
1537
|
+
|
|
1538
|
+
def __str__(self):
|
|
1539
|
+
return self.name.lower()
|
|
1540
|
+
|
|
1541
|
+
|
|
1542
|
+
class ValidatorTestVerdict(Enum):
|
|
1543
|
+
VALID = 0
|
|
1544
|
+
INVALID = 1
|
|
1545
|
+
|
|
1546
|
+
def __str__(self):
|
|
1547
|
+
return self.name
|
|
1548
|
+
|
|
1549
|
+
|
|
1550
|
+
class CheckerTestVerdict(Enum):
|
|
1551
|
+
OK = 0
|
|
1552
|
+
WRONG_ANSWER = 1
|
|
1553
|
+
CRASHED = 2
|
|
1554
|
+
PRESENTATION_ERROR = 3
|
|
1555
|
+
|
|
1556
|
+
def __str__(self):
|
|
1557
|
+
return self.name
|
|
@@ -1,16 +0,0 @@
|
|
|
1
|
-
from .api import (
|
|
2
|
-
Polygon,
|
|
3
|
-
Problem,
|
|
4
|
-
ProblemInfo,
|
|
5
|
-
Statement,
|
|
6
|
-
ResourceAdvancedProperties,
|
|
7
|
-
PolygonRequestFailedException,
|
|
8
|
-
PointsPolicy,
|
|
9
|
-
FeedbackPolicy,
|
|
10
|
-
FileType,
|
|
11
|
-
SolutionTag,
|
|
12
|
-
Stage,
|
|
13
|
-
Asset,
|
|
14
|
-
)
|
|
15
|
-
|
|
16
|
-
__version__ = "1.1.0a2"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|