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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polygon_api
3
- Version: 1.1.0a2
3
+ Version: 1.1.0a3
4
4
  Summary: Python wrapper for Polygon API (polygon.codeforces.com)
5
5
  Home-page: https://github.com/citxx/polygon-py
6
6
  Author: Artem Tabolin
@@ -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 problem_test_input(self, problem_id, testset, test_index):
383
- response = self._request_raw(
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
- response = self._request_raw(
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
- if isinstance(dependencies, list):
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._request_raw(
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._request_raw(
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, source_type, tag, check_existing=None):
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(package) for package in response.result]
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, full, verify):
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, source_type, tag, check_existing=None):
753
- return self._polygon.problem_save_solution(self.id, name, file, source_type, tag, check_existing)
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, packageId, type=None):
792
- return self._polygon.problem_package(self.id, packageId, type)
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, full, verify):
795
- return self._polygon.problem_build_package(self.id, full, verify)
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
- response_raw = self.issue_raw()
1366
+ response_text = self.issue_text()
1154
1367
  try:
1155
- response_json = json.loads(response_raw)
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 raw response (useful e.g. for files)"""
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.content
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,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: polygon_api
3
- Version: 1.1.0a2
3
+ Version: 1.1.0a3
4
4
  Summary: Python wrapper for Polygon API (polygon.codeforces.com)
5
5
  Home-page: https://github.com/citxx/polygon-py
6
6
  Author: Artem Tabolin
@@ -6,7 +6,7 @@ with open("README.md", "r") as fh:
6
6
 
7
7
  setuptools.setup(
8
8
  name="polygon_api",
9
- version="1.1.0a2",
9
+ version="1.1.0a3",
10
10
  author="Artem Tabolin",
11
11
  author_email="artemtab@gmail.com",
12
12
  description="Python wrapper for Polygon API (polygon.codeforces.com)",
@@ -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